-
-
Save jmsdnns/f170599dc98f036ba72a2618797f525d to your computer and use it in GitHub Desktop.
/** | |
* jd-export.jsx | |
* ------------- | |
* Illustrator script—Exports CMYK, RGB, and Hex values for all the color | |
* swatches in a document. CMYK to RGB conversion using Adobe’s default US | |
* Web Coated SWOP2 to sRGB. | |
* | |
* | |
* LICENSE | |
* ------- | |
* Copyright 2017 Jms Dnns | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are | |
* met: | |
* | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* 3. Neither the name of the copyright holder nor the names of its | |
* contributors may be used to endorse or promote products derived from | |
* this software without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
try { | |
// | |
// Function Library | |
// | |
/** | |
* decimalToHex takes a number and returns it converted base 16, aka hex | |
* @param {number} decimal number to convert to hex | |
* @returns {String} a hex string | |
*/ | |
function decimalToHex(decimal) { | |
var hex = decimal.toString(16); | |
return hex; | |
}; | |
/** | |
* hexToDecimal takes a base 16 number and returns it converted to decimal | |
* @param {String} hex a hex string | |
* @returns {number} hex as decimal | |
*/ | |
function hexToDecimal(hex) { | |
var decimal = parseInt(hex, 16); | |
return decimal; | |
}; | |
/** | |
* padPrefix takes a string `s`, a desired width `width`, and a padding | |
* character `padChar`, and returns a string. If the length of `s` is | |
* less than `width`, `padChar` will be used to fill in the space. | |
* @param {String} s string to be padded | |
* @param {number} width desired width for the string | |
* @param {String} padChar character to pad string | |
* @returns {String} the padded string | |
*/ | |
function padPrefix(s, width, padChar) { | |
var paddedS = s; | |
if(s.length < width) { | |
var padding = new Array(width - paddedS.length + 1).join(padChar); | |
var paddedS = padding + s; | |
} | |
return paddedS; | |
}; | |
/** | |
* RGBToHex takes numeric values for red, green, and blue, and returns | |
* a hex string. | |
* @param {number} r red | |
* @param {number} g green | |
* @param {number} b blue | |
* @returns {String} a hex string | |
*/ | |
function RGBToHex(r, g, b) { | |
if (r < 0 || r > 255) alert("Red value should be between 0-255: " + r); | |
if (g < 0 || g > 255) alert("Green value should be between 0-255: " + g); | |
if (b < 0 || b > 255) alert("Blue value should be between 0-255: " + b); | |
// Convert to hex | |
r_hex = decimalToHex(r); | |
g_hex = decimalToHex(g); | |
b_hex = decimalToHex(b); | |
// Pad any values that are a single character | |
r_hex = padPrefix(r_hex, 2, "0"); | |
g_hex = padPrefix(g_hex, 2, "0"); | |
b_hex = padPrefix(b_hex, 2, "0"); | |
// Create hex string | |
hex = "#" + r_hex + g_hex + b_hex; | |
return hex; | |
}; | |
/** | |
* hexToRGB takes a hex string and returns a structure with r, g, and b | |
* fields. | |
* @param {String} hex hex string representing an html color value | |
* @returns {Object} Object with values for r, g, and b | |
*/ | |
function hexToRGB(hex) { | |
// Remove leading "#" from "#000" or "#000000" | |
if ((hex.length == 4 || hex.length == 7) && hex[0] == "#") { | |
hex = hex.slice(1); | |
} | |
// Convert "RGB" to "RRGGBB" | |
if (hex.length == 3) { | |
var new_hex = ""; | |
for(var i=0; i < hex.length; i++) { | |
new_hex += hex [i] + hex[i]; | |
} | |
hex = new_hex; | |
} | |
// Extract color values | |
var r = hex.slice(0,2); | |
var g = hex.slice(2,4); | |
var b = hex.slice(4,6); | |
// Convert to decimal | |
var r_decimal = hexToDecimal(r); | |
var g_decimal = hexToDecimal(g); | |
var b_decimal = hexToDecimal(b); | |
return { r: r_decimal, g: g_decimal, b: b_decimal }; | |
}; | |
/** | |
* convertColor Translates color values from one format, like CMYK, to | |
* another, like RGB. If the destFormat is RGB, the return value is an | |
* array with 3 items: R, G, and B. | |
* @param {String} srcFormat Color format of the source data | |
* @param {String} destFormat Color format we are converting to | |
* @param {Object} colorArray Source data | |
* @returns {Object} An array of colors | |
*/ | |
function convertColor(srcFormat, destFormat, colorArray) { | |
var srcColorSpace = ImageColorSpace[srcFormat]; | |
var destColorSpace = ImageColorSpace[destFormat]; | |
return app.convertSampleColor(srcColorSpace, colorArray, destColorSpace, ColorConvertPurpose.defaultpurpose); | |
} | |
/** | |
* RGBtoCMYK converts r, g, and b values into CMYK and returns an | |
* object with c, m, y, and k fields. | |
* @param {number} r red | |
* @param {number} g green | |
* @param {number} b blue | |
* @returns {Object} Object with c, m, y, and k fields | |
*/ | |
function RGBToCMYK(r, g, b) { | |
var colors = [Math.round(r), Math.round(g), Math.round(b)]; | |
var cmyk = convertColor("RGB", "CMYK", colors); | |
return { c: cmyk[0], m: cmyk[1], y: cmyk[2], k: cmyk[3] } | |
} | |
/** | |
* CMYKtoRGB converts c, m, y, and k values into RGB and returns a | |
* structure with r, g, and b fields. | |
* @param {number} c cyan | |
* @param {number} m magenta | |
* @param {number} y yellow | |
* @param {number} k black | |
* @returns {Object} Object with r, g, and b fields | |
*/ | |
function CMYKToRGB(c, m, y, k) { | |
var colors = [Math.round(c), Math.round(m), Math.round(y), Math.round(k)] | |
var rgb = convertColor("CMYK", "RGB", colors); | |
return { r: rgb[0], g: rgb[1], b: rgb[2] }; | |
} | |
/** | |
* fromRGB is a conversion function to go from RGB to every format | |
* @param {number} r red | |
* @param {number} g green | |
* @param {number} b blue | |
* @returns {Object} Object with values for rgb, hex, and cmyk | |
*/ | |
function fromRGB(r, g, b) { | |
var hex = RGBToHex(r, g, b); | |
var cmyk = RGBToCMYK(r, g, b); | |
var c = Math.round(cmyk.c); | |
var m = Math.round(cmyk.m); | |
var y = Math.round(cmyk.y); | |
var k = Math.round(cmyk.k); | |
return { | |
r: r, g: g, b: b, | |
hex: hex, | |
c: c, m: m, y: y, k: k, | |
}; | |
}; | |
/** | |
* fromHex is a conversion function to go from Hex to every format | |
* @param {String} hex hex string representing an html color value | |
* @returns {Object} Object with values for rgb, hex, and cmyk | |
*/ | |
function fromHex(hex) { | |
var rgb = HexToRGB(hex); | |
var r = Math.round(rgb.r); | |
var g = Math.round(rgb.g); | |
var b = Math.round(rgb.b); | |
var cmyk = RGBToCMYK(r, g, b); | |
var c = Math.round(cmyk.c); | |
var m = Math.round(cmyk.m); | |
var y = Math.round(cmyk.y); | |
var k = Math.round(cmyk.k); | |
return { | |
r: r, g: g, b: b, | |
hex: hex, | |
c: c, m: m, y: y, k: k, | |
}; | |
}; | |
/** | |
* fromCMYK is a conversion function to go from CMYK to every format | |
* @param {number} c cyan | |
* @param {number} m magenta | |
* @param {number} y yellow | |
* @param {number} k black | |
* @returns {Object} Object with values for rgb, hex, and cmyk | |
*/ | |
function fromCMYK(c, m, y, k) { | |
var rgb = CMYKToRGB(c, m, y, k); | |
var r = Math.round(rgb.r); | |
var g = Math.round(rgb.g); | |
var b = Math.round(rgb.b); | |
var hex = RGBToHex(r, g, b); | |
return { | |
r: r, g: g, b: b, | |
hex: hex, | |
c: c, m: m, y: y, k: k, | |
}; | |
}; | |
// | |
// App Logic | |
// | |
if (app.documents.length > 0) { | |
var destFolder = null; | |
destFolder = Folder.selectDialog('Select destination folder for CSV', '~'); | |
if (destFolder != null) { | |
var doc = activeDocument; | |
var swatches = doc.swatches; | |
var colors = new Array(); | |
// Document is CMYK | |
if (doc.documentColorSpace == DocumentColorSpace.CMYK) { | |
for (var i=0; i < swatches.length; i++) { | |
if (swatches[i].color == "[CMYKColor]") { | |
var c = Math.round(swatches[i].color.cyan); | |
var m = Math.round(swatches[i].color.magenta); | |
var y = Math.round(swatches[i].color.yellow); | |
var k = Math.round(swatches[i].color.black); | |
var color = fromCMYK(c, m, y, k); | |
var na = swatches[i].name; | |
color.name = na; | |
colors.push(color); | |
} else { | |
// Ignore anything that is not CMYK | |
} | |
} | |
} | |
// Document is RGB | |
else if (doc.documentColorSpace == DocumentColorSpace.RGB) { | |
for (var i = 0; i < col.length; i++) { | |
if (col[i].color == "[RGBColor]") { | |
var r = Math.round(col[i].color.red); | |
var g = Math.round(col[i].color.green); | |
var b = Math.round(col[i].color.blue); | |
var color = fromRGB(r, g, b); | |
var na = col[i].name; | |
color.name = na; | |
colors.push(color); | |
} else { | |
// Ignore anything that is not RGB | |
} | |
} | |
} | |
// Open output file | |
var listName = doc.name + ".csv"; | |
var listFile = destFolder + "/" + listName; | |
var theFile = new File(listFile); | |
var isOpen = theFile.open("w"); | |
if (isOpen) { | |
theFile.seek(0, 0); | |
// Write headers | |
theFile.writeln("I.D.,name,C,M,Y,K,hex,R,G,B"); | |
// Print every item in colors. | |
for (var i = 0; i < colors.length; i++) { | |
var color = colors[i]; | |
// color.name is handled specifically below to add quotation marks | |
var color_items = [ | |
color.c, | |
color.m, | |
color.y, | |
color.k, | |
color.hex, | |
color.r, | |
color.g, | |
color.b | |
]; | |
var line = i + "," + "\"" + color.name + "\"," + color_items.join(','); | |
theFile.writeln(line); | |
} | |
theFile.close(); | |
} | |
alert('Export Complete'); | |
} | |
else { | |
alert('Export Aborted'); | |
} | |
} | |
else { | |
throw new Error('There are no documents open!'); | |
} | |
} | |
catch (e) { | |
alert(e.message, "Script Alert", true); | |
} | |
@fuzenco, this is exactly the problem that I've been having. It recognizes when I delete the default swatches but fails to recognize anything custom. so for something like the following picture, no data will be exported despite having 2 new colors.
@fuzenco, this is exactly the problem that I've been having. It recognizes when I delete the default swatches but fails to recognize anything custom. so for something like the following picture, no data will be exported despite having 2 new colors.
Ok. I thought I was losing my mind. Or that it was a script permissions problem. What you indicate is exactly my problem.
@schroef Yes, my file(s) are CMYK. I’ve run this script before, so I know it worked well. Maybe the most recent Illustrator update(s) broke something. The following link contains two files. One contains the default swatches + the custom color; the other one without the default swatches + the custom color.
There is no difference between these documents. The with and without default have exactly the same swatches
PS as i thought the Spot color doesnt get exported, all process colors do. See below for alternate version which does work on spot colors
The adjust from @louisrawlins was only for CMYK, the RGB still had col instead of swatches, thats also fixed
Ive made an alternate version of this script, which can now also do Spot, Spot LAB, Spot Grayscale
https://raw.githubusercontent.com/schroef/Illustrator-Scripts/master/jd-export.jsx
@schroef my apologies, you're right that I forget to remove the additional swatches on file two.
I ran your script and everything works perfect now. Thank you very much. And thanks for the Spot additions 👍
I think my ideal feature for this script would be to export color groups (as in folders in the color palette) as separated groups in the CSV file. Now that would be awesome.
@jjaybyrd @fuzenco Perhaps i could add Gradients as well, but thats is more complicated and im not sure how we should tackle that. I mean a gradient can be very complicated and can have many colors. Not see i see value in adding it.
@schroef It's an interesting idea, but I'm considering its usefulness for graphic design purposes 🤔 Illustrator's classification and handling of gradients is in my opinion pretty clunky. There isn't really a super short-handed way communicate gradient information (other than maybe sharing swatches). I typically have to give specs for combined colors and percentages for placement. If anybody else has a better way of doing that though, would be super interested to hear
@schroef ill test it out
@jjaybyrd @fuzenco Perhaps i could add Gradients as well, but thats is more complicated and im not sure how we should tackle that. I mean a gradient can be very complicated and can have many colors. Not see i see value in adding it.
@schroef It's an interesting idea, but I'm considering its usefulness for graphic design purposes 🤔 Illustrator's classification and handling of gradients is in my opinion pretty clunky. There isn't really a super short-handed way communicate gradient information (other than maybe sharing swatches). I typically have to give specs for combined colors and percentages for placement. If anybody else has a better way of doing that though, would be super interested to hear
Im not sure i follow? Could you explain that different. Im not sure what is wrong with current method of sharing gradient?
@schroef sorry i think i was just venting about what i perceive as an illustrator problem in that you can communicate color stops but not easily their placement on the color slider. Your added approach above actually really helps me with a current project I'm working on (i was having to manually select gradient color stops), honestly thank you for all your great work 😃
@jjaybyrd
Well editing color stops is not that difficult, especially in the last couple of illustratie versions. It's always best to to use global colors, because if you would edit those color, all your gradients in the document will be adjusted. It's always better to use global colors for ease of use.
I'll update the current version tomorrow with this new edit
Guys, I’ve been designing for close to 30 years. One simple way of creating gradients and saving them as a color palette is to create a blend.
- Create two squares (or whatever) with the first and end color you want to use
- Select them and choose Object > Blend > Options
- Enter Specified Steps (in this case 8)
- Go back and choose Object > Blend > Make
- The gradient gets created and then…
- Choose Object > Blend > Expand
- Then distributing the items via Horizontal Distribution Evenly
I usually then just select the entire row and save to my palette. It's a quick and easy way to create gradients but more importantly to have the color stops at your disposal for using as needed.
Sorry if this derails this conversation but @schroef addition of gradients is cool in my opinion. I would just need to test what he's done.
In my case, if I used the blend method AND there were a way to group palette folders together in the CSV (maybe a blank line between groups), that would be a great addition to this script.
okay i added updated version, this one can also do gradient colors
I will add "Gradient Color", so user know where it starts, then i add "ColorStop X" for each colorstop. I first had the color value as name, but that made the colorstops below the gradient color much longer in name. It works in both RGB and CMYK documents
https://raw.githubusercontent.com/schroef/Illustrator-Scripts/master/jd-export.jsx
This is masterful @schroef. I will test it out this afternoon. Thank you 👍
p palette folders together in the CS
Yes i know that method, but one would only use that if they needs to color stops. Perhaps that is usefull GUI designers which want tints or inbetween colors of a gradient. Downside it adds a lot colors. PS i also have a script which can turn those colors into a real gradient. If i recall correct
PS i dont see how i could add colorgroups clearly in the CSV without changing the formatting to much. Basically adding the gradient is already changing that.
If i recall correct, the colorgroups are not exposed to script. ExtendScript doesnt know if a color is inside a color group
@schroef . Tested it. Gradient export works perfect. However…
I do see a bug in the script, though. After creating my gradients and properly exporting, if I add additional standard swatches (in my case 2 colors in a color group/folder), those two new colors do not get exported when the same file name is used for the CSV. In my case, I had to duplicate the file and rename it. Running the script did include the two new swatches this time around.
Here’s the file I used: http://fuzen.co/dropbox/test2.ai.zip
@jjaybyrd yes, only for evenly distributed gradients. But prior to this script, getting color stop values was a manual process for me.
PS i dont see how i could add colorgroups clearly in the CSV without changing the formatting to much. Basically adding the gradient is already changing that. If i recall correct, the colorgroups are not exposed to script. ExtendScript doesnt know if a color is inside a color group
Understood. You’ve done a masterful job.
That script to convert colors to a gradient would be cool. Is it somewhere I can download?
@schroef . Tested it. Gradient export works perfect. However…
I do see a bug in the script, though. After creating my gradients and properly exporting, if I add additional standard swatches (in my case 2 colors in a color group/folder), those two new colors do not get exported when the same file name is used for the CSV. In my case, I had to duplicate the file and rename it. Running the script did include the two new swatches this time around.
Here’s the file I used: http://fuzen.co/dropbox/test2.ai.zip
@fuzenco
You mean it doesn't overwrite the existing CSV file?. I'll test that file
I don't have issues with that on my windows system
PS i dont see how i could add colorgroups clearly in the CSV without changing the formatting to much. Basically adding the gradient is already changing that. If i recall correct, the colorgroups are not exposed to script. ExtendScript doesnt know if a color is inside a color group
Understood. You’ve done a masterful job.
That script to convert colors to a gradient would be cool. Is it somewhere I can download?
@fuzenco
Actually swatchgroups are exposed. I see what I can do about that. I would need to check if can test if a swath or spot is a child of a search group, than it would be possible
..
I did found it, it was made by someone else. It only does CMYK now. I'll need to update it so it will do all kinds of document color modes
@schroef . Tested it. Gradient export works perfect. However…
I do see a bug in the script, though. After creating my gradients and properly exporting, if I add additional standard swatches (in my case 2 colors in a color group/folder), those two new colors do not get exported when the same file name is used for the CSV. In my case, I had to duplicate the file and rename it. Running the script did include the two new swatches this time around.
Here’s the file I used: http://fuzen.co/dropbox/test2.ai.zip
I just tested your file and it works just fine with v002. I opened your test doc and add a new swatchgroup and added 3 extra colors. I had the csv export from earlier open in Visual Studio Code and after a new export, those 3 colors where added.
You do have v002 right?
I do but it must have been an intermittent bug. 3x I tried to overwrite that initial file. The new file was saved (which overwrote the test2 file), but the new colors were not being added. However, today everything seems to be working fine although I had 002 all along. So disregard this report and if it pops up again, I’ll notify you. Thanks.
I’d not used this script for some time and happened to install it again on the most current Illustrator 2024 (28.1) and it doesn’t export new swatches. It exports the full default color list just fine. Or if you delete all default colors and just leave black and white, it exports fine. But new colors added manually to the color palette are not exported. I’ve placed the script in Adobe Illustrator 2024 > Presets > en_US > Scripts and even restarted the app, but it doesn't work.