Gradient: find dominant color by spread.

Adobe Community Professional ,
Jan 24, 2021

Copy link to clipboard

Copied

Hello dear scripting professionals.

Given the case that a shape is filled with a gradient and this gradient is composed of known standardized swatch colors (and only those swatch colors, 100% opacity), what is the way to use gradient stop rampPoints, midPoints, anything else, to determine the most dominant color by how much this color spreads across the gradient and takes up the most spectrum.

 

Thanks to anyone taking a look!

Silly-V_0-1611482173943.png

 

TOPICS
Scripting

Views

135

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Adobe Community Professional ,
Jan 24, 2021

Copy link to clipboard

Copied

midPoint is the place where the colors are equal (50% of each one). Gradient points are places where the one color value is 100% and the other's is 0%. So, using Location field, tou can determine the spreading of the color and its changing speed.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Enthusiast ,
Jan 24, 2021

Copy link to clipboard

Copied

I think a formula to quantify dominance would be:

 

(distance between stop and stop before) * (fraction of mid point on that side) +

(distance between stop and stop after) * (fraction of mid point on that side)

 

zzz.png

 

So if you have four colors

 

xxx.png

 

var stops = selection[0].fillColor.gradient.gradientStops;

var d0 = stops[0].rampPoint;
var d1 = stops[1].rampPoint-stops[0].rampPoint;
var d2 = stops[2].rampPoint-stops[1].rampPoint;
var d3 = stops[3].rampPoint-stops[2].rampPoint;
var d4 = 100-stops[3].rampPoint;

var colors = [
    {
        value: d0 + (d1 * (stops[0].midPoint / 100)),
        name: "magenta"
    },
    {
        value: (d1 * ((100-stops[0].midPoint) / 100)) + (d2 * (stops[1].midPoint / 100)),
        name: "yellow"
    },
    {
        value: (d2 * ((100-stops[1].midPoint) / 100)) + (d3 * (stops[2].midPoint / 100)),
        name: "cyan"
    },
    {
        value: (d3 * ((100-stops[2].midPoint) / 100)) + d4,
        name: "black"
    }
];

// most dominant to least dominant
colors.sort(function(a, b) {return b.value - a.value;})

alert( colors[0].name + " - " + colors[0].value + "\
" + colors[1].name + " - " + colors[1].value + "\
" + colors[2].name + " - " + colors[2].value + "\
" + colors[3].name + " - " + colors[3].value );

 

This doesn't take into account repeated colors.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Engaged ,
Jan 24, 2021

Copy link to clipboard

Copied

My thoughts are exactly as @femkeblanco. I wonder if we are being naive? I can imagine cases where a human looking at the gradient would pick the eye-popping color from the 'dominant' color. Anyway, for fun, I've had a go at an implementation:

// select an item with gradent fillColor before running script
var item = selection[0];
var grad = item.fillColor;

var colorStats = getGradientSpotColorCoverageStats(grad);
var dominantColor = colorStats[0];
$.writeln(dominantColor.name + ': ' + dominantColor.score + ' percent coverage');


function getGradientSpotColorCoverageStats(grad) {
    if (grad.typename == 'GradientColor') grad = grad.gradient;
    if (grad.typename != 'Gradient') throw new Error('Not a gradient');
    var colrs = {}, currentRampPoint = 0, currentStop, currentColorName, prevColorName, currentRampPoint, prevRampPoint, currentMidPoint, prevMidPoint;

    for (var i = 0; i < grad.gradientStops.length; i++) {
        currentColorName = grad.gradientStops[i].color.spot.name;
        currentRampPoint = grad.gradientStops[i].rampPoint;
        currentMidPoint = grad.gradientStops[i].midPoint;

        if (colrs[currentColorName] == undefined) {
            // add new color to keep track of
            colrs[currentColorName] = { score: 0 };
        }

        if (i > 0) {
            // work out strength of color based on length of stop and midpoint (assumes linear function!)
            colrs[prevColorName].score += (currentRampPoint - prevRampPoint) * (prevMidPoint / 100)
            colrs[currentColorName].score += (currentRampPoint - prevRampPoint) * ((100 - prevMidPoint) / 100)
        }

        prevRampPoint = currentRampPoint;
        prevColorName = currentColorName;
        prevMidPoint = currentMidPoint;
    }

    // return a sorted array
    sortedColrs = [];
    for (var colr in colrs) {
        sortedColrs.push({ name: colr, score: colrs[colr].score });
    }
    sortedColrs.sort(function (a, b) { return b.score - a.score });

    return sortedColrs;
}

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Silly-V AUTHOR
Adobe Community Professional ,
Jan 24, 2021

Copy link to clipboard

Copied

These are great explorations and potential solutions, or otherwise useful exercises for gradient nees.

However, I must come clean and disclose that this question was driven by another goal, which is to create a process to turn color-to-color gradients into color-to-transparency gradients by applying an opacity mask in the shape of the inverted gradient on top of a shape of flat color. The simplest case is a gradient which has the spot color going to the same color, but it's transparent. The more complex case is multiple spot colors going from one to another, which results in layers of masked shapes (each new mask gets the same gradient, but the stops are changed to all black and opacity 0 is set for stops which are not the current name-group (the spot name)).

During this, I found that although the resulting layered masked shapes make a visual result that is comparable and acceptable within tolerance, putting a background behind this set of shapes shows that it will indeed show through thin transparency areas which occur between color stops fading into each other.
Therefore it would be necessary to place a flat-color background behind the entire set so that this color will fill in any thinly transparent gradated areas.
It was my thought that the color which recurs the most in a gradient should be that final background color. However, I noticed that while there can be many stops of a color, the midpoints and such can make those colors actually less prominent despite the amounts of stops containing those colors. i.e. they could occupy less space.
So, I went here to ask this question but continued my work meanwhile.
And in my work, I also observed that actually, none of this is quite correct given the workflow at hand.

 

What ends up happening is that the resulting masked gradated shapes create a layered structure which compounds to create such blending that the most-stop approach seems to work Ok. In this image, the top-right shape was automatically assigned the Yellow color as the background. The one below has what I would think should be the best color, Green. Visually it has tighter lines, because in the context of being layered thus, there is a color that is out order concerning the new blending interactions which are created. You can see that in the area of red-yellow gradation that there is a greenish hue showing a little bit and making the area somewhat uglier and not as close to the original shape than the yellow color.

Silly-V_0-1611546799245.png

 

As I said, for the needs at this time, this appears satisfactory. Using the answers here it may be possible to better refine the 'most stops' approach to create an even better layering arrangement. Yet, as what I've got appears to be workable already, I'm not sure I will pursue further refinement until such time that new needs would call for it.

 

Thank you all for great insight, it will surely help everyone and probably me later.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
m1b LATEST
Engaged ,
Jan 24, 2021

Copy link to clipboard

Copied

Hi @Silly-V, that's an interesting problem. I don't think it has a general answer though. I think there will be spot color combos that can never be good, but I might be wrong. Anyway, it was fun to play with and useful for my learning. 🙂

- Mark

Likes

Translate

Translate

Report

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