BridgeTalk to the rescue!
After asking this question, I've spent days doing research and trial & error to figure out how to get this to work. It seems that the only way to see which colors in a linked EPS file in InDesign is to open that EPS file into Illustrator and check it out there. Thankfully, Adobe has incorporated BridgeTalk into ExtendScript. Thus, I have come up with the following two functions. First, the bridgeToIllustrator function, which takes an EPS file as input and returns an Array to the global variable halftoneInks
:
/**
* The BridgeTalk function that will call Illustrator and run its script,
* returning an array of halftone colors to the variable 'halftoneInks'.
*
* @param {File} oFile The EPS file in which to check for halftone colors.
*/
function bridgeToIllustrator(oFile) {
var resArr = new Array;
var epsFile = oFile.fullName;
// create a new BridgeTalk message object
var bt = new BridgeTalk();
// send this msg to the Adobe Illustrator CS6 application
bt.target = "illustrator-16";
// the script passed to the target application
bt.body = "var sentFile = File(\"" + epsFile + "\");";
bt.body += "var SnpSentMessage = {}; SnpSentMessage.create = " + checkForHalftones.toString();
bt.body += "SnpSentMessage.create(sentFile)";
bt.onResult = function (resObj) {
// use eval to reconstruct the array
resArr = eval(resObj.body);
// and now we can access the returned array
halftoneInks = resArr;
}
bt.onError = function(errObj)
{
$.writeln(errObj.body);
$.writeln(bt.body);
}
// send the message
bt.send(30);
}
The second function is the one that will be passed on to Illustrator, checking every object in the EPS file and adding its fill color or stroke color to an Array if it is a halftone. There might be a better way to write this function, but for now, this works:
/**
* The main part of the script that will run in Illustrator, checking the file for halftones.
*
* @param {File} theFile The file object that will be opened in Illustrator and checked.
*/
function checkForHalftones(theFile) {
var document = app.open(theFile);
var colorsArray = [];
colorsInUse(document.layers[0]);
function colorsInUse(currPageItem) {
for (var i = 0; i < currPageItem.pageItems.length; i++) {
// Stepping through each item on the layer.
var currentItem = currPageItem.pageItems[i];
if (currentItem.typename === "GroupItem" && !currentItem.guides) {
// If it's a group, dig into the group and start the function over.
colorsInUse(currentItem);
} else if (currentItem.typename === "RasterItem") {
if (currentItem.imageColorSpace === ImageColorSpace.CMYK) {
$.writeln("Four-color process image in artwork.");
} else if (currentItem.channels > 1) {
if (currentItem.colorants[0] === "Gray") {
if (colorsArray.toString().indexOf("Black") === -1) {
colorsArray.push("Black");
}
} else {
if (colorsArray.toString().indexOf(currentItem.colorants[0]) === -1) {
colorsArray.push(currentItem.colorants[0]);
}
}
} else {
$.writeln("The raster image in the art file must be a 1-channel bitmap and, thus, does not need to be listed as a halftone.");
}
} else if ((currentItem.fillColor || currentItem.strokeColor) && !currentItem.guides) {
// If the current object has either a fill or a stroke, continue.
var fillColorType = currentItem.fillColor.typename;
var strokeColorType = currentItem.strokeColor.typename;
switch (fillColorType) {
case "CMYKColor":
if (currentItem.fillColor.cyan === 0 && currentItem.fillColor.magenta === 0 && currentItem.fillColor.yellow === 0) {
if (currentItem.fillColor.black === 0) {
break;
} else if (currentItem.fillColor.black === 100) {
break;
} else {
if (colorsArray.toString().indexOf("Black") === -1) {
colorsArray.push("Black");
}
}
} else {
$.writeln("Four color process!");
}
break;
case "GrayColor":
if (currentItem.fillColor.gray > 0 && currentItem.fillColor.gray < 100) {
if (colorsArray.toString().indexOf("Black") === -1) {
colorsArray.push("Black");
}
}
break;
case "SpotColor":
if (currentItem.fillColor.tint < 100) {
if (colorsArray.toString().indexOf(currentItem.fillColor.spot.name) === -1) {
colorsArray.push(currentItem.fillColor.spot.name);
}
}
break;
case "GradientColor":
for (var j = 0; j < currentItem.fillColor.gradient.gradientStops.length; j++) {
var gStop = currentItem.fillColor.gradient.gradientStops[j].color;
switch (gStop.typename) {
case "GrayColor":
if (colorsArray.toString().indexOf("Black") === -1) {
colorsArray.push("Black");
}
break;
case "SpotColor":
if (colorsArray.toString().indexOf(gStop.spot.name) === -1) {
colorsArray.push(gStop.spot.name);
}
break;
case "CMYKColor":
if (gStop.cyan === 0 && gStop.magenta === 0 && gStop.yellow === 0 && gStop.black != 0) {
if (colorsArray.toString().indexOf("Black") === -1) {
colorsArray.push("Black");
}
} else if (gStop.cyan === 0 && gStop.magenta === 0 && gStop.yellow === 0 && gStop.black === 0) {
break;
} else {
$.writeln("Four color process.");
}
break;
default:
$.writeln("Four color process?");
}
}
break;
case "NoColor":
break;
default:
$.writeln("The fill color on object number " + i + " is of type " + fillColorType);
}
switch (strokeColorType) {
case "CMYKColor":
if (currentItem.strokeColor.cyan === 0 && currentItem.strokeColor.magenta === 0 && currentItem.strokeColor.yellow === 0) {
if (currentItem.strokeColor.black === 0) {
break;
} else if (currentItem.strokeColor.black === 100) {
break;
} else {
if (colorsArray.toString().indexOf("Black") === -1) {
colorsArray.push("Black");
}
}
} else {
$.writeln("Four color process!");
}
break;
case "GrayColor":
if (currentItem.strokeColor.gray > 0 && currentItem.strokeColor.gray < 100) {
if (colorsArray.toString().indexOf("Black") === -1) {
colorsArray.push("Black");
}
}
break;
case "SpotColor":
if (currentItem.strokeColor.tint < 100) {
if (colorsArray.toString().indexOf(currentItem.strokeColor.spot.name) === -1) {
colorsArray.push(currentItem.strokeColor.spot.name);
}
}
break;
case "GradientColor":
for (var j = 0; j < currentItem.strokeColor.gradient.gradientStops.length; j++) {
var gStop = currentItem.strokeColor.gradient.gradientStops[j].color;
switch (gStop.typename) {
case "GrayColor":
if (colorsArray.toString().indexOf("Black") === -1) {
colorsArray.push("Black");
}
break;
case "SpotColor":
if (colorsArray.toString().indexOf(gStop.spot.name) === -1) {
colorsArray.push(gStop.spot.name);
}
break;
case "CMYKColor":
if (gStop.cyan === 0 && gStop.magenta === 0 && gStop.yellow === 0 && gStop.black != 0) {
if (colorsArray.toString().indexOf("Black") === -1) {
colorsArray.push("Black");
}
} else if (gStop.cyan === 0 && gStop.magenta === 0 && gStop.yellow === 0 && gStop.black === 0) {
break;
} else {
$.writeln("Four color process.");
}
break;
default:
$.writeln("Four color process?");
}
}
break;
case "NoColor":
break;
default:
$.writeln("The stroke color on object number " + i + " is of type " + strokeColorType);
}
}
}
return;
}
document.close(SaveOptions.DONOTSAVECHANGES);
return colorsArray.toSource();
};
A few key things to note about this set of functions:
- The semicolon at the end is necessary, since the entire function will be turned into a string and sent to Illustrator by way of BridgeTalk. I discovered this the hard way.
- Since any information returned to InDesign from Illustrator is likewise sent as a string, an Array has to be handled carefully. In order to send an Array from Illustrator back to InDesign via BridgeTalk, it will need to be sent with a
.toSource()
method. Then, when BridgeTalk executes the .onResult
callback, you need to use eval()
in order for it to reconstruct the array into something useable for InDesign. Yes, it sucks. Yes, it's necessary. That's just how BridgeTalk functions.
- I had a bear of a time getting the proper syntax for the file to be sent to Illustrator via BridgeTalk. In the end, I discovered that as long as I get the file's
.fullName
, then place that within quotes within the File() constructor within the bt.body
area, it would work. And, of course, to have quotes be interpreted as quotes within quotes, each one must be prepended with a backslash. Whew! Talk about confusing!
Anyway, I hope this has been of help to anyone else out there who needs to learn how to use BridgeTalk between InDesign and Illustrator. Cheers!