I am trying to figure out how to get the color of one defined Pixel.
In my imagination its shoud look like:
color = get.color.Pixel(x,y);
Maybe someone can help me with this piece of code?
Using the Color Range Tool to Select Color in Photoshop Once the image is loaded into Photoshop, go to Select > Color Range. In the Color Range menu, make sure it says Sampled Colors in the dropdown menu. Set the Fuzziness slider to 0, and set Range to 100 percent.
With the get() function we can read the color of any pixel in our program window. We can specify which pixel we are interested in by using x and y coordinates as parameters. For example, color mycolor = get(100, 200); would grab the color of pixel 100, 200 and put that color into the mycolor variable.
Click somewhere on an open design, hold down and drag, and then you can actually sample color from anywhere on your screen. To get the HEX code, just double click the foreground color and a window with color information will pop up. Then copy the hexidemal #123456 value (HEX code) to your clipboard.
Photoshop's JavaScript API doesn't provide a mechanism like you imagine in your question.
You'll need to utilize the Document.colorSamplers.add([x, y])
method, then read each component color value via its properties:
The following gist shows how to obtain either rgb
or cmyk
values for a given x,y
coordinate:
#target photoshop
// Define the x and y coordinates for the pixel to sample.
var x = 1;
var y = 1;
// Add a Color Sampler at a given x and y coordinate in the image.
var pointSample = app.activeDocument.colorSamplers.add([(x - 1),(y - 1)]);
// Obtain array of RGB values.
var rgb = [
pointSample.color.rgb.red,
pointSample.color.rgb.green,
pointSample.color.rgb.blue
];
// Obtain array of rounded CMYK values.
var cmyk = [
Math.round(pointSample.color.cmyk.cyan),
Math.round(pointSample.color.cmyk.magenta),
Math.round(pointSample.color.cmyk.yellow),
Math.round(pointSample.color.cmyk.black)
];
// Remove the Color Sampler.
pointSample.remove();
// Display the complete RGB values and each component color.
alert('RGB: ' + rgb)
alert('red: ' + rgb[0])
alert('green: ' + rgb[1])
alert('blue: ' + rgb[2])
// Display the complete CMYK values and each component color.
alert('CMYK: ' + cmyk)
alert('cyan: ' + cmyk[0])
alert('magenta: ' + cmyk[1])
alert('yellow: ' + cmyk[2])
alert('black: ' + cmyk[3])
Here's a simple script using a ColorSampler
. It's set up to return RGB values.
function PixelSampler(doc) {
this.doc = doc
this.doc.colorSamplers.removeAll();
this.sampler = this.doc.colorSamplers.add([0, 0]);
}
// Return an array of R, G, B pixel values for a particular coordinate.
PixelSampler.prototype.get = function (x, y) {
this.sampler.move([x, y]);
const R = this.sampler.color.rgb.red;
const G = this.sampler.color.rgb.green;
const B = this.sampler.color.rgb.blue;
return [R, G, B];
}
////////////////////////////////////////////////////////
/// SOME TESTS /////////////////////////////////////////
////////////////////////////////////////////////////////
const p = new PixelSampler(app.activeDocument);
alert("Pixel 0 =\n\n" + p.get(0, 0));
$.hiresTimer;
var n = 1000; //p.width * p.height;
for (var i = 0; i < n; i++) p.get(i, 0);
sec = ($.hiresTimer / 1000 / 1000);
alert("Got " + (n / 1000) + " kilopixels in " + sec.toFixed(2) + " seconds.");
This gives me pixel values at about 100 pixels per second on my machine.
I found this and cleaned up the script a bit. Basically, the idea is to:
This gives me pixel values at about 72,000 pixels per second, not including the overhead of writing the raw data to disk and reading it back in. It has the added benefit that you can set pixel values, too.
// Adapted from https://community.adobe.com/t5/photoshop/get-index-of-each-pixel/td-p/10022899?page=1
// The purpose is to query (and change) pixel values quickly.
//
// The secret to speed is doing everything on the script side rather than ask Photoshop to do things.
// We use files on disk as an intermediary; on the script side, we read / write it as a binary file; on the
// Photoshop side, we save / open it as a raw bitmap.
//
// Only works on RGB 8bpp images, but this could be easily extended to support others.
function RawPixels(doc) {
this.doc = doc;
const currentActiveDoc = app.activeDocument;
// Obtain the width and height in pixels of the desired document.
const currentRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
app.activeDocument = doc;
this.width = Number(doc.width.value);
this.height = Number(doc.height.value);
this.length = this.width * this.height;
this.pixelData = "";
// Return the ruler to its previous state.
app.preferences.rulerUnits = currentRulerUnits;
try {
// We're going to save this document as a raw bitmap to be able to read back in the pixel values
// themselves.
const file = new File(Folder.temp.fsName + "/" + Math.random().toString().substr(2) + ".raw");
// Set up the save action.
// See https://helpx.adobe.com/photoshop/using/file-formats.html#photoshop_raw_format for some info,
// and more technical at https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/
var rawFormat = new ActionDescriptor();
rawFormat.putString(stringIDToTypeID("fileCreator"), "8BIM");
rawFormat.putBoolean(stringIDToTypeID("channelsInterleaved"), true);
var saveAction = new ActionDescriptor();
saveAction.putObject(stringIDToTypeID("as"), stringIDToTypeID("rawFormat"), rawFormat);
saveAction.putPath(stringIDToTypeID("in"), file);
saveAction.putBoolean(stringIDToTypeID("copy"), false);
executeAction(stringIDToTypeID("save"), saveAction, DialogModes.NO);
// File is saved; now read it back in as raw bytes.
file.open("r");
file.encoding = "BINARY";
this.pixelData = file.read();
const err = file.error;
file.close();
file.remove();
file = null;
if (err) alert(err);
}
catch (e) { alert(e); }
// Return focus to whatever the user had.
app.activeDocument = currentActiveDoc;
}
// Calculate offset from x, y coordinates. Does not check for valid bounds.
getOffset = function(x, y) {
if (y == undefined) {
// allow linear indices too
y = Math.floor(x / this.width);
x = x - y * this.width;
}
return (y * this.width + x) * 3;
}
// Return an array of R, G, B pixel values for a particular coordinate.
RawPixels.prototype.get = function (x, y) {
const off = getOffset(x, y);
const R = this.pixelData.charCodeAt(off + 0);
const G = this.pixelData.charCodeAt(off + 1);
const B = this.pixelData.charCodeAt(off + 2);
return [R, G, B];
}
// Set the pixel at x, y to the values in RGB.
RawPixels.prototype.set = function (RGB, x, y) {
const off = getOffset(x, y);
// note: note checking that length of p = 3!
const R = String.fromCharCode(RGB[0]);
const G = String.fromCharCode(RGB[1]);
const B = String.fromCharCode(RGB[2]);
this.pixelData = this.pixelData.substr(0, off) + R + G + B + this.pixelData.substr(off + 3);
}
// If any changes were made to the pixels, we need to save them to disk and have Photoshop read that file back in.
// We do that by creating a new layer in the desired document.
RawPixels.prototype.create_layer = function () {
try {
const file = new File(Folder.temp.fsName + "/" + Math.random().toString().substr(2) + ".raw");
file.open("w");
file.encoding = "BINARY";
file.write(this.pixelData);
const err = file.error;
file.close();
if (err) { file.remove(); alert(err); return; }
var rawFormat = new ActionDescriptor();
rawFormat.putInteger(stringIDToTypeID("width"), this.width);
rawFormat.putInteger(stringIDToTypeID("height"), this.height);
rawFormat.putInteger(stringIDToTypeID("channels"), 3);
rawFormat.putBoolean(stringIDToTypeID("channelsInterleaved"), true);
rawFormat.putInteger(stringIDToTypeID("depth"), 8);
var openAction = new ActionDescriptor();
openAction.putPath(stringIDToTypeID("null"), file);
openAction.putObject(stringIDToTypeID("as"), stringIDToTypeID("rawFormat"), rawFormat);
executeAction(stringIDToTypeID("open"), openAction, DialogModes.NO);
file.remove();
// The new active document is the file we just opened. Duplicate its contents into
// a new layer in our desired document, then close this temporary file.
app.activeDocument.activeLayer.duplicate(this.doc.layers[0], ElementPlacement.PLACEBEFORE);
const tempDoc = app.activeDocument;
app.activeDocument = this.doc;
this.doc.layers[0].name = "Pixels";
app.activeDocument = tempDoc;
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
app.activeDocument = this.doc;
}
catch (e) { alert(e); }
}
////////////////////////////////////////////////////////
/// SOME TESTS /////////////////////////////////////////
////////////////////////////////////////////////////////
$.hiresTimer;
const p = new RawPixels(app.activeDocument);
var sec = ($.hiresTimer / 1000 / 1000);
alert("Init RawPixels in " + sec.toFixed(2) + " seconds");
alert("Pixel 0 =\n\n" + p.get(0));
var a = new Array();
for (var i = 0; i < 100; i++) a.push(p.get(i));
alert("Pixel 0-99 = \n\n" + a.toSource());
p.set(0, [1, 200, 3]);
alert("New Pixel 0=\n\n" + p.get(0));
$.hiresTimer;
var n = p.width * p.height;
for (var i = 0; i < n; i++) p.get(i);
sec = ($.hiresTimer / 1000 / 1000);
alert("Got " + (n / 1000 / 1000) + " megapixels in " + sec.toFixed(2) + " seconds.");
$.hiresTimer;
n = 10;
for (var i = 0; i < n; i++) p.set([255, i * 20, i * 10], 1 + i * 2);
sec = ($.hiresTimer / 1000 / 1000);
//alert("Set " + n + " pixels in " + sec.toFixed(2) + " seconds");
p.create_layer();
alert("New layer created with new pixels");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With