Copy link to clipboard
Copied
hi all,
I need to evaluate/scan all pixels of a given PSD layer via a script. for accessing the R, G, B values I
seached the script reference and found the RGBColor element as
Properties
Property Value type What it is
blue number [0..255] Read-write. The blue color value (default: 255).
green number [0..255] Read-write. The green color value (default: 255)
hexValue string Read-write. The hexadecimal representation of the color.
red number [0..255] Read-write. The red color value (default: 255)
typename string Read-only. The class name of the referenced RGBColor object.
BUT I NEED to evaluate the alpha value of the layer's pixels. where is this value stored?
is it mathematically imbedded in R, G and B?
does anybody has a sample for accessing all pixels of a layer?
thanks for any info and link to a sample script, or any note.
best
stephen
Copy link to clipboard
Copied
These are the values that are available for a selected pixel...
var mySampler = app.activeDocument.colorSamplers.add([new UnitValue( 100,'px'),new UnitValue(100,'px' )]);
var R = Math.round(mySampler.color.rgb.red); //Red Value
var G = Math.round(mySampler.color.rgb.green); //Green value
var B = Math.round(mySampler.color.rgb.blue); // Blue value
var hexColour = "#"+mySampler.color.rgb.hexValue;
var Hue = Math.round(mySampler.color.hsb.hue); //Hue value
var Saturation = Math.round(mySampler.color.hsb.saturation); //Saturation value
var Brightness = Math.round(mySampler.color.hsb.brightness); //Brightness value
var Opacity = activeDocument.activeLayer.opacity; //Layer opacity
Copy link to clipboard
Copied
thanks for your info. may I ask
* how can I determine (calculate) the alpha value of a pixel? the opacity in your formula is the global one of the layer.
* which other opacity values in other photoshop elements also control the final alpha of a pixel? channel?
* is there anything better (more efficient) given to access each pixel in a layer? programming a filter?
many thanks for any feedback!
stephen
Copy link to clipboard
Copied
That is all that is available that I know of, maybe someone knows better and can enlighten us.
For a filter you would have to look at the SDK and the people in this forum may help..
Copy link to clipboard
Copied
One more option is available:
make an opacity mask and then use channel.opacity of the alpha channel
Reading out the value (Range: 0 to 100. Valid only when 'type' = masked area or selected area) for every pixel to get the opacity value of every pixel.
Copy link to clipboard
Copied
Using Apply to the layer's transparency channel to a white alpha channel it a more direct way to access that channel. And the range will be at least 0 - 255 for 8bit RGB images.
But that really doesn't matter. There have been several methods for trying to read the color of every pixel in a document via scripting. Unless the document is very small the script will too slow to be useful. And hang the system at some point with larger images. I will try to find either the scripts( or link to post ) that attempt read that much data. One method uses single pixel selection to get the color. One uses color sampler set to single pixels. And another saves the document to either Photoshop Raw or PBM then reads the pixel data from the file. The script would need make two reading to get the color and transparency for each pixel
Finally, I understand that Photoshop handles transparency differently than rgba. Chris Cox has made several post on the subject. So the transparency channel is not the same as the 'a' channel in an opened document.
Copy link to clipboard
Copied
Mike, this is not the kind of thing I get involved with really but I have used Bridge's BitmapData in other scripts for both AI & ID to read me some HEX colour data out of image files… Have you tried this…? I have no idea how this would compare for speed… How slow is PS at doing this…? lets say 1000 x 1000 pix
Copy link to clipboard
Copied
No, I haven't tried using Bridge. Can you post an example? From a quick look at the Bridge scripting guide, that may be workable for both color and transparency. As someone with a long background in photography I would consider 1000 x 1000 px small but if that method chokes on larger images it might be possible to save the image in tiles and read one tile at a time.
Copy link to clipboard
Copied
Oh yes 1000 x 1000 would be small to me too… Here is a what I have played about with in BR… And used in other scripts… Like I say now idea how this compares… but what I was playing about in AI & ID made this part of the process unimportant… the rest of the other script processes were longer. I was just trying to throw a curve ball you may not have used B4… Of cause this is just for a selected image in BR
#target bridge
getImage();
function getImage() {
var image, bit;
image = app.document.selections[0]; // First item of selection
bit = new BitmapData( image.spec, true ); // Make bitmap data
//bit = bit.resize( bit.height/40, 'bicubicSharper' );
$.writeln( 'Width: ' + bit.width + ' Height: ' + bit.height );
//bit.exportTo( File( Folder.desktop + '/Muppet_Fluff.jpg', 100 ) );
readColorData( bit );
};
//
function readColorData( bitMap ) {
var main, pix, row, x, y;
main = Array();
for ( y = 0; y < bitMap.height; y++ ) {
row = Array();
for ( x = 0; x < bitMap.width; x++ ) {
pix = bitMap.getPixel( x, y );
//row.push( new Color( pix ).toString() ); // This eats up a bit of time…
row.push( new Color( pix ).number );
//row.push( new Color( pix ) );
};
main.push( row );
};
writeImageData( main );
};
//
function writeImageData( data ) {
var txt = File( Folder.desktop + '/Muppet_Fluff.txt' );
txt.open( 'w' );
txt.write( data.toSource() );
txt.close();
};
Copy link to clipboard
Copied
Mmmmmmmmmm I am not sure what Bridge is saying , if you use getPixel() the alpha is always 0 but if you use getPixel32() the alpha does change but so does the rgb.
var image, bit;
image = app.document.selections[0];
bit = new BitmapData( image.spec);
bit = bit.resize( 40, 'bicubicSharper' );
$.writeln( 'Width: ' + bit.width + ' Height: ' + bit.height );
var X = 3;
var Y = 10;
$.writeln("------------");
var colour = new Color( bit.getPixel( X, Y ) ) ;
$.writeln(colour);
$.writeln(colour.red);
$.writeln(colour.blue);
$.writeln(colour.green);
$.writeln(colour.alpha);
$.writeln("------------");
colour = new Color( bit.getPixel32( X, Y ) ) ;
$.writeln(colour);
$.writeln(colour.red);
$.writeln(colour.blue);
$.writeln(colour.green);
$.writeln(colour.alpha);
Copy link to clipboard
Copied
I think that you were thrown off by the fact that the colors are in a different order. They seems correct and I tested quite a few pixel comparing the values to what Photoshop show. Sometimes one or two values would be off by 1 but I think that is a rounding error.
var image, bit;
image = app.document.selections[0];
bit = new BitmapData( image.spec);
//bit = bit.resize( 40, 'bicubicSharper' );// turned off resize to compare Bridge colors to Photoshop. The resize changed the pixel data
$.writeln( 'Width: ' + bit.width + ' Height: ' + bit.height );
var X = 3;
var Y = 10;
$.writeln("------------");
var colour = new Color( bit.getPixel( X, Y ) ) ;// returns RGB as a 24bit number
$.writeln(colour);
$.writeln(colour.red);// colors are correct
$.writeln(colour.blue);
$.writeln(colour.green);
$.writeln(colour.alpha);// I think Color() expects a 32bit number so the high bits are always #00
$.writeln("------------");
colour = new Color( bit.getPixel32( X, Y ) ) ;// returns argb as a 32bit number
$.writeln(colour);
$.writeln(colour.alpha);// still correct but are in a different order
$.writeln(colour.red);
$.writeln(colour.green);
$.writeln(colour.blue);
Copy link to clipboard
Copied
I am not seeing this Mike. The colours are the same if the opacity is 100, but if the opacity is lowered then there is a vast difference, here is one set of results...
Width: 3216 Height: 2144
------------
#003C5232
Red 60
Green 82
Blue 50
Alpha 0
------------
#7880AF6B
Alpha 120
Red 128
Green 175
Blue 107
It does say in the docs that the value is pre-multiplied, does that mean there is an approximation?
Edit: Here is the colorsampler results for the same location..
Red 127.996108949416
Green 175
Blue 107.003891050584
Copy link to clipboard
Copied
It does say in the docs that the value is pre-multiplied,
I missed seeing that, it would have been helpful. So yes that means if there is transparency the getPixel value are off because Photoshop only shows the un-multiplied values.
I think the rounding errors a because alpha it 0.0 - 1.0 and 8bit rgb is 0 - 255.
Mark, I only did limited testing using a small image. It depends on how it scales up but it could be useful if you need to check the transparency for a few pixels. It was late here when I was testing this and I could have something wrong with the loop, but tring to test all the pixels hung ESKT and I was only trying to store a one byte alpha value for each pixel.
Copy link to clipboard
Copied
Resizing to 1024 on the longest side, it takes approx 8 seconds. A fullsize document did complete but took over a minute for me using the code below.
(Writing the Alpha only, converted to 0 - 100 format.)
#target bridge
if( BridgeTalk.appName == "bridge" ) {
alpha2Text = MenuElement.create("command", "Alpha to text", "at the end of Tools","alpha");
}
alpha2Text.onSelect = function () {
try{
var image, bit, main, pix, row, x, y;
image = app.document.selections[0];
bit = new BitmapData( image.spec );
bit = bit.resize( 1024, 'bicubicSharper' );
main = Array();
for ( y = 0; y < bit.height; y++ ) {
row = Array();
for ( x = 0; x < bit.width; x++ ) {
row.push((0.00392156862745 *(new Color( bit.getPixel32( x, y ) ).alpha)).toFixed(2));
};
main.push( row );
}
var txt = File( Folder.desktop +"/"+ decodeURI(image.spec.name).replace(/\....$/,'.txt' ));
txt.open( 'w' );
txt.write( main.toSource() );
txt.close();
}catch(e){alert(e + " - " + e.line);};
alert("Alpha extracted");
};
Copy link to clipboard
Copied
Unless I am still not thinking correctly, wouldn't resizing mean there is no longer a 1:1 pixel relationship to the Bridge data and the origianl size Photoshop document? Or did you only resize for testing speed?
Copy link to clipboard
Copied
Just to test to see how long it would take Mike.
Copy link to clipboard
Copied
Will you see if this runs any faster on your system? My system is an old 32bit Windows and I think it runs out of ram trying to hold all the data in an array. Whatever the reason I can't get either your or the version I tried last night which just used one array to run.
try{
var image, bit, main, pix, row, x, y;
image = app.document.selections[0];
bit = new BitmapData( image.spec );
var txt = File( Folder.desktop +"/"+ decodeURI(image.spec.name).replace(/\....$/,'.txt' ));
txt.open( 'w' );
txt.write('[');
for ( y = 0; y < bit.height; y++ ) {
for ( x = 0; x < bit.width; x++ ) {
txt.write( Number((bit.getPixel32(x, y )>>24)*0.003922).toFixed(2)+',');
}
}
txt.write(']');
txt.close();
}catch(e){alert(e + " - " + e.line);};
alert("Alpha extracted");
Copy link to clipboard
Copied
That runs at least twice as fast Mike.
I am using my laptop I5 with 8gb and Windows 7 64bit.
Copy link to clipboard
Copied
Mike, did you find it of any use… I must admit I did very little in result comparsion… I just tried to use a built-in app method cos my math is hopeless… There is an option about preserving color profile but I don't know how or if this affects results… I'll let you and paul pull it to bits cos you'll probably start going over my head very soon…
Copy link to clipboard
Copied