Copy link to clipboard
Copied
Hello.
Please help in solving the following problem:
I need to pick up color with a dropper from a pre-selected randomly shaped area, probably quite small relative to the image and having no known position on the canvas, the current layer.
This needs to be done automatically, without manual clicks.
I haven't found ways to do this in PS itself without human intervention, and I have no experience in scripting, but scripting seems to be the correct solution to the problem. It would be great to have a ready-made script for such an operation.
Thank.
function get_average_color(color)
from here: Auto picking the most distinct accent color from an image
UPD.
Короче. По ссылке - глючная реплика со старого форума, скрипты там все нерабочие.
Вот готовый скрипт.
get_average_color(app.foregroundColor);
////////////////////////////////////////////////////////////
function get_average_color(color, x, y)
{
try {
if (x != undefined && y != undefined) app.activeDocument.selection.select([[x,y],[x+1,y],[x+1,y+1],[x,y+1]], Sel
...
Copy link to clipboard
Copied
Easy to do, but hard to imagine what you mean by pre-selected randomly shaped area in a document.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
So you have a mask on a layer, or how your document for these layers part is constructed?
Copy link to clipboard
Copied
No.
This is the normal selection that the Magic Wand Tool can give us, for example.
Without any additional layers. An ordinary selection.
The screenshot shows the selection in the alpha channel, but this is done for a better visualization.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Looking at your tools you don't have latest Photoshop release (Help / Adobe Photoshop...)?
I do not know in which version 'ArrayPolyfills.jsx' was added to Photoshop, so if script won't
work I'll post polyfills I used till today. For a test I linked script to that file. Let's see if it goes.
Make selection and run the script. It's going to change your foreground colour to "middle":
$.evalFile(File(Folder.startup +
'/Presets/Scripts/Stack Scripts Only/ArrayPolyfills.jsx'))
aHS = (aD = activeDocument).activeHistoryState; if (aD.mode != 'RGB')
aD.changeMode(ChangeMode.RGB); rgb = aD.componentChannels; while(rgb.length) {
hstgrm = aD.channels.getByName(nme = rgb.shift().name).histogram, pxls = amnt = 0
while(lngth = hstgrm.length) amnt += ((pxls += hstgrm.pop()) * lngth)
foregroundColor.rgb[nme.toLowerCase()] = amnt / pxls / 128.5
}
aD.activeHistoryState = aHS, aD.selection.deselect()
I wrote this script 6 years ago for my needs so the result might be just close to expected 😄
Copy link to clipboard
Copied
$.evalFile(File(Folder.startup +
'/Presets/Scripts/Stack Scripts Only/ArrayPolyfills.jsx'))
aHS = (aD = activeDocument).activeHistoryState; if (aD.mode != 'RGB')
aD.changeMode(ChangeMode.RGB); rgb = aD.componentChannels; while(rgb.length) {
hstgrm = aD.channels.getByName(nme = rgb.shift().name).histogram, pxls = amnt = 0
while(lngth = hstgrm.length) amnt += ((pxls += hstgrm.pop()) * lngth)
foregroundColor.rgb[nme.toLowerCase()] = amnt / pxls / 128.5
}
aD.activeHistoryState = aHS, aD.selection.deselect()
To Kukurykus
Copy link to clipboard
Copied
1) Originally I used there latter ECMA implementaion methods for Array ie. .indexOf, .reduce and .some, but yestarday after I rewritten my code I didn't check if any of them left within 😄
2) if (aD.mode! = 'RGB') was added to new version of script with intention to check if that is equal to for ex. DocumentMode.RGB. I had later to decide how I want to do it, so temporarily I put there RGB only. When code was finished & worked I didn't realise it wasn't complete 🙂
3) I explained in extra line the result had to be like it, as I needed it in the past for something else, so it is correct unless others want to reconstruct it to make it correct for themselves 😉
Copy link to clipboard
Copied
If we talk about all the stages, ideally it should look like this:
1. The allocation is set
2. Inside the area is the middle color
3. The middle color is picked up with the dropper
4. Placed in the main color
I hope I was able to get my point across more correctly. Thank you
Copy link to clipboard
Copied
Where from is middle color (and what is that?) in 2.png if on 1.png you had only selection?
Copy link to clipboard
Copied
I do not think a without a click to set a color sampler to the pixel a script can. What do you know about the shape layer? Do you know where in the Layer stack the shape layers is and what kind of a fill layer the shape layer is? A script can get the bounds of a shape layer. Get the Paths of a shape layer there can be many path item for various close path in the layer's vector mask that combine in various ways, A shape layers combined path can be stroked on the path, outside the path or inside the path and the stroke can be wide, So Pixels in the shape layer can very in color if its not a solid fill shape and part of the fill can be overlaid with a stroke. So you must know the fill is a solid color and where the x,y of an untainted pixels in the shape is.
A script need to coded with some logic the will get the pixel in the shape you want to sample. Once the script knows the Pixel's x,y it could set a color sampler to get that pixel color.
A selection is quite like a shape how would you know which x,y pixel in the has the color you want to sample,
Copy link to clipboard
Copied
To answer your questions:
1. it won't be a shape, but a regular raster layer.
2. The action is performed with the active layer
3. The fill of the selected area will be solid
Also in the screenshots in the reply to Kukurykus you can see the whole process step by step how it should work with the image.
Copy link to clipboard
Copied
I do not see any process there or even your layer stack.
I see what look to be a screen capture of a layer mask a gray scale channel black white with gray soft edges.
A screen capture of a raster image layer with a quick mask overlay.
A screen capture of a raster image layer with no mask applied but there an active selection the is like the captured Layer Mask load as a selection.
I see no layer stack wih layer with thumnails for contents and mask or any steps documented.
I see one thing a selection
Copy link to clipboard
Copied
function get_average_color(color)
from here: Auto picking the most distinct accent color from an image
UPD.
Короче. По ссылке - глючная реплика со старого форума, скрипты там все нерабочие.
Вот готовый скрипт.
get_average_color(app.foregroundColor);
////////////////////////////////////////////////////////////
function get_average_color(color, x, y)
{
try {
if (x != undefined && y != undefined) app.activeDocument.selection.select([[x,y],[x+1,y],[x+1,y+1],[x,y+1]], SelectionType.REPLACE);
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; }
if (x != undefined && y != undefined) app.activeDocument.selection.deselect();
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));
return hist;
}
catch (e) { alert(e); return null; }
}