Inspiring
September 1, 2023
Answered
Adobe script: Selecting the most prominent color from a PSD layer
- September 1, 2023
- 2 replies
- 3676 views
Dear experts
Suppose I want to extract the most prominent color of an image or a photoshop layer, that is the color which is drawing the most attention, how is that possible?
I checked the following example -
Auto picking the most distinct accent color from a... - Adobe Support Community - 9875726
Here the code is picking up the average color of the image. Now this color is a mix of all the RGB components, but I want to get the most prominent color, not the average one.
Please check the attached picture; though purple is the most prominent color, the code is picking up the brown tone as the average color.
How can we enhance this?
This is the code from the above mentioned link -
var min_saturation = 50;
// create tmp layer and move it on top
app.activeDocument.artLayers.add();
if (app.activeDocument.activeLayer != app.activeDocument.layers[0])
app.activeDocument.activeLayer.move(app.activeDocument.layers[0], ElementPlacement.PLACEBEFORE);
// stamp visible to tmp layer
var d = new ActionDescriptor();
d.putBoolean( charIDToTypeID( "Dplc" ), true );
executeAction( charIDToTypeID( "MrgV" ), d, DialogModes.NO );
// call hsb/hsl filter (rgb -> hsb)
var d = new ActionDescriptor();
d.putEnumerated( charIDToTypeID( "Inpt" ), charIDToTypeID( "ClrS" ), charIDToTypeID( "RGBC" ) );
d.putEnumerated( charIDToTypeID( "Otpt" ), charIDToTypeID( "ClrS" ), charIDToTypeID( "HSBl" ) );
executeAction( charIDToTypeID( "HsbP" ), d, DialogModes.NO );
// select "green" channel
app.activeDocument.activeChannels = [ app.activeDocument.channels[1] ];
// threshold 128 ==> saturation 50% or higher
var d = new ActionDescriptor();
d.putInteger( charIDToTypeID( "Lvl " ), min_saturation * 255/100 );
executeAction( charIDToTypeID( "Thrs" ), d, DialogModes.NO );
// selection from current channel
var r1 = new ActionReference();
r1.putProperty( charIDToTypeID( "Chnl" ), charIDToTypeID( "fsel" ) );
var d = new ActionDescriptor();
d.putReference( charIDToTypeID( "null" ), r1 );
var r2 = new ActionReference();
r2.putEnumerated( charIDToTypeID( "Chnl" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
d.putReference( charIDToTypeID( "T " ), r2 );
executeAction( charIDToTypeID( "setd" ), d, DialogModes.NO );
// remove tmp layer
app.activeDocument.layers[0].remove();
// get average color for selection
var c = new SolidColor();
if (!get_average_color(c)) { alert("Something is wrong"); }
app.activeDocument.selection.deselect();
app.foregroundColor = c;
alert(c.rgb.red + " " + c.rgb.green + " " + c.rgb.blue);
///////////////////////////////////////////////////////////////////////////////////
function get_average_color(color)
{
try {
var chnl = 3;
if (app.activeDocument.mode == DocumentMode.CMYK) chnl = 4;
if (app.activeDocument.mode == DocumentMode.GRAYSCALE) chnl = 1;
var lm = new Array();
var px = new Array();
for (var i = 0; i < chnl; i++)
{
var hst = get_histogram(i+1);
var l = 0;
var p = 0;
if (!hst) { return false; }
for (var n in hst) { l += hst[n] * n; p += hst[n]; }
hst = null;
lm.push(l);
px.push(p);
}
if (app.activeDocument.mode == DocumentMode.RGB)
{
var r =lm[0]/px[0];
var g =lm[1]/px[1];
var b =lm[2]/px[2];
with (color.rgb) { red = Math.round(r); green = Math.round(g); blue = Math.round(b); };
}
else if (app.activeDocument.mode == DocumentMode.LAB)
{
var _l = lm[0]/px[0] * 100/255;
var _a = lm[1]/px[1] - 128;
var _b = lm[2]/px[2] - 128;
with (color.lab) { l = Math.round(_l); a = Math.round(_a); b = Math.round(_b); };
}
else if (app.activeDocument.mode == DocumentMode.CMYK)
{
var c = 100 - lm[0]/px[0] * 100/255;
var m = 100 - lm[1]/px[1] * 100/255;
var y = 100 - lm[2]/px[2] * 100/255;
var k = 100 - lm[3]/px[3] * 100/255;
with (color.cmyk) { cyan = Math.round(c); magenta = Math.round(m); yellow = Math.round(y); black = Math.round(k); };
}
else if (app.activeDocument.mode == DocumentMode.GRAYSCALE)
{
var _l = 100 - lm[0]/px[0] * 100/255;
with (color.gray) { gray = Math.round(_l); };
}
else { alert("Unsupported color mode", "Error", true); return false; }
return true;
}
catch (e) { alert(e); }
}
////////////////////////////////////////////////////////////
function get_histogram(n)
{
try {
var r = new ActionReference();
r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("histogram"));
if (typeof(n) == "string")
r.putName(stringIDToTypeID("channel"), n);
else
{
if (app.activeDocument.mode == DocumentMode.RGB)
{
switch (n)
{
case -1: r.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;
case 0: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("RGB" )); break;
case 1: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("red" )); break;
case 2: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("green")); break;
case 3: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("blue" )); break;
default: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;
}
}
else if (app.activeDocument.mode == DocumentMode.LAB)
{
switch (n)
{
case -1:
case 0: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("lab" )); break;
case 1: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("lightness")); break;
case 2: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("a" )); break;
case 3: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("b" )); break;
default: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;
}
}
else if (app.activeDocument.mode == DocumentMode.CMYK)
{
switch (n)
{
case -1: r.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;
case 0: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("CMYK" )); break;
case 1: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("cyan" )); break;
case 2: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("magenta")); break;
case 3: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("yellow" )); break;
case 4: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("black" )); break;
default: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;
}
}
else if (app.activeDocument.mode == DocumentMode.GRAYSCALE)
{
switch (n)
{
case -1:
case 0: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("black")); break;
default: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;
}
}
else { alert("Unsupported color mode", "Error", true); return null; }
}
var ret;
try { ret = executeActionGet(r).getList(stringIDToTypeID("histogram")); } catch (e) { alert(e); return null; }
var hist = new Array();
for (var i = 0; i < 256; i++) hist.push(ret.getInteger(i));
// var max = Math.max.apply(null, hist);
// alert (avg(hist));
return hist;
}
catch (e) { alert(e); return null; }
}
function avg(arr) {
var sum = 0;
// Iterate the elements of the array
for (var i = 0; i < 256; i++) {
sum += arr[i];
}
// Returning the average of the numbers
return sum / arr.length;
}

