Copy link to clipboard
Copied
I'm new to Photoshop scripting (am using JavaScript) and was wondering how to get access to each pixel. I have tried doing things like:
var docRef = app.activeDocument
pixelRef = docRef.pixel[0]
Then I could (hopefully) access things like the pixel's color. Please help me!
Copy link to clipboard
Copied
function cS(v1, v2) {
with(preferences) {
s = (parseFloat(version) > 14.1 ? 10 : 4)
if ((len = (cs = (aD = activeDocument)
.colorSamplers).length) < s) {
pixels = Units.PIXELS; function rU(v) {
if (v) cU = rulerUnits, rulerUnits = pixels
}
if (u = rulerUnits != pixels) rU(u)
cs.add([v1,v2]); if (u) rulerUnits = cU
hexColor = cs[len].color.rgb.hexValue
return cs[len].remove(), hexColor
}
else aD.colorSamplers.removeAll(), cS(v1, v2)
}
}
cS(225, 275)
Copy link to clipboard
Copied
Layers can be any size. Only a Layers pixel over the document canvas are visible if the layer visibility is on. Any of the visible pixels can be address with a color sampler and you can access its color. You can set up to 10 Color samplers. I do not know how you can address a layer pixels that are clipped by the Document canvas size. Color samplers are relaive to canvas size and seem to be confind to be within the canvas Area. If you add or remove camvas a color sampler position remains relative to canvas and is adjusted by Photoshop during the canvas size change. Which may mean removing samplers that would no longer be within canvas the document canvas. The Sampler Color is for the Image composit pixel so set layer visibility to what you want to sample.
Copy link to clipboard
Copied
Wow when did they increase that to 10, I always thought it was 4!
Oh duh the answer is in the code snippet above! Wow!~
s = (parseFloat(version) > 13.1 ? 10 : 4)
Copy link to clipboard
Copied
With second update to first CC: https://www.davidebarranca.com/2014/01/up-to-10-color-samplers-photoshop-cc-14-2/​
Copy link to clipboard
Copied
Btw I saw here some amazing script of r-bin I didn't try, but it looked much more profesional than mine. Now it is gone
Copy link to clipboard
Copied
Btw I saw here some amazing script of r-bin I didn't try, but it looked much more profesional than mine. Now it is gone
Play with it. I'm already tired.:)
function RawPixels(doc)
{
this.doc = doc;
this.pixels = null;
var tmp1 = app.preferences.rulerUnits;
var tmp2 = app.activeDocument;
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.data = "";
app.preferences.rulerUnits = tmp1;
try {
var file = new File(Folder.temp.fsName + "/" + Math.random().toString().substr(2) + ".raw");
var d = new ActionDescriptor();
var d1 = new ActionDescriptor();
d1.putString(stringIDToTypeID("fileCreator"), "8BIM");
d1.putBoolean(stringIDToTypeID("channelsInterleaved"), true);
d.putObject(stringIDToTypeID("as"), stringIDToTypeID("rawFormat"), d1);
d.putPath(stringIDToTypeID("in"), file);
d.putBoolean(stringIDToTypeID("copy"), false);
executeAction(stringIDToTypeID("save"), d, DialogModes.NO);
file.open("r");
file.encoding = "BINARY";
this.data = file.read();
var err = file.error;
file.close();
file.remove();
file = null;
if (err) alert(err);
}
catch (e) { alert(e); }
app.activeDocument = tmp2;
}
RawPixels.prototype.get = function(x, y)
{
if (y == undefined) y = 0;
var off = (y*this.width + x) * 3;
return [ this.data.charCodeAt(off), this.data.charCodeAt(off+1), this.data.charCodeAt(off+2) ];
}
RawPixels.prototype.set = function(p, x, y)
{
if (y == undefined) y = 0;
var off = (y*this.width + x) * 3;
var len = p.length;
var s = ""; for (var i = 0; i < len; i++) s += String.fromCharCode(p);
this.data = this.data.substr(0,off) + s + this.data.substr(off+len);
}
RawPixels.prototype.create_layer = function()
{
try {
var file = new File(Folder.temp.fsName + "/" + Math.random().toString().substr(2) + ".raw");
file.open("w");
file.encoding = "BINARY";
file.write(this.data);
var err = file.error;
file.close();
if (err) { file.remove(); alert(err); return; }
var d = new ActionDescriptor();
d.putPath(stringIDToTypeID("null"), file);
var d1 = new ActionDescriptor();
d1.putInteger(stringIDToTypeID("width"), this.width);
d1.putInteger(stringIDToTypeID("height"), this.height);
d1.putInteger(stringIDToTypeID("channels"), 3);
d1.putBoolean(stringIDToTypeID("channelsInterleaved"), true);
d1.putInteger(stringIDToTypeID("depth"), 8);
d.putObject(stringIDToTypeID("as"), stringIDToTypeID("rawFormat"), d1);
executeAction(stringIDToTypeID("open"), d, DialogModes.NO);
app.activeDocument.activeLayer.duplicate(this.doc.layers[0], ElementPlacement.PLACEBEFORE);
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
app.activeDocument = this.doc;
this.doc.layers[0].name = "Pixels";
file.remove();
}
catch (e) { alert(e); }
}
////////////////////////////////////////////////////////
/// SOME TESTS /////////////////////////////////////////
////////////////////////////////////////////////////////
$.hiresTimer;
var p = new RawPixels(app.activeDocument);
alert("Init RawPixels in " + ($.hiresTimer/1000000).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([1,200,3],0);
alert("New Pixel 0=\n\n" + p.get(0));
$.hiresTimer;
var n = 100000;
for (var i = 0; i < n; i++) p.get(i);
alert("Processed get " + n + " pixels in " + ($.hiresTimer/1000000).toFixed(2) + " seconds");
$.hiresTimer;
var n = 10;
for (var i = 0; i < n; i++) p.set([255,i*20,i*10], 1+i*2);
alert("Processed set " + n + " pixels in " + ($.hiresTimer/1000000).toFixed(2) + " seconds");
p.create_layer();
alert("New layer created with new pixels");
Copy link to clipboard
Copied
A much much faster version for the set() function
function RawPixels(doc)
{
this.doc = doc;
var tmp1 = app.preferences.rulerUnits;
var tmp2 = app.activeDocument;
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.red = new Array(this.height);
this.green = new Array(this.height);
this.blue = new Array(this.height);
app.preferences.rulerUnits = tmp1;
try {
var file = new File(Folder.temp.fsName + "/" + Math.random().toString().substr(2) + ".raw");
var d = new ActionDescriptor();
var d1 = new ActionDescriptor();
d1.putString(stringIDToTypeID("fileCreator"), "8BIM");
d1.putBoolean(stringIDToTypeID("channelsInterleaved"), false);
d.putObject(stringIDToTypeID("as"), stringIDToTypeID("rawFormat"), d1);
d.putPath(stringIDToTypeID("in"), file);
d.putBoolean(stringIDToTypeID("copy"), false);
executeAction(stringIDToTypeID("save"), d, DialogModes.NO);
var w = this.width;
var h = this.height;
file.open("r");
file.encoding = "BINARY";
for (var i = 0; i < h; i++) this.red = file.read(w);
for (var i = 0; i < h; i++) this.green = file.read(w);
for (var i = 0; i < h; i++) this.blue = file.read(w);
var err = file.error;
file.close();
file.remove();
file = null;
if (err) alert(err);
}
catch (e) { alert(e); }
app.activeDocument = tmp2;
}
RawPixels.prototype.get = function(x, y)
{
if (y == undefined)
{
y = Math.floor(x/this.width);
x = x - y*this.width;
}
if (y >= this.height) return undefined;
if (x >= this.width) return undefined;
return [ this.red
.charCodeAt(x), this.green .charCodeAt(x), this.blue .charCodeAt(x) ]; }
RawPixels.prototype.set = function(p, x, y)
{
if (y == undefined)
{
y = Math.floor(x/this.width);
x = x - y*this.width;
}
if (y >= this.height) return undefined;
if (x >= this.width) return undefined;
this.red
= this.red .substr(0,x) + String.fromCharCode(p[0]) + this.red .substr(x+1); this.green
= this.green .substr(0,x) + String.fromCharCode(p[1]) + this.green .substr(x+1); this.blue
= this.blue .substr(0,x) + String.fromCharCode(p[2]) + this.blue .substr(x+1); return true;
}
RawPixels.prototype.create_layer = function()
{
try {
var file = new File(Folder.temp.fsName + "/" + Math.random().toString().substr(2) + ".raw");
file.open("w");
file.encoding = "BINARY";
var h = this.height;
for (var i = 0; i < h; i++) file.write(this.red );
for (var i = 0; i < h; i++) file.write(this.green);
for (var i = 0; i < h; i++) file.write(this.blue );
var err = file.error;
file.close();
if (err) { file.remove(); alert(err); return; }
var d = new ActionDescriptor();
d.putPath(stringIDToTypeID("null"), file);
var d1 = new ActionDescriptor();
d1.putInteger(stringIDToTypeID("width"), this.width);
d1.putInteger(stringIDToTypeID("height"), this.height);
d1.putInteger(stringIDToTypeID("channels"), 3);
d1.putBoolean(stringIDToTypeID("channelsInterleaved"), false);
d1.putInteger(stringIDToTypeID("depth"), 8);
d.putObject(stringIDToTypeID("as"), stringIDToTypeID("rawFormat"), d1);
executeAction(stringIDToTypeID("open"), d, DialogModes.NO);
app.activeDocument.activeLayer.duplicate(this.doc.layers[0], ElementPlacement.PLACEBEFORE);
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
app.activeDocument = this.doc;
this.doc.layers[0].name = "Pixels";
file.remove();
}
catch (e) { alert(e); }
}
////////////////////////////////////////////////////////
/// SOME TESTS /////////////////////////////////////////
////////////////////////////////////////////////////////
$.hiresTimer;
var p = new RawPixels(app.activeDocument);
alert("Init RawPixels in " + ($.hiresTimer/1000000).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([1,200,3],0);
alert("New Pixel 0=\n\n" + p.get(0));
$.hiresTimer;
var n = 100000;
for (var i = 0; i < n; i++) p.get(i);
alert("Processed get " + n + " pixels in " + ($.hiresTimer/1000000).toFixed(2) + " seconds");
$.hiresTimer;
var n = 200;
for (var x = 0; x < n; x++)
for (var y = 0; y < n; y++)
p.set([255,20,70], x*2, y*2);
alert("Processed set " + n*n + " pixels in " + ($.hiresTimer/1000000).toFixed(2) + " seconds");
p.create_layer();
alert("New layer created with new pixels");
UPD:
// invert image
$.hiresTimer;
var w = p.width;
var h = p.height;
for (var x = 0; x < w; x++)
for (var y = 0; y < h; y++)
{
var px = p.get(x, y);
px[0] = 255-px[0];
px[1] = 255-px[1];
px[2] = 255-px[2];
p.set(px, x, y);
}
p.create_layer();
alert("Processed get-set " + w*h + " pixels in " + ($.hiresTimer/1000000).toFixed(2) + " seconds");
Copy link to clipboard
Copied
Thx for sharing, one day I will use it for tests