Skip to content

Instantly share code, notes, and snippets.

@akaleeroy
Last active October 17, 2021 04:54
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save akaleeroy/be4a139ce116256e27fb to your computer and use it in GitHub Desktop.
Save akaleeroy/be4a139ce116256e27fb to your computer and use it in GitHub Desktop.
Flatten Black - Illustrator script to batch convert rich blacks to 100%K

Flatten Black

Convert rich blacks to flat black

Flatten Black.jsx Demo

Description

Finds all items with enhanced blacks in the artwork and changes their color to flat black.

It has no prompts because it should work inside a Batch action.

Usage

Save the file and drop it onto the artboard. Or copy it to Illustrator's Scripts folder and launch it from File > Scripts

Default settings are to flatten any color with more than 90%K and 300% coverage. To change this limit open the .jsx file in a text editor and change var maxBlack = 95 and var minCoverage = 300 to your desired values.

You can add this to an action by using Insert Menu Item. Then save your action to an .aia file ( ▾☰ > Save Actions... ).

TODOs

  • Fix Target layer cannot be modified error – locked layers support
#target Illustrator
/* Convert rich blacks to flat black
* Finds items with enhanced blacks in the artwork and changes their color to flat black
*
* No prompts because it should work inside a Batch action!
* TODO: Error Target layer cannot be modified when another layer exists and is locked or smth
*/
// Black limit
// All colors with more than this amount of K and coverage will be flattened
// EDIT HERE
var maxBlack = 90;
var minCoverage = 300;
(function init() {
if(documents.length < 1) {
return;
} else {
main();
}
})();
function main() {
var docRef = app.activeDocument;
with (docRef) {
// Stop if document isn't CMYK
if(documentColorSpace !== DocumentColorSpace.CMYK) {
alert("Document isn't CMYK.");
return;
}
// Extend CMYKColor object with coverage calculation method
CMYKColor.getCoverage = function(color) {
return color.black + color.cyan + color.magenta + color.yellow;
};
// Create flat black Color
flatBlack = new CMYKColor();
flatBlack.black = 100;
// Iterate through all path items
for (var i = 0; i < pathItems.length; i++) {
with (pathItems[i]) {
if (filled == true && fillColor instanceof CMYKColor) {
// If black exceeds maxBlack clip it to flat black (100%K)
if (fillColor.black >= maxBlack && CMYKColor.getCoverage(fillColor) >= minCoverage) fillColor = flatBlack;
}
if (stroked == true && strokeColor instanceof CMYKColor) {
if (strokeColor.black >= maxBlack && CMYKColor.getCoverage(fillColor) >= minCoverage) strokeColor = flatBlack;
}
if (filled == true && fillColor instanceof SpotColor) {
if (fillColor.spot.color.black >= maxBlack && CMYKColor.getCoverage(fillColor) >= minCoverage) fillColor.spot.color = flatBlack;
}
if (stroked == true && strokeColor instanceof SpotColor) {
if (strokeColor.spot.color.black >= maxBlack && CMYKColor.getCoverage(fillColor) >= minCoverage) strokeColor.spot.color = flatBlack;
}
}
}
// Iterate through text items as well
for (var j = 0; j < stories.length; j++) {
with (stories[j]) {
for (var k = 0; k < characters.length; k++) {
with (characters[k].characterAttributes) {
if (fillColor instanceof CMYKColor) {
if (fillColor.black >= maxBlack && CMYKColor.getCoverage(fillColor) >= minCoverage) fillColor = flatBlack;
}
if (strokeColor instanceof CMYKColor) {
if (strokeColor.black >= maxBlack && CMYKColor.getCoverage(fillColor) >= minCoverage) strokeColor = flatBlack;
}
if (fillColor instanceof SpotColor) {
if (fillColor.spot.color.black >= maxBlack && CMYKColor.getCoverage(fillColor) >= minCoverage) fillColor.spot.color = flatBlack;
}
if (strokeColor instanceof SpotColor) {
if (strokeColor.spot.color.black >= maxBlack && CMYKColor.getCoverage(fillColor) >= minCoverage) strokeColor.spot.color = flatBlack;
}
}
}
}
}
}
}
@shauntur
Copy link

shauntur commented Jun 8, 2019

Thanks akaleeroy, this was really helpful. I made a few changes to the code to suit my purpose and thought i'd share the edits to help anyone else wanting to do something similar.

Click to view / download my file here
Please note: i'm not much a coder so it may be a little messy sorry

Changes made are:

  • Added a function to unlock all locked layers and delete any hidden layers
  • Added a function to delete all swatches except the spot colours that my company uses
  • Changed the colorSpace check to convert to CMYK profile rather than showing a warning (please note the file must be previously saved for this to work)
  • Added a new calculation for an artificial saturation which helps separate greys from colours (max CMY value - Min CMY value). This means i can lower the minBlack and minCoverage values to cover a larger mixed black range.
  • Also noticed all your getCoverage calculations were set to fillColor, so i changed the 4 to strokeColor that were referencing stroked objects

My Application:
I work at a power tool company and many of our old instruction manuals have illustrations saved as RGB .AI files and when saving for print, the blacks become a mix of CMYK values. To make it easy for the print factories, these blacks should be pure 100K.
Many of our files have locked or hidden layers and will have a bunch of random spot colours in swatches, so this cleans all that up in one go :)

Note: i also created a script to convert all CMYK.Greys to pure 50K, so let me know if anyone would find this useful.
Hope this helps

@akaleeroy
Copy link
Author

@shauntur So glad this was useful to you, and thanks for sharing your great contributions!
The use cases you outline sound like common problems, I'm a little surprised we had to script to handle them. For batch jobs there could be a simpler config language where you can declare stuff like preflight checks and lookup-table substitutions like these ones (flatten blacks, flatten greys).

P.S. The mess is mostly on the surface, try using a text editor / IDE for code formatting and enforcing a style. Visual Studio Code, Prettier

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment