Copy link to clipboard
Copied
Hi All!
So, a question regarding the failry well known fab Script written by John Wundes:
I need to create a chart that specifies just the LAB values underneith the swatches that the script creates, but curiously, the LAB values that the script produces are always wrong - they're always out by a digit and I don't know why.
If I double click the swatch in the swatch palette, the LAB value is correct/as it should be, it is just the text that the script produces and lays onto the artboard that is incorrect. Please see following image. Any ideas why this glitch is happening?
This glitch happens consistently on every single import - the lab value that the script generates onto the artboard is never the correct value. Help!
Copy link to clipboard
Copied
ALSO - I forgot to add, does anyone know what the G number is (below the LAB values?)
Copy link to clipboard
Copied
Most likely Gray scale on a 0-10 range.
Copy link to clipboard
Copied
Thanks larry!
Do you know if it is necessary to display this value along with LAB? (If I have to show LAB that is)
Copy link to clipboard
Copied
I don't think the script is correct in showing the Lab values.
It looks like it is showing the Lab values of the color when it is converted to CMYK.
Copy link to clipboard
Copied
Argh! IF so, that is super frustrating. LAB values are the most accurate print values there are, so it's crucial they match.
What is puzzling to me though, is that the script does any conversions at all - WHY???????
It should just be extracting the actual data from the swatch, so why is it changing numerical values at all?
The actual swatch values are exacting, certainly from Pantones. So why does the script then start to Ãnterpret' them? Makes no sense at all.
Copy link to clipboard
Copied
we don't have access to LAB values in the scripting API, that's the reason conversion was needed
Copy link to clipboard
Copied
An Book Color, Carlos, is that available in scripting?
Copy link to clipboard
Copied
The Scripting API recognizes Pantone Colors as SpotLAB, but when we dig down to get the actual color values we get either CMYK or RGB according to your Document Color Mode.
Copy link to clipboard
Copied
It comes down to rounding, decimals get lost from Pantone to CMYK (or RGB) then to LAB.
Copy link to clipboard
Copied
I’m not sure that is correct. Rounding would make sense if there were half values etc but this isn’t the case.
On every single imported swatch - I.e on every swatch the script runs through and presents on the art board, the values are always one digit more out, without fail. The L value often remains the same, but the A B Values are always off by one digit. This isn’t rounding, there’s something going wrong.
Copy link to clipboard
Copied
It is not rounding.
A Pantone color cannot be reproduced in CMYK, that's why it is a special mixed ink.
But Lab can describe any color we can see.
When you convert from Lab to CMYK you will lose color information
When you convert it back to Lab, you will never get the original values back.
Copy link to clipboard
Copied
Thanks for the input, but I'm getting completely lost and baffled here.
why is the script doing any conversions of anything? I'm not sure if I have explained the problem correctly here.
I'll try br clearer.
when the script runs, it is placing the swatch on the art board - this is absolutely fine, I can select that placed square of colour that the script creates and then open up its swatch values by double clicking the actual swatch in the swatches palette - the values are all correct, LAB values also.
The problem is nothing to do with the swatch or the colour itself.
the problem, is the text that the script is placing onto the swatch. The LAB value in the text in creates, does not match up with the lab value of the actual swatch.
Something funky is happening with the script that is extrapolating the LAB value from the swatches, it is deleting digits and then creating the overlay text. There is nothing wrong with the color/swatch itself, just the overlaid text info.
is that clearer?
Copy link to clipboard
Copied
it's been clear since the very start Nathan, what I'm trying to tell you is that the LAB values you see in the UI are not accessible to scripting. The Scripting API provides a conversion method, we get the values in CMYK or RGB then we convert them to LAB. That's where the rounding comes from.
Copy link to clipboard
Copied
Hi Carlos, yes sorry - all is clear now, I understand what is happening.
I've never understood why Illustrator doesn't display LAB natively, but this is obviously why the script is needing to take the cmyk/RGB data and then produce the Lab value (That is slightly different).
Makes sense to me now, thank you for explaining and repeating this to me.
Copy link to clipboard
Copied
Knowing what we know now, the script will only give correct values for CMYK swatches in a CMYK document an RGB swatches in an RGB document. All other values are calculated using the current color settings.
Copy link to clipboard
Copied
The plot thickens!
My problem is that I download my pantones from Pantone Colour Manager as 'LAB' swatches - I can only download as either LAB or sRGB and this is for textile printing.
My file is set up using Adobe RGB space as I'm digitally printing fabric.
Long story short, the LAB value that the script creates and writes out is never going to be precise, so in my user case, I'll just have to use the RGB values that the script writes out - if I'm thinking this through correctly, those RGB values the script writes out should be correct?
Copy link to clipboard
Copied
Yes as far as I can conclude, the RGB values that the script gives you are the same values you would get when you open the Pantone swatch and manually switch to RGB.
Copy link to clipboard
Copied
hmmm. there might be hope, let me make some testing...The plot thickens!
Copy link to clipboard
Copied
Yes, the plot is getting very thick!
Let me add to my latest reply: the RGB values that the script gives you are the same values you would get when you open the Pantone swatch and manually switch to RGB: In an RGB document.
Copy link to clipboard
Copied
try this updated version
/////////////////////////////////////////////////////////////////
// Render Swatch Legend v1.3 -- CC
//>=--------------------------------------
//
// This script will generate a legend of rectangles for every swatch in the main swatches palette.
// You can configure spacing and value display by configuring the variables at the top
// of the script.
// update: v1.1 now tests color brightness and renders a white label if the color is dark.
// update: v1.2 uses adobe colour converter, rather than rgb colour conversion for a closer match.
// update: v1.3 adds multiple colour space values based on array printColors.
// LAB values by Carlos Canto - 09/16/2020
// reference: https://community.adobe.com/t5/illustrator/illustrator-javascript-render-swatch-legend-lab-colour-values-incorrect/m-p/11438710?page=2#M244722
//>=--------------------------------------
// JS code (c) copyright: John Wundes ( john@wundes.com ) www.wundes.com
// copyright full text here: http://www.wundes.com/js4ai/copyright.txt
//
// Edits by Adam Green (@wrokred) www.wrokred.com
//////////////////////////////////////////////////////////////////
doc = activeDocument,
swatches = doc.swatches,
cols = 4, // number of columns in group
displayAs = "RGBColor", //or "CMYKColor"
printColors = ["RGB", "CMYK", "LAB", "GrayScale"], // RGB, CMYK, LAB and/or GrayScale
colorSeparator = " ", // Character used to separate the colours eg "|" output = R: XXX|G: XXX|B: XXX
textSize = 10, // output text size value in points
rectRef = null,
textRectRef = null,
textRef = null,
swatchColor = null,
w = 150;
h = 120,
h_pad = 10,
v_pad = 10,
t_h_pad = 10,
t_v_pad = 10,
x = null,
y = null,
black = new GrayColor(),
white = new GrayColor();
black.gray = 100;
white.gray = 0;
activeDocument.layers[0].locked = false;
var newGroup = doc.groupItems.add();
newGroup.name = "NewGroup";
newGroup.move(doc, ElementPlacement.PLACEATBEGINNING);
for (var c = 2, len = swatches.length; c < len; c++) {
var swatchGroup = doc.groupItems.add();
swatchGroup.name = swatches[c].name;
x = (w + h_pad) * ((c - 2) % cols);
y = (h + v_pad) * (Math.round(((c) + .03) / cols)) * -1;
rectRef = doc.pathItems.rectangle(y, x, w, h);
swatchColor = swatches[c].color;
rectRef.fillColor = swatchColor;
textRectRef = doc.pathItems.rectangle(y - t_v_pad, x + t_h_pad, w - (2 * t_h_pad), h - (2 * t_v_pad));
textRef = doc.textFrames.areaText(textRectRef);
textRef.contents = swatches[c].name + "\r" + getColorValues(swatchColor);
textRef.textRange.fillColor = is_dark(swatchColor) ? white : black;
textRef.textRange.size = textSize;
rectRef.move(swatchGroup, ElementPlacement.PLACEATBEGINNING);
textRef.move(swatchGroup, ElementPlacement.PLACEATBEGINNING);
swatchGroup.move(newGroup, ElementPlacement.PLACEATEND);
}
function getColorValues(c, spot) {
if (c.typename) {
if (c.typename == "SpotColor") {
return getColorValues(c.spot.color, c.spot);
};
switch (c.typename) {
case "RGBColor":
sourceSpace = ImageColorSpace.RGB;
colorComponents = [c.red, c.green, c.blue];
break;
case "CMYKColor":
sourceSpace = ImageColorSpace.CMYK;
colorComponents = [c.cyan, c.magenta, c.yellow, c.black];
break;
case "LabColor":
sourceSpace = ImageColorSpace.LAB;
colorComponents = [c.l, c.a, c.b];
break;
case "GrayColor":
sourceSpace = ImageColorSpace.GrayScale;
colorComponents = [c.gray];
break;
}
var outputColors = new Array();
for (var i = printColors.length - 1; i >= 0; i--) {
targetSpace = ImageColorSpace[printColors[i]];
if (printColors[i] == 'LAB' && spot && spot.spotKind == 'SpotColorKind.SPOTLAB') {
outputColors[i] = spot.getInternalColor();
}
else {
outputColors[i] = app.convertSampleColor(sourceSpace, colorComponents, targetSpace, ColorConvertPurpose.previewpurpose);
}
for (var j = outputColors[i].length - 1; j >= 0; j--) {
outputColors[i][j] = printColors[i].charAt(j) + ": " + Math.round(outputColors[i][j]);
if (j == outputColors[i].length - 1) {
outputColors[i][j] += "\r";
};
};
outputColors[i] = outputColors[i].join(colorSeparator);
};
return outputColors.join("");
}
return "Non Standard Color Type";
}
function is_dark(c) {
if (c.typename) {
switch (c.typename) {
case "CMYKColor":
return (c.black > 50 || (c.cyan > 50 && c.magenta > 50)) ? true : false;
case "RGBColor":
return (c.red < 100 && c.green < 100) ? true : false;
case "GrayColor":
return c.gray > 50 ? true : false;
case "SpotColor":
return is_dark(c.spot.color);
return false;
}
}
}
Copy link to clipboard
Copied
You did it!
The Lab values are exactly the same as the ones from the Pantone swatch.
And in an RGB document the RGB colors are the same as the conversion you see when you select RGB in the Color panel or in the Swatch options.
Same for the CMYK conversion in a CMYK document.
But CMYK or Gray numbers are totally different from the conversion you would expect when you selected them in an RGB document and RGB and Gray are different in a CMYK document. I wonder where that comes from.
Copy link to clipboard
Copied
Hi Ton thanks so much for your input and testing, it's so helpful.
what do you mean exactly in your last sentence there? Could you possibly do a screen shot to explain?
thanks in advance
Copy link to clipboard
Copied
I cannot WAIT to try this in the morning!
You absolute star Carlos, thanks a million if this works - which judging by Ton's input below, it does!
You have both been incredibly helpful thank you thank you
Copy link to clipboard
Copied
A small edit i would make is adjust #23
swatches = doc.swatches
to get only selected
swatches = doc.swatches.getSelected()
EDIT 2 - Added HEX code
I made another edit, it now also outputs HEX code. This one was a bit tricky. code is not as clean. But im no pro at this
EDIT 3 - Split color componenten yes/no
Okay last feature, added an option to split by color component or show color component as name then all the values. If you adjust the bool splitColorComponents. I did add 2 function from a different script. This was needed todo the convert from CMYtoRGB. I think i can get rif od it, part of that looks the same function already in this script. It now also works when you have a CMYK document, it still returns the HEX value
/////////////////////////////////////////////////////////////////
// Render Swatch Legend v1.4.4 -- CC
//>=--------------------------------------
//
// This script will generate a legend of rectangles for every swatch in the main swatches palette.
// You can configure spacing and value display by configuring the variables at the top
// of the script.
// update: v1.1 now tests color brightness and renders a white label if the color is dark.
// update: v1.2 uses adobe colour converter, rather than rgb colour conversion for a closer match.
// update: v1.3 adds multiple colour space values based on array printColors.
// update: v1.4.1 Updated by CarlCanto > https://community.adobe.com/t5/illustrator-discussions/illustrator-javascript-render-swatch-legend-lab-colour-values-incorrect/m-p/11437592
// update: v1.4.2 Only on selected Rombout Versluijs
// update: v1.4.3 Added HEX colors Rombout Versluijs
// update: v1.4.4 Added Split by Color Component Rombout Versluijs
// LAB values by Carlos Canto - 09/16/2020
// reference: https://community.adobe.com/t5/illustrator/illustrator-javascript-render-swatch-legend-lab-colour-values-incorrect/m-p/11438710?page=2#M244722
//>=--------------------------------------
// JS code (c) copyright: John Wundes ( john@wundes.com ) www.wundes.com
// copyright full text here: http://www.wundes.com/js4ai/copyright.txt
//
// Edits by Adam Green (@wrokred) www.wrokred.com
//////////////////////////////////////////////////////////////////
doc = activeDocument,
swatches = doc.swatches.getSelected(),
cols = 4, // number of columns in group
displayAs = "RGBColor", //or "CMYKColor"
printColors = ["HEX", "RGB", "CMYK", "LAB", "GrayScale"], // RGB, CMYK, LAB and/or GrayScale
colorSeparator = " ", // Character used to separate the colours eg "|" output = R: XXX|G: XXX|B: XXX
splitColorComponents = false;
textSize = 10, // output text size value in points
rectRef = null,
textRectRef = null,
textRef = null,
swatchColor = null,
w = 150;
h = 120,
h_pad = 10,
v_pad = 10,
t_h_pad = 10,
t_v_pad = 10,
x = null,
y = null,
black = new GrayColor(),
white = new GrayColor();
black.gray = 100;
white.gray = 0;
activeDocument.layers[0].locked = false;
var newGroup = doc.groupItems.add();
newGroup.name = "NewGroup";
newGroup.move(doc, ElementPlacement.PLACEATBEGINNING);
for (var c = 0, len = swatches.length; c < len; c++) {
var swatchGroup = doc.groupItems.add();
swatchGroup.name = swatches[c].name;
x = (w + h_pad) * ((c) % cols);
y = (h + v_pad) * (Math.round(((c+2) + .03) / cols)) * -1;
rectRef = doc.pathItems.rectangle(y, x, w, h);
swatchColor = swatches[c].color;
rectRef.fillColor = swatchColor;
textRectRef = doc.pathItems.rectangle(y - t_v_pad, x + t_h_pad, w - (2 * t_h_pad), h - (2 * t_v_pad));
textRef = doc.textFrames.areaText(textRectRef);
textRef.contents = swatches[c].name + "\r" + getColorValues(swatchColor);
textRef.textRange.fillColor = is_dark(swatchColor) ? white : black;
textRef.textRange.size = textSize;
rectRef.move(swatchGroup, ElementPlacement.PLACEATBEGINNING);
textRef.move(swatchGroup, ElementPlacement.PLACEATBEGINNING);
swatchGroup.move(newGroup, ElementPlacement.PLACEATEND);
}
function getColorValues(c, spot) {
if (c.typename) {
if (c.typename == "SpotColor") {
return getColorValues(c.spot.color, c.spot);
};
switch (c.typename) {
case "RGBColor":
sourceSpace = ImageColorSpace.RGB;
colorComponents = [c.red, c.green, c.blue];
break;
case "CMYKColor":
sourceSpace = ImageColorSpace.CMYK;
colorComponents = [c.cyan, c.magenta, c.yellow, c.black];
break;
case "LabColor":
sourceSpace = ImageColorSpace.LAB;
colorComponents = [c.l, c.a, c.b];
break;
case "GrayColor":
sourceSpace = ImageColorSpace.GrayScale;
colorComponents = [c.gray];
break;
}
var outputColors = new Array();
for (var i = printColors.length - 1; i >= 0; i--) {
colorType = printColors[i] == "HEX" ? "Indexed": printColors[i];
targetSpace = ImageColorSpace[colorType] ;
if (printColors[i] == 'LAB' && spot && spot.spotKind == 'SpotColorKind.SPOTLAB') {
outputColors[i] = spot.getInternalColor();
} else if(printColors[i] == 'HEX') {
if (app.activeDocument.documentColorSpace == DocumentColorSpace.CMYK) {
colorArray = [c.cyan, c.magenta, c.yellow, c.black];
// [Math.round(c), Math.round(m), Math.round(y), Math.round(k)]
rgbConv = app.convertSampleColor(ImageColorSpace["CMYK"], colorArray, ImageColorSpace["RGB"], ColorConvertPurpose.defaultpurpose);
outputColors[i] = [rgbConv[0].toString(16), rgbConv[1].toString(16), rgbConv[2].toString(16)];
} else{
outputColors[i] = [c.red.toString(16), c.green.toString(16), c.blue.toString(16)];
}
}
else {
outputColors[i] = app.convertSampleColor(sourceSpace, colorComponents, targetSpace, ColorConvertPurpose.previewpurpose);
}
for (var j = outputColors[i].length - 1; j >= 0; j--) {
colorComp = splitColorComponents == true ? printColors[i].charAt(j) + ": " : "";
if(isNaN(outputColors[i][j])){
outputColors[i][j] = colorComp + outputColors[i][j];
} else {
outputColors[i][j] = colorComp + Math.round(outputColors[i][j]);
}
if (j == outputColors[i].length - 1) {
outputColors[i][j] += "\r";
};
};
outputColors[i] = outputColors[i].join(colorSeparator);
if(!splitColorComponents) outputColors[i] = printColors[i]+" "+outputColors[i]
};
return outputColors.join("");
}
return "Non Standard Color Type";
}
function is_dark(c) {
if (c.typename) {
switch (c.typename) {
case "CMYKColor":
return (c.black > 50 || (c.cyan > 50 && c.magenta > 50)) ? true : false;
case "RGBColor":
return (c.red < 100 && c.green < 100) ? true : false;
case "GrayColor":
return c.gray > 50 ? true : false;
case "SpotColor":
return is_dark(c.spot.color);
return false;
}
}
}