Hexadecimal Swatches in InDesign

On Thursday, David Blatner sent me an email asking how difficult it would be to create a script which would create swatches in InDesign from hex values.

It was not too difficult, and proved to be a nice distraction from “real” work… ;)

Before reading further, make sure you get the script here!

I couldn’t sit down to work on it until Saturday night, and by Sunday afternoon I was basically done. But I used quite a few interesting scripting features along the way…

Script vs Plugin

David wanted to know if it would be possible to hack into the standard New Swatch dialog to add the ability to create the hex colors there. I looked into the SDK a bit to try to find that answer. I came to the conclusion that it probably could be done, but the relevant APIs are not really documented, so it would require a considerable amount of reverse-engineering work to figure out how to go about it. Not a job for “between real work”… :D

Once that option was out, there was no real benefit to going through the (considerable!) added effort of doing this add-on as a plugin instead of a script.

Dialogs vs Palettes

David asked for me to include an “Add” button which allows for the creation of swatches without closing the dialog. Adding swatches requires modifying the application or document model. Script UI dialogs are what is called “modal dialogs” meaning it locks out the user from interacting with the application. Unfortunately, it not only locks out the user, but the scripting interface as well. Script UI is somewhat of a second-class citizen when compared to true plugins (which can change things in the application even when a modal dialog is active). I actually asked an engineer at Adobe why this limitation is there. Flash modal dialogs do not have this limitation. The response was that it was probably an oversight! :( Maybe one day that oversight will be corrected…

Well, back to the subject at hand: Since I needed to modify things, I needed to create the dialog as a “palette” instead of a dialog. This has the interesting side-effect that you can leave it open while you continue to work…

BridgeTalk and Photoshop

David asked me to offer the ability to grab the current foreground color in Photoshop. This might sound hard, but BridgeTalk actually makes this quite easy. This is all the code required to do that:

function getPhotoshopForeground(){
 var psColor;
 var bt = new BridgeTalk;
 bt.target = 'photoshop';
 bt.body = "app.foregroundColor.rgb.hexValue;";
 bt.onResult = function(resObj) {
  if(resObj.body){
   d.updateAllValues(resObj.body);
  }
 }
 bt.send();
}

The way this code works is really very simple:

  1. We create a new BridgeTalk object.
  2. We set the target (Photoshop).
  3. We give the BridgeTalk object body code. This code will execute inside Photoshop and since I did not assign the result of that evaluation, the evaluation of that code (i.e. our needed hex value) will be the script result. This script result is what you would see if the script is executed in the ESTK or in Script Bay for that matter. When it is executed as a BridgeTalk message, BridgeTalk returns that result in a Result object.
  4. We define the onResult function which tells our BridgeTalk messaging system what to do with the result (in our case update the dialog based on the new hex values). Once we define this, the onResult will run automatically when Photoshop finishes doing its thing and returns the result. Since our BridgeTalk script is really quite simple, that happens nearly instantaneously. In more complicated scripts there can be a significant pause before you get the result back. BridgeTalk works asynchronously, so the sender app can continue doing its thing…
  5. We just send the BridgeTalk object.

The only other aspect of BridgeTalk I used here was enabling the button based on the current status of Photoshop. That was very simple as well:

function getPhotoshopActive(){
 var status = BridgeTalk.getStatus("photoshop");
 if(status == "IDLE" || status == "BUSY" ||status == "PUMPING"){
  return true;
 }
 return false;
}

Hex Conversions

The actual conversion was done by some pretty simple functions. The web is literally covered with javascript functions for conversion between Hex an RGB. The nice thing about using ExtendScript for scripting the CS apps, is you have a huge resource of readily available code!

The conversions I needed for this script were as follows:

  1. Hex to RGB
  2. RGB to Hex
  3. RGB to color name
  4. Color name to RGB
  5. RGB to CMYK approximation (which is a very simple function using ridiculously strong GCR…)
  6. Hex literal to Hex numeric values (to pass into the colorPicker — which takes an returns numbers and not strings)
  7. Hex numeric to Hex literal (to get the values out of the colorPicker)

Of all these functions, the only ones I did not find on the web were the color name conversions. For that I simply used two separate json objects. One used the color name as a key for the RGB values, and the other used the RGB values as a key for the names. This simple lookup is quite fast, and the values in the dialog update instantly.

The Color Picker

The Color picker area is actually comprised of two separate pieces. The sliders I simply took almost as-is from a really cool sample script which comes with the ExtendScript Toolkit (ColorPicker.jsx). I needed to change a number of aspects to make it work the way I wanted, but that ready-made script really made life easy!

The other part is the OS color picker which is called up when you click on the color swatch button. That is done by simply using the $.colorPicker() function built into ExtendScript. Easy Peasy! :)

Getting/Setting InDesign Values

The next issue is getting the RGB values out of InDesign and actually creating the swatches. Getting the current color is easy:

var fillColor = app.strokeFillProxySettings.fillColor;

The problem is that the active color might not be RGB. Unlike Photoshop, you can’t ask InDesign for RGB values of a CMYK color. The solution is to change the current color to RGB, and grab the values before you change it back to CMYK. There is two problems with that:

  1. That adds an “undo” to InDesign’s undo stack.
  2. When you change CMYK to RGB and back again, the values are almost guaranteed (maybe 100% guaranteed?) to change.

Problem #2 can be solved by saving the CMYK values before you change the color to RGB and then resetting them. However, this just makes problem #1 even bigger, because you have even more undo steps. However, in CS4 and later, problem #1 can be elegantly solved by using UndoModes. UndoModes allow scripts to specify how script actions appear in the undo stack (similar to the functionality available to plugins). One of the UndoModes is UndoModes.AUTO_UNDO. This attaches the script action(s) to the previously executed action and does not appear in the undo stack at all. Yes! 8)

Creating the swatches is as simple as:

var addedColor = appOrDoc.colors.add({space:ColorSpace.RGB,colorValue:d.rgb});
try{
 if(d.colorName.text !=""){
  addedColor.name = d.colorName.text;
 } else {
  addedColor.name = d.hexText.text;
 }
}catch(err){
 alert("There's already another swatch with the same name...");
}
if(d.cmykSpace.value){//CMYK
 addedColor.space = ColorSpace.CMYK;
} else if(d.labSpace.value){//LAB
  addedColor.space = ColorSpace.LAB;
}

We just create the swatch, try to name it, and then convert the color space if necessary. Of course this is all wrapped inside a UndoModes.ENTIRE_SCRIPT to make it all nice and tidy… :)

That (and about a total of 1100 lines of code including all the UI stuff) is about all there is to creating this cool script!

Tags: , , ,

12 Comments

  1. Jeff says:

    Thanks so much for this! Just downloaded and can’t wait to put it to use. Been needing hex colors in Indesign for quite awhile now, we use the app for a lot of our wireframing and comping needs.

    Cheers!

  2. Robbie Kelly says:

    Great. Just what I needed. Many thanks.
    R

  3. Brandon says:

    This script is AWESOME! thanks so much! I can’t believe Adobe left this feature out of their version. It seems like such an oversight. With your script, my project just got a whole lot easier. Bless You!

  4. todd says:

    crashes my cs5 version of indesign when I use the plugin rather than the script. also, the new hex swatch doesn’t allow me to add a numerical hex value to create a new swatch. It will only pull from the foreground color.

  5. Susan says:

    Oops, posted that in a reply. Will this script work in CS6?

  6. Guz says:

    Crashes my inDesign CS5.5 everytime I click on the “new Hex swatch”… Pitty, it’s seemed an excelent option for hex colors.

  7. Greg says:

    Does not work in CS6. Darn.

  8. Nancy Wirsig McClure says:

    The script works great in InDesign CS6. It’s easy to use (which was a relief to me after I read the intimidating “under the hood” material above).

    It is installed using Extension Manager. There are clear and simple instructions in the ReadMe file inside the zip (way better than average instructions!)

    May I suggest that my previous paragraph be added at the top of the post, next to the download link?

    I am very happy this is here.

  9. Frank says:

    Works fine in InDesign CC.

  10. Kevin says:

    YOU RULE!!!

    Just a couple notes for other designers:

    • Instructions are in ZIP. Easy Peesy.
    • I had to install manually in InD CC (Ex Manager no worky)
    • You can’t find the option in the other color pallets just swatches

    I can’t understand for the life of me why adobe would not include HEX and HSB controls in InD… They must be aware that a lot of web and mobile designers are using this for layout and style guides and need those features. PUT THEM IN ALREADY!!! IT’S 2013!!! WE SHOULD HAVE HAD FLYING CARS BY NOW!!! HEX and HSB is not a lot to ask for ;)

Leave feedback