Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Applescript: Create logos from list of hex colors and shape layer

Explorer ,
Aug 15, 2009 Aug 15, 2009

I'm trying to write an AppleScript that will create a bunch of PNG files from:

1) A list of hex colors

2) A CS4 Photoshop  file that consists of a single shape layer which uses a logo as a vector mask.

I want to end up with different colored versions of the logo--a red one, a sea foam one, a burnt sienna one, etc. etc.

So far I've got this:

set colorlist to every word of "002266 005566 006611 . . ."

set destinationFolder to "HD:Logos:"

tell application "Adobe Photoshop CS4"

activate

repeat with theCurrentValue in colorlist

--set color of current shape layer of current document to theCurrentValue

set currentFilepath to destinationFolder & theCurrentValue & ".png"

save current document in file  currentFilepath as PNG with options {interlaced:false}

end repeat

end tell


So, how do I change the color of a shape layer?

How do I specify the color as a hex value?

Are these things even possible?

----------------

Finally, is it just me, or is the Adobe documentation incredibly obtuse? Well, maybe that's not the right word. How about "useless." E.g., I searched the script reference for hex, but all I found was this:

RGB hex color

A hexadecimal specification of an RGB color. The RGB hex color class inherits properties from the color

value class.


Properties:

Property             Value                            Type What it is

hex value            Unicode text                   The hex representation of an RGB color

Well, thanks a lot. Sorry to be churlish, but that's a bit like "The copy command copies the selected object.

TOPICS
Actions and scripting
3.7K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Guide , Aug 16, 2009 Aug 16, 2009

This is what I knocked together but Im not sure what Mike recorded as this is not working for me.

I get the saved files but no colour change to the shape layer.

Can't really check until on my work mac where I've got X's tool kit installed.

set Dest_folder to (path to startup disk as text) & "logos:"

set Color_List to {"990000", "005566", "006611"} -- a list

--

tell application "Adobe Photoshop CS2"

activate

set Doc_Ref to the current document

tell Doc_Ref

repeat with This_Value in Color_List

set This_

...
Translate
Adobe
Guru ,
Aug 16, 2009 Aug 16, 2009

I don't use Applescript but I think the guide it trying to note that the returned value of that property is a String. Some expect it to be a Number.

I know that with javascript and VB the only way to change solidfill layer is with scriptlistner. I expect it's the same with Applescript.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 16, 2009 Aug 16, 2009

Thanks, I didn't know about Script Listener. I installed it, recorded a color change, opened the Listener log, turned the contents into a javascript function (change all double quotes to single quotes; add vars, function name and curly brackets; pass AS vars to JS with concatenation), and inserted it into my script (thanks in part to http://forums.adobe.com/thread/433329).

It's ugly, but it works. See below. The only thing left to do is convert a hex color to an RGB color.

I tried:

set currentRGB to convert color theCurrentValue to RGB

but that doesn't work.

Any ideas?

-----------------------

Scripting Listener plug in is located here:

Adobe Photoshop CS4:Scripting:Utilities

To install, move here:

Adobe Photoshop CS4:Plug-Ins:Automate

Also useful: Adobe Intro to Scripting which is buried here:

Applications:Utilities:Adobe Utilities:ExtendScript Toolkit CS4:SDK:English:Adobe Intro to Scripting

--------------------

set colorlist to every word of "002266 005566 006611 . . ."

set destinationfolder to "HD:logos:"

tell application "Adobe Photoshop CS4"

activate

repeat with theCurrentValue in colorlist

set currentRGB to convert color theCurrentValue to RGB --THIS LINE DOESN'T WORK

set currentRed to red of currentRGB

set currentGreen to green of currentRGB

set currentBlue to blue of currentRGB

do javascript "ChangeShapeColor(" & currentRed & "," & currentGreen & "," & currentBlue & ");

// =======================================================

function ChangeShapeColor(NewRed, NewGreen, NewBlue)

{

var idsetd = charIDToTypeID( 'setd' );

    var desc5 = new ActionDescriptor();

    var idnull = charIDToTypeID( 'null' );

        var ref2 = new ActionReference();

        var idcontentLayer = stringIDToTypeID( 'contentLayer' );

        var idOrdn = charIDToTypeID( 'Ordn' );

        var idTrgt = charIDToTypeID( 'Trgt' );

        ref2.putEnumerated( idcontentLayer, idOrdn, idTrgt );

    desc5.putReference( idnull, ref2 );

    var idT = charIDToTypeID( 'T   ' );

        var desc6 = new ActionDescriptor();

        var idClr = charIDToTypeID( 'Clr ' );

            var desc7 = new ActionDescriptor();

            var idRd = charIDToTypeID( 'Rd  ' );

            desc7.putDouble( idRd, NewRed );

            var idGrn = charIDToTypeID( 'Grn ' );

            desc7.putDouble( idGrn, NewGreen );

            var idBl = charIDToTypeID( 'Bl  ' );

            desc7.putDouble( idBl, NewBlue );

        var idRGBC = charIDToTypeID( 'RGBC' );

        desc6.putObject( idClr, idRGBC, desc7 );

    var idsolidColorLayer = stringIDToTypeID( 'solidColorLayer' );

    desc5.putObject( idT, idsolidColorLayer, desc6 );

executeAction( idsetd, desc5, DialogModes.NO );

};" show debugger on runtime error

set currentFilepath to destinationfolder & theCurrentValue & "png"

save current document in file theCurrentValue as PNG with options {interlaced:false}

end repeat

end tel

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Aug 16, 2009 Aug 16, 2009

Send the javascript the hex value you want as a string. The function below will accept a string.

///////////////////////////////////////////////////////////////////////////////
// Function:  colorToSolidColorLayer
// Description: Sets color of active layer solidColor
// Usage: colorToSolidColorLayer( [ 72, 50.6, 45.45 ] );
// Input: Color as one of String, Array, or SolidColor
// Return: -1 if fails
// Notes: Use Array for 16bit color. Both String and
//              SolidColor  are 8bit.
///////////////////////////////////////////////////////////////////////////////
function colorToSolidColorLayer( color ){
     var arg = arguments[0].constructor;
     switch( arg ){
          case Array:
               var c =  color;
               break;
          case SolidColor:
               var c = new Array();
               c.push( color.rgb.red );
               c.push( color.rgb.green );
               c.push( color.rgb.blue );
               break;
          case String:
               var c = new Array();
               var sc = new SolidColor();
               sc.rgb.hexValue = color;
               c.push( sc.rgb.red );
               c.push( sc.rgb.green );
               c.push( sc.rgb.blue );
               break;
          default:
               return -1;
     }
     try{
          var desc = new ActionDescriptor();
               var ref = new ActionReference();
               ref.putEnumerated( stringIDToTypeID( "contentLayer" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
          desc.putReference( charIDToTypeID( "null" ), ref );
               var modeDesc = new ActionDescriptor();
                    var colorDesc = new ActionDescriptor();
                    colorDesc.putDouble( charIDToTypeID( "Rd  " ), c[ 0 ] );
                    colorDesc.putDouble( charIDToTypeID( "Grn " ), c[ 1 ] );
                    colorDesc.putDouble( charIDToTypeID( "Bl  " ), c[ 2 ] );
               modeDesc.putObject( charIDToTypeID( "Clr " ), charIDToTypeID( "RGBC" ), colorDesc );
          desc.putObject( charIDToTypeID( "T   " ), stringIDToTypeID( "solidColorLayer" ), modeDesc );
          executeAction( charIDToTypeID( "setd" ), desc, DialogModes.NO );
          }catch(e){ return -1; }
}

EIther that or convert the 3 hex pairs to 3 decimal numbers if that is possible in Applescript.

Edit: I hate the way this forum mangles code. Remove all the & ndsp;

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 16, 2009 Aug 16, 2009

I couldn't get the script you posted to work with anything but RGB arrays, so I converted the hex to decimal (modified a subroutine I found here: http://osdir.com/ml/editors.bbedit.general/2006-06/msg00020.html).

I haven't analyzed the subroutine to make sure it gives the correct values, but that can be adjusted later.

For now, the only remaining problem is that the save statements at the end of the script don't work. Instead, Photoshop's save dialogs pop up. What am I doing wrong?

set colorlist to every word of "990000 005566 006611"

set destinationfolder to "HD:logos:"

on fromHex(hexstring, channel)

set charactarlist to every character of hexstring

if channel = "red" then

set firstdigit to item 1 of charactarlist

set seconddigit to item 2 of charactarlist

else if channel = "green" then

set firstdigit to item 3 of charactarlist

set seconddigit to item 4 of charactarlist

else if channel = "blue" then

set firstdigit to item 5 of charactarlist

set seconddigit to item 6 of charactarlist

end if

set str to firstdigit & seconddigit

set n to 0

set i to 1

repeat with a in reverse of every text item of str

if a is greater than 9 or a is less than 0 then

set a to ASCII number of a

if a is greater than 70 then

set a to a - 87

else

set a to a - 55

end if

end if

set n to n + a * i

set i to i * 16

end repeat

return n

end fromHex

tell application "Adobe Photoshop CS4"

activate

repeat with theCurrentValue in colorlist

set currentRed to my fromHex(theCurrentValue, "red")

set currentGreen to my fromHex(theCurrentValue, "green")

set currentBlue to my fromHex(theCurrentValue, "blue")

do javascript "ChangeShapeColor(" & currentRed & "," & currentGreen & "," & currentBlue & ");

function ChangeShapeColor(NewRed, NewGreen, NewBlue)

{      

var idsetd = charIDToTypeID( 'setd' );

    var desc5 = new ActionDescriptor();

    var idnull = charIDToTypeID( 'null' );

        var ref2 = new ActionReference();

        var idcontentLayer = stringIDToTypeID( 'contentLayer' );

        var idOrdn = charIDToTypeID( 'Ordn' );

        var idTrgt = charIDToTypeID( 'Trgt' );

        ref2.putEnumerated( idcontentLayer, idOrdn, idTrgt );

    desc5.putReference( idnull, ref2 );

    var idT = charIDToTypeID( 'T   ' );

        var desc6 = new ActionDescriptor();

        var idClr = charIDToTypeID( 'Clr ' );

            var desc7 = new ActionDescriptor();

            var idRd = charIDToTypeID( 'Rd  ' );

            desc7.putDouble( idRd, NewRed );

            var idGrn = charIDToTypeID( 'Grn ' );

            desc7.putDouble( idGrn, NewGreen );

            var idBl = charIDToTypeID( 'Bl  ' );

            desc7.putDouble( idBl, NewBlue );

        var idRGBC = charIDToTypeID( 'RGBC' );

        desc6.putObject( idClr, idRGBC, desc7 );

    var idsolidColorLayer = stringIDToTypeID( 'solidColorLayer' );

    desc5.putObject( idT, idsolidColorLayer, desc6 );

executeAction( idsetd, desc5, DialogModes.NO );

};" show debugger on runtime error

set currentFilepath to destinationfolder & theCurrentValue & "png"

set saveOptions to {class:PNG save options, interlaced:false}

save current document in file currentFilepath as PNG with options saveOptions appending no extension with copying

end repeat

end tell

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Aug 16, 2009 Aug 16, 2009

Sorry, as I said I don't know Applescript so I did not know that my function would not work for you. I would guess that it has something to do with the way arguments are passed. But I'm glad you got that part working.

Hopefully someone will post a fix for you save problem soon.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Aug 16, 2009 Aug 16, 2009

If it helps both the applescript guide and the save sample script have a 'tell finder' line that I don't see in your code.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 16, 2009 Aug 16, 2009

Turns out it was working fine. I just made a stupid mistake and had the destination folder on the desktop instead of the hard drive. Again, thanks for your help on this.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Aug 16, 2009 Aug 16, 2009

Joe, you were passing Photoshop a 6 character string and it wants a little more info than that does this work for you?

tell application "Adobe Photoshop CS2"

activate

set This_RGB to convert color {class:RGB hex color, hex value:"006611"} to RGB

end tell

This_RGB

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 16, 2009 Aug 16, 2009

That's much prettier. The script is now:

. . .

repeat with theCurrentValue in colorlist

set currentRGB to convert color {class:RGB hex color, hex value:theCurrentValue} to RGB

set currentRed to red of currentRGB

set currentGreen to green of currentRGB

set currentBlue to blue of currentRGB

do javascript "ChangeShapeColor(" & currentRed & "," & currentGreen & "," & currentBlue & ");

. . .

Now that I see it the syntax, the entry in the reference make sense.  I suppose a better understanding of OOP would have led me to that solution in the first place, but it wouldn't kill the writers of the reference to put a single example after each section to make it a bit easier for non-programmers. I mean, it's AppleSCRIPT, not C.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Aug 16, 2009 Aug 16, 2009

This is what I knocked together but Im not sure what Mike recorded as this is not working for me.

I get the saved files but no colour change to the shape layer.

Can't really check until on my work mac where I've got X's tool kit installed.

set Dest_folder to (path to startup disk as text) & "logos:"

set Color_List to {"990000", "005566", "006611"} -- a list

--

tell application "Adobe Photoshop CS2"

activate

set Doc_Ref to the current document

tell Doc_Ref

repeat with This_Value in Color_List

set This_RGB to convert color {class:RGB hex color, hex value:This_Value} to RGB

set {R, G, B} to {red of This_RGB, green of This_RGB, blue of This_RGB}

do javascript "colorToSolidColorLayer( " & R & ", " & G & ", " & B & " );

function colorToSolidColorLayer( color ){

     var arg = arguments[0].constructor;

     switch( arg ){

          case Array:

               var c =  color;

               break;

          case SolidColor:

               var c = new Array();

               c.push( color.rgb.red );

               c.push( color.rgb.green );

               c.push( color.rgb.blue );

               break;

          case String:

               var c = new Array();

               var sc = new SolidColor();

               sc.rgb.hexValue = color;

               c.push( sc.rgb.red );

               c.push( sc.rgb.green );

               c.push( sc.rgb.blue );

               break;

          default:

               return -1;

     }

     try{

          var desc = new ActionDescriptor();

               var ref = new ActionReference();

               ref.putEnumerated( stringIDToTypeID( 'contentLayer' ), charIDToTypeID( 'Ordn' ), charIDToTypeID( 'Trgt' ) );

          desc.putReference( charIDToTypeID( 'null' ), ref );

               var modeDesc = new ActionDescriptor();

                    var colorDesc = new ActionDescriptor();

                    colorDesc.putDouble( charIDToTypeID( 'Rd  ' ), c[ 0 ] );

                    colorDesc.putDouble( charIDToTypeID( 'Grn ' ), c[ 1 ] );

                    colorDesc.putDouble( charIDToTypeID( 'Bl  ' ), c[ 2 ] );

               modeDesc.putObject( charIDToTypeID( 'Clr ' ), charIDToTypeID( 'RGBC' ), colorDesc );

          desc.putObject( charIDToTypeID( 'T   ' ), stringIDToTypeID( 'solidColorLayer' ), modeDesc );

          executeAction( charIDToTypeID( 'setd' ), desc, DialogModes.NO );

          }catch(e){ return -1; }

}" show debugger on runtime error

set File_Path to Dest_folder & This_Value & ".png"

save in file File_Path as PNG with options ¬

{class:PNG save options, interlaced:false} ¬

appending no extension with copying

end repeat

end tell

end tell

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Aug 16, 2009 Aug 16, 2009

MM--What I have is working, so no need to go further with this unless you just want to clean up the script for the heck of it and for any future users .

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Aug 17, 2009 Aug 17, 2009

Well I had a look at script listeners output and it was exactly the same as Mikes. When I cut down the code to this it works just fine.

set Dest_folder to (path to startup disk as text) & "logos:"

set Color_List to {"990000", "005566", "006611"} -- a list

--

tell application "Adobe Photoshop CS2"

activate

set Doc_Ref to the current document

tell Doc_Ref

repeat with This_Value in Color_List

set This_RGB to convert color {class:RGB hex color, hex value:This_Value} to RGB

set {R, G, B} to {red of This_RGB, green of This_RGB, blue of This_RGB}

do javascript "colorToSolidColorLayer();

function colorToSolidColorLayer( color ){

          var desc = new ActionDescriptor();

               var ref = new ActionReference();

               ref.putEnumerated( stringIDToTypeID( 'contentLayer' ), charIDToTypeID( 'Ordn' ), charIDToTypeID( 'Trgt' ) );

          desc.putReference( charIDToTypeID( 'null' ), ref );

               var modeDesc = new ActionDescriptor();

                    var colorDesc = new ActionDescriptor();

                    colorDesc.putDouble( charIDToTypeID( 'Rd  ' )," & R & ");

                    colorDesc.putDouble( charIDToTypeID( 'Grn ' )," & G & ");

                    colorDesc.putDouble( charIDToTypeID( 'Bl  ' )," & B & ");

               modeDesc.putObject( charIDToTypeID( 'Clr ' ), charIDToTypeID( 'RGBC' ), colorDesc );

          desc.putObject( charIDToTypeID( 'T   ' ), stringIDToTypeID( 'solidColorLayer' ), modeDesc );

          executeAction( charIDToTypeID( 'setd' ), desc, DialogModes.NO );}" show debugger on runtime error

set File_Path to Dest_folder & This_Value & ".png"

save in file File_Path as PNG with options ¬

{class:PNG save options, interlaced:false} ¬

appending no extension with copying

end repeat

end tell

end tell

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Aug 17, 2009 Aug 17, 2009

Hi Mark, if it's not too much trouble would you mind doing a test for me to see why my function doesn't work with Applescript?

It takes only one argument. That can be a string or an array or a solidColor object. I wouldn't expect solidColor to work, the Applescript guide doesn't seem to list solidColor.

With javascript the function would be called like this

colorToSolidColorLayer( [255,255,255] );

or
colorToSolidColorLayer( "a10000" );

For the test I would like you to add the following to the top of the function

alert("The number of argument(s): " + arguments.length + "\rFirst
argument: " + arguments[0] + "\rArgument class : " +
arguments[0].constructor );

Thanks,

Mike

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Aug 17, 2009 Aug 17, 2009

Mike, I will go back and run a check. From a quick glance though it looks like I've forgot the JS array [] from the function call. (thats why I've got the muppet handle)

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Aug 17, 2009 Aug 17, 2009

Yep the typo was my doing… doh! When breaking up the call to pass the AppleScript variables into the function I forgot the array brackets…

I had…

colorToSolidColorLayer( " & R & ", " & G & ", " & B & " );

should have been…

colorToSolidColorLayer( [" & R & ", " & G & ", " & B & "] );

It does work with the string too. But then I knew it would

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Aug 17, 2009 Aug 17, 2009
LATEST

Thanks for the testing. I knew it worked with javascript but I was worried that when Applescript passed the argument my constructor switch fails for some reason.

Looking back over this thread maybe I should have been clearer on how to call the function when I first posted it.

Thanks again,

Mike

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines