Try to loop through all objects selected and adjust the color based on a variable.

Community Beginner ,
Aug 30, 2022 Aug 30, 2022

Copy link to clipboard

Copied

Hey y'all,

 

I'm trying to create a script that will cycle through all the items in a document and change them to either Black (RGB 0,0,0) or White (RGB 255,255,255) based on the sum of their RGB values.

 

If the sum of all RGB values >= 500, turn object white.

If the sum of all RGB values < 500, turn the object black.

 

I have a functional script that I will post below that works for a single object, but I can't get it to loop through all objects.

 

I've tried tweaking it with these methods with no luck.

For Loops

While Loops

pathItems

selection

run script and lock selection, select all, and repeat.


Any help is appreciated!

 

doc = app.activeDocument;

var sel = doc.selection[0];
var colorSum = sel.fillColor.red + sel.fillColor.green + sel.fillColor.blue;

if (colorSum >= 500 ) {
        var whiteFillColor = new RGBColor();
        whiteFillColor.red = 255;
        whiteFillColor.green = 255;
        whiteFillColor.blue = 255;
       
    sel.fillColor = whiteFillColor;}
else{
    var blackFillColor = new RGBColor();
        blackFillColor.red = 0;
        blackFillColor.green = 0;
        blackFillColor.blue = 0;
       
    sel.fillColor = blackFillColor;}
 
TOPICS
Scripting

Views

53

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 30, 2022 Aug 30, 2022

Copy link to clipboard

Copied

Hi @Keaton5CDB 

Below is the same version of your script, just running on all pageItems of the documents. Assuming your script is working fine, I have just added the loop to traverse all pageItems of the documents.

doc = app.activeDocument;

for (var i = 0; i < doc.pageItems.length; i++) {
    var sel = doc.pageItems[i];
    var colorSum = sel.fillColor.red + sel.fillColor.green + sel.fillColor.blue;

    if (colorSum >= 500) {
        var whiteFillColor = new RGBColor();
        whiteFillColor.red = 255;
        whiteFillColor.green = 255;
        whiteFillColor.blue = 255;

        sel.fillColor = whiteFillColor;
    }
    else {
        var blackFillColor = new RGBColor();
        blackFillColor.red = 0;
        blackFillColor.green = 0;
        blackFillColor.blue = 0;

        sel.fillColor = blackFillColor;
    }
}

 

Let us know if this works for you or not. If not, then it will be good to share the sample documents to see how items are arranged in your documents.

Best regards

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 30, 2022 Aug 30, 2022

Copy link to clipboard

Copied

Thanks for the reply!

That works for a couple of simple shapes on the document which will be handy, but once you get a little more complex it throws the error

"Error 21: undefined is not an object.

Line:5

-> var colorSum = sel.fillColor.red + sel.fillColor.green + sel.fillColor.blue;"

 

I'm attaching the document I tested it on that has a couple of off-whites and blacks scattered throughout the document..

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 30, 2022 Aug 30, 2022

Copy link to clipboard

Copied

LATEST

it's likely there are some groupItems or compoundPathItems or other art items like linkedItems that don't have a "fillColor" property.

 

if you encounter a group.. you need to dig inside it and find the pathItems or compoundPathItems.

If you encounter a compoundPathItem, you need to access a pageItem inside of it and get the fill color from that, like this: myCompoundPath.pathItems[0].fillColor

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 30, 2022 Aug 30, 2022

Copy link to clipboard

Copied

it can be dangerous (but in general it's just bad practice) to try to loop all of the items in a document. Because of the way the artwork tree is, and the way each node in that tree is technically a pageItem, you may end up processing way way more things than you expected (as an example, if you have a compound path, that's one pageItem. But that compound path could be made of dozens of other compound paths and pathItems and groupItems.. You don't want to process all of the children of a compound path. you only need to touch the first path to get and set colors).

 

Can you share the document you're trying to recolor? What does it contain? Lots of different kinds of art? Or just simple shapes with a simple fill?

 

For the time being, I'll just show you the loop assuming you're just looping the selected items. But we can discuss better ways to target your artwork if you want.

 

So, your logic up there is good. You just need to wrap it inside of your loop and target the specific piece by index then you're good to go. it looks like this:

 

//i always wrap my code in a function to avoid global variables
function setBlackOrWhite()
{
    //make sure there's at least one document open
    if(!app.documents.length)
    {
        alert("Please open a document and select at least one pageItem first.");
        return;
    }

    var doc = app.activeDocument; //make sure to use "var" when declaring a variable or it will be placed in the global scope.
    var sel = doc.selection; //get the selection
    if(!sel.length)
    {
        alert("Please select at least one pageItem and try again.");
        //no selection. exiting script.
        return;
    }

    
    //set up the color variables outside the loop so we don't have to keep re-declaring them
    var whiteFillColor = new RGBColor();
    whiteFillColor.red = 255;
    whiteFillColor.green = 255;
    whiteFillColor.blue = 255;
    var blackFillColor = new RGBColor();
    blackFillColor.red = 0;
    blackFillColor.green = 0;
    blackFillColor.blue = 0;

    //declare some variables that will be used inside the loop.
    //declaring new variables inside of a loop body has been known to cause problems
    //with extendscript. I don't believe this is an issue for regular javascript,
    //but something we need to keep an eye out for, for sure.
    var curItem, colorSum;

    //now loop the selection
    for(var i=0;i<sel.length;i++)
    {
        //within a loop, use your loop variable to access the selection index.
        //just like your original code had "doc.selection[0]". zero is the index.
        //in the loop, we're replacing a hard coded number for a variable that represents
        //all integers between 0 and the length of the selection.
        curItem = doc.selection[ i ]; 
        colorSum = sel.fillColor.red + sel.fillColor.green + sel.fillColor.blue;

        if ( colorSum >= 500 )
        {
            sel.fillColor = whiteFillColor;
        }
        else
        {
            sel.fillColor = blackFillColor;
        }
    }
}
setBlackOrWhite();

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines