Copy link to clipboard
Copied
Hi, I have made an exercise that can be usefull to someone.
On a active image, it builds and draws the histograms on several layers.
This works only on RGB images and if they have more than 8bits/channel, it will reduce to 8bit/channel before proced.
I used this on windows 10 and CC(2017)
Enjoy or complete and develop it as you want.
This next code will build 4 layers
1 - the 3 rgb channels coloured histogram
2 - the Max(
3 - the 8bit Lightness channel Lab histogram (the image will be reverted again to RGB afterwards)
4 - 8bit Luminosity RGB histogram
addHistogram(true); // this draws a layer with a coloured 8bit RGB histogram
addHistogram(false, false, true); // this draws the Max(
, , ) Luminosity RGB histogram (gets the max value of each channel) addHistogram(false, true); // this draws a layer with 8bit Lightness channel Lab histogram
addHistogram(false, false); // this draws a layer with 8bit Luminosity RGB histogram
/////////////////////////////// HISTOGRAM IN LAYER ///////////////////////////////////
function addHistogram(RGB, Lab, MaxRGB) {
///////////////////////////////////////////////// createProgressWindow
var createProgressWindow = function(title, message, hasCancelButton) {
var win;
if (title == null) title = "Work in progress";
if (message == null) message = "Please wait...";
if (hasCancelButton == null) hasCancelButton = false;
win = new Window("palette", "" + title, undefined);
win.bar = win.add("progressbar", {x: 20, y: 12, width: 300, height: 20 }, 0, 100);
win.stMessage = win.add("statictext", { x: 10, y: 36, width: 320, height: 20 }, "" + message);
win.stMessage.justify = 'center';
if (hasCancelButton) {
win.cancelButton = win.add('button', undefined, 'Cancel');
win.cancelButton.onClick = function() {
win.close();
throw new Error('User canceled the pre-processing!');
};
}
this.reset = function(message) {
win.bar.value = 0;
win.stMessage.text = message;
return win.update();
};
this.updateProgress = function(perc, message) {
if (perc != null) win.bar.value = perc;
if (message != null) win.stMessage.text = message;
return win.update();
};
this.close = function() {
return win.close();
};
win.center(win.parent);
return win.show();
};
//
// the other layer histograms, if exist, should be invisible so the reading is only on the pixels of the image itself
if (getLayer("RGB histogram")) activeDocument.artLayers.getByName ("RGB histogram").visible = false;
if (getLayer("Lightness Lab histogram")) activeDocument.artLayers.getByName ("Lightness Lab histogram").visible = false;
if (getLayer("Luminosity RGB")) activeDocument.artLayers.getByName ("Luminosity RGB").visible = false;
if (getLayer("Luminosity Max
")) activeDocument.artLayers.getByName ("Luminosity Max ").visible = false; //
var layerName = (RGB) ? "RGB histogram" : ((Lab) ? "Lightness Lab histogram" : ((MaxRGB) ? "Luminosity Max
" : "Luminosity RGB")); //
if (!getLayer(layerName)) {
// it works only on RGB images
if (activeDocument.mode == DocumentMode.RGB) {
// if the image is 16bit/channel or more it sets 8bits/channel before read the histogram
if (!activeDocument.bitsPerChannel == BitsPerChannelType.EIGHT) activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;
$.writeln(layerName);
var wasHereLayer = activeDocument.activeLayer;
var unitsAntes = app.preferences.rulerUnits;
var foregroundPreviousColor = app.foregroundColor;
app.preferences.rulerUnits = Units.PIXELS; // importante
activeDocument.quickMaskMode = false;
activeDocument.selection.deselect();
//
// read histogram:
var hL = activeDocument.histogram;
var hR = activeDocument.channels["Red"].histogram;
var hG = activeDocument.channels["Green"].histogram;
var hB = activeDocument.channels["Blue"].histogram;
// if you want the Luminosity of Lab, export it to Lab, read it, and revert it to RGB
if (Lab) {
activeDocument.changeMode (ChangeMode.LAB);
// read Lightness channel histogram of Lab
var hL = activeDocument.channels["Lightness"].histogram;
// revert to RGB
activeDocument.changeMode (ChangeMode.RGB);
} else {
// read Luminosity composite channel histogram of RGB
var hL = activeDocument.histogram;
}
//
var ww = activeDocument.width.as('px');
var hh = activeDocument.height.as('px');
var totalPixels = ww*hh;
var totalPixels1Col = totalPixels/256;
//
var pBar = new createProgressWindow("Histogram building...", "Please wait", false);
//
activeDocument.artLayers.add();
activeDocument.activeLayer.name = layerName;
activeDocument.activeLayer.move( activeDocument, ElementPlacement.PLACEATBEGINNING );
activeDocument.activeLayer.blendMode = BlendMode.NORMAL; // blending mode "normal"
activeDocument.activeLayer.opacity = 60; // opacity 60%
//
var hhGraph = 60;
var hY = 400; // base y of graph
var hX = 100; // base x of graph
// base transparent
app.foregroundColor.rgb.red = 0;
app.foregroundColor.rgb.green = 0;
app.foregroundColor.rgb.blue = 0;
//
drawSelectionScreen (hX-2, hY+2, 258+hX, hY-322);
// fill (filltype [, mode] [, opacity] [, preserveTransparency]) // filltype: SolidColor | mode: ColorBlendMode | opacity: [1..100]
app.activeDocument.selection.fill(app.foregroundColor, ColorBlendMode.SCREEN, 40, false);
activeDocument.selection.deselect();
//
var myHist = [];
//
if (RGB) {
for (var a in activeDocument.componentChannels) {
// criar as 3 cores R, G e B e o graph da cada uma
(a==0) ? app.foregroundColor.rgb.red = 255 : app.foregroundColor.rgb.red = 0;
(a==1) ? app.foregroundColor.rgb.green = 255 : app.foregroundColor.rgb.green = 0;
(a==2) ? app.foregroundColor.rgb.blue = 255 : app.foregroundColor.rgb.blue = 0;
//
if (a==0) myHist = hR;
if (a==1) myHist = hG;
if (a==2) myHist = hB;
//
for ( i = 0; i <= 255; i++ ) {
var col = i+hX;
var YYY = Math.min(Math.floor(myHist*hhGraph/totalPixels1Col), 320);
drawSelectionScreen (col, hY, col+1, hY-YYY);
//
var percent = Math.floor(((i+1)+(a*256))*100/768);
pBar.updateProgress (percent, activeDocument.componentChannels.name.toUpperCase() + " Channel " + percent+ " % completed");
}
// fill (filltype [, mode] [, opacity] [, preserveTransparency]) // filltype: SolidColor | mode: ColorBlendMode | opacity: [1..100]
app.activeDocument.selection.fill(app.foregroundColor, ColorBlendMode.SCREEN, 100, false);
activeDocument.selection.deselect();
}
} else {
app.foregroundColor.rgb.red = 255;
app.foregroundColor.rgb.green = 255;
app.foregroundColor.rgb.blue = 255;
myHist = hL;
for ( i = 0; i <= 255; i++ ) {
var col = i+hX;
if (MaxRGB) {
var YYY = Math.min(Math.floor(Math.max(hR, hG, hB)*hhGraph/totalPixels1Col), 320);
} else {
var YYY = Math.min(Math.floor(myHist*hhGraph/totalPixels1Col), 320);
}
drawSelectionScreen (col, hY, col+1, hY-YYY);
//
var percent = Math.floor((i+1)*100/256);
pBar.updateProgress (percent, "Luminosity Channel " + percent+ " % completed");
}
// fill (filltype [, mode] [, opacity] [, preserveTransparency]) // filltype: SolidColor | mode: ColorBlendMode | opacity: [1..100]
app.activeDocument.selection.fill(app.foregroundColor, ColorBlendMode.SCREEN, 100, false);
activeDocument.selection.deselect();
}
pBar.close();
// activeDocument.activeLayer = wasHereLayer;
app.preferences.rulerUnits = unitsAntes;
app.foregroundColor = foregroundPreviousColor;
$.gc();
} else {
alert("Must be an RGB image");
}
} else {
alert("Already has created this '" + layerName + "' layer!");
return;
}
function drawSelectionScreen(x1, y1, x2, y2) {
$.level = 0;
try {
// SelectionType.SELECTEDAREA | DIMINISH | EXTEND | INTERSECT | REPLACE
activeDocument.selection.select([[ x1, y1], [x2, y1], [x2, y2], [x1,y2]], SelectionType.EXTEND, 0, false);
} catch(e) {}
$.level = 1;
}
function drawLineScreen(x1, y1, x2, y2, width, transparency) {
$.level = 0;
try {
var desc = new ActionDescriptor();
var lineDesc = new ActionDescriptor();
var startDesc = new ActionDescriptor();
startDesc.putUnitDouble( charIDToTypeID('Hrzn'), charIDToTypeID('#Pxl'), x1 );
startDesc.putUnitDouble( charIDToTypeID('Vrtc'), charIDToTypeID('#Pxl'), y1 );
lineDesc.putObject( charIDToTypeID('Strt'), charIDToTypeID('Pnt '), startDesc );
var endDesc = new ActionDescriptor();
endDesc.putUnitDouble( charIDToTypeID('Hrzn'), charIDToTypeID('#Pxl'), x2 );
endDesc.putUnitDouble( charIDToTypeID('Vrtc'), charIDToTypeID('#Pxl'), y2 );
lineDesc.putObject( charIDToTypeID('End '), charIDToTypeID('Pnt '), endDesc );
lineDesc.putUnitDouble( charIDToTypeID('Wdth'), charIDToTypeID('#Pxl'), width ); //
desc.putObject( charIDToTypeID('Shp '), charIDToTypeID('Ln '), lineDesc );
desc.putEnumerated( charIDToTypeID( "Md " ), charIDToTypeID( "BlnM" ), charIDToTypeID( "Scrn" ) ); // mode: Screen
desc.putUnitDouble( charIDToTypeID( "Opct" ), charIDToTypeID( "#Prc" ), transparency ); // [0-100] transparency
desc.putBoolean( charIDToTypeID('AntA'), false ); // important antialias should be false
executeAction( charIDToTypeID('Draw'), desc, DialogModes.NO );
} catch(e) {}
$.level = 1;
}
//////////////////////////////////
function getLayer(layername) {
var result = false;
for (var a=0; a<activeDocument.artLayers.length ; a++) {
if (String(activeDocument.artLayers.name) == layername) {
result = true;
break;
}
}
return result;
}
}
Copy link to clipboard
Copied
It worked perfectly on CS6 EXTENDED!
That new createProgressWindow() is something new for me I like visible incement. It works very fast (as far as panels are hidden, but that's normal). The end result makes only last layer is visible. Shouldn't all be checked? Anyway that is ok too
Copy link to clipboard
Copied
Hi,
I the function I created, I put all the existing histograms invisible so the next histogram when being created, it should not be affected by the colors added to the image from the previous histograms.
Resume: the histograms should be build on the image colors and not the layer colors of the histograms.
In the end, the last histogram created should be visible and the previous invisible.
Copy link to clipboard
Copied
Is it possible to do this for video footage?
Copy link to clipboard
Copied
I don't know if I understand the question.
You mean video within photoshop where you can get the histogram at any frame?
That should work in a single stoped frame.
In the meantime I have found that it is much faster to draw the histogram in a layer creating first all the vector data by code and on the layer 1 time in the end for each channel.
When I have time I can update the code.
Copy link to clipboard
Copied
Is it possible to do this in After Effects for Video footage
Copy link to clipboard
Copied
I only have very few scripts tested in AE and the histogram is not one of them.
If it is possible, I do not know.
May be the histogram data could be passed to an external JSON file and converted outside to a svg using uts RGB colors objects to mix has 'screen' colors mode (possible in SVG css)
Then I do not know AE enough to know if you can import a svg image into a frame by code...
Sorry, I can't help more.
Copy link to clipboard
Copied
Script works, but for those who want histogram for not transparent pixels, modify this script to make selection first (selection without transparent pixels by: Selection->Load->from transparency).
Or use HSB/HSL filter from Win_Optional_Plug-Ins.zip which surely works on selections - above didnt ( it may require more modifications).
Copy link to clipboard
Copied
Thank you very much for sharing this... I was looking for something similar.
Copy link to clipboard
Copied
Hey Pedro! Thank you for this wonderful script. Unfortunately it does not work for me on PS 2020 and i can't find out why. Stays just silent.
Copy link to clipboard
Copied
addHistogram(true); // this draws a layer with a coloured 8bit RGB histogram
//addHistogram(false, false, true); // this draws the Max(, , ) Luminosity RGB histogram (gets the max value of each channel)
//addHistogram(false, true); // this draws a layer with 8bit Lightness channel Lab histogram
//addHistogram(false, false); // this draws a layer with 8bit Luminosity RGB histogram
/////////////////////////////// HISTOGRAM IN LAYER ///////////////////////////////////
function addHistogram(RGB, Lab, MaxRGB) {
///////////////////////////////////////////////// createProgressWindow
var createProgressWindow = function(title, message, hasCancelButton) {
var win;
if (title == null) title = "Work in progress";
if (message == null) message = "Please wait...";
if (hasCancelButton == null) hasCancelButton = false;
win = new Window("palette", "" + title, undefined);
win.bar = win.add("progressbar", {x: 20, y: 12, width: 300, height: 20 }, 0, 100);
win.stMessage = win.add("statictext", { x: 10, y: 36, width: 320, height: 20 }, "" + message);
win.stMessage.justify = 'center';
if (hasCancelButton) {
win.cancelButton = win.add('button', undefined, 'Cancel');
win.cancelButton.onClick = function() {
win.close();
throw new Error('User canceled the pre-processing!');
};
}
this.reset = function(message) {
win.bar.value = 0;
win.stMessage.text = message;
return win.update();
};
this.updateProgress = function(perc, message) {
if (perc != null) win.bar.value = perc;
if (message != null) win.stMessage.text = message;
return win.update();
};
this.close = function() {
return win.close();
};
win.center(win.parent);
return win.show();
};
//
// the other layer histograms, if exist, should be invisible so the reading is only on the pixels of the image itself
if (getLayer("RGB histogram")) activeDocument.artLayers.getByName ("RGB histogram").visible = false;
if (getLayer("Lightness Lab histogram")) activeDocument.artLayers.getByName ("Lightness Lab histogram").visible = false;
if (getLayer("Luminosity RGB")) activeDocument.artLayers.getByName ("Luminosity RGB").visible = false;
if (getLayer("Luminosity Max")) activeDocument.artLayers.getByName ("Luminosity Max").visible = false;
//
var layerName = (RGB) ? "RGB histogram" : ((Lab) ? "Lightness Lab histogram" : ((MaxRGB) ? "Luminosity Max" : "Luminosity RGB"));
//
if (!getLayer(layerName)) {
// it works only on RGB images
if (activeDocument.mode == DocumentMode.RGB) {
// if the image is 16bit/channel or more it sets 8bits/channel before read the histogram
if (!activeDocument.bitsPerChannel == BitsPerChannelType.EIGHT) activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;
var wasHereLayer = activeDocument.activeLayer;
var unitsAntes = app.preferences.rulerUnits;
var foregroundPreviousColor = app.foregroundColor;
app.preferences.rulerUnits = Units.PIXELS; // importante
activeDocument.quickMaskMode = false;
activeDocument.selection.deselect();
//
// read histogram:
var hL = activeDocument.histogram;
var hR = activeDocument.channels["Red"].histogram;
var hG = activeDocument.channels["Green"].histogram;
var hB = activeDocument.channels["Blue"].histogram;
// if you want the Luminosity of Lab, export it to Lab, read it, and revert it to RGB
if (Lab) {
activeDocument.changeMode (ChangeMode.LAB);
// read Lightness channel histogram of Lab
var hL = activeDocument.channels["Lightness"].histogram;
// revert to RGB
activeDocument.changeMode (ChangeMode.RGB);
} else {
// read Luminosity composite channel histogram of RGB
var hL = activeDocument.histogram;
}
//
var ww = activeDocument.width.as('px');
var hh = activeDocument.height.as('px');
var totalPixels = ww*hh;
var totalPixels1Col = totalPixels/256;
//
var pBar = new createProgressWindow("Histogram building...", "Please wait", false);
//
activeDocument.artLayers.add();
activeDocument.activeLayer.name = layerName;
activeDocument.activeLayer.move( activeDocument, ElementPlacement.PLACEATBEGINNING );
activeDocument.activeLayer.blendMode = BlendMode.NORMAL; // blending mode "normal"
activeDocument.activeLayer.opacity = 60; // opacity 60%
//
var hhGraph = 60;
var hY = 400; // base y of graph
var hX = 100; // base x of graph
// base transparent
app.foregroundColor.rgb.red = 0;
app.foregroundColor.rgb.green = 0;
app.foregroundColor.rgb.blue = 0;
//
drawSelectionScreen (hX-2, hY+2, 258+hX, hY-322);
// fill (filltype [, mode] [, opacity] [, preserveTransparency]) // filltype: SolidColor | mode: ColorBlendMode | opacity: [1..100]
app.activeDocument.selection.fill(app.foregroundColor, ColorBlendMode.SCREEN, 40, false);
activeDocument.selection.deselect();
//
var myHist = [];
//
if (RGB) {
for (var a in activeDocument.componentChannels) {
// criar as 3 cores R, G e B e o graph da cada uma
(a==0) ? app.foregroundColor.rgb.red = 255 : app.foregroundColor.rgb.red = 0;
(a==1) ? app.foregroundColor.rgb.green = 255 : app.foregroundColor.rgb.green = 0;
(a==2) ? app.foregroundColor.rgb.blue = 255 : app.foregroundColor.rgb.blue = 0;
//
if (a==0) myHist = hR;
if (a==1) myHist = hG;
if (a==2) myHist = hB;
//
for ( i = 0; i <= 255; i++ ) {
var col = i+hX;
var YYY = Math.min(Math.floor(myHist[i]*hhGraph/totalPixels1Col), 320);
drawSelectionScreen (col, hY, col+1, hY-YYY);
//
var percent = Math.floor(((i+1)+(a*256))*100/768);
pBar.updateProgress (percent, activeDocument.componentChannels[a].name.toUpperCase() + " Channel " + percent+ " % completed");
}
// fill (filltype [, mode] [, opacity] [, preserveTransparency]) // filltype: SolidColor | mode: ColorBlendMode | opacity: [1..100]
app.activeDocument.selection.fill(app.foregroundColor, ColorBlendMode.SCREEN, 100, false);
activeDocument.selection.deselect();
}
} else {
app.foregroundColor.rgb.red = 255;
app.foregroundColor.rgb.green = 255;
app.foregroundColor.rgb.blue = 255;
myHist = hL;
for ( i = 0; i <= 255; i++ ) {
var col = i+hX;
if (MaxRGB) {
var YYY = Math.min(Math.floor(Math.max(hR[i], hG[i], hB[i])*hhGraph/totalPixels1Col), 320);
} else {
var YYY = Math.min(Math.floor(myHist[i]*hhGraph/totalPixels1Col), 320);
}
drawSelectionScreen (col, hY, col+1, hY-YYY);
//
var percent = Math.floor((i+1)*100/256);
pBar.updateProgress (percent, "Luminosity Channel " + percent+ " % completed");
}
// fill (filltype [, mode] [, opacity] [, preserveTransparency]) // filltype: SolidColor | mode: ColorBlendMode | opacity: [1..100]
app.activeDocument.selection.fill(app.foregroundColor, ColorBlendMode.SCREEN, 100, false);
activeDocument.selection.deselect();
}
pBar.close();
// activeDocument.activeLayer = wasHereLayer;
app.preferences.rulerUnits = unitsAntes;
app.foregroundColor = foregroundPreviousColor;
} else {
alert("Must be an RGB image");
}
} else {
alert("Already has created this '" + layerName + "' layer!");
return;
}
function drawSelectionScreen(x1, y1, x2, y2) {
try {
// SelectionType.SELECTEDAREA | DIMINISH | EXTEND | INTERSECT | REPLACE
activeDocument.selection.select([[ x1, y1], [x2, y1], [x2, y2], [x1,y2]], SelectionType.EXTEND, 0, false);
} catch(e) {}
}
function drawLineScreen(x1, y1, x2, y2, width, transparency) {
try {
var desc = new ActionDescriptor();
var lineDesc = new ActionDescriptor();
var startDesc = new ActionDescriptor();
startDesc.putUnitDouble( charIDToTypeID('Hrzn'), charIDToTypeID('#Pxl'), x1 );
startDesc.putUnitDouble( charIDToTypeID('Vrtc'), charIDToTypeID('#Pxl'), y1 );
lineDesc.putObject( charIDToTypeID('Strt'), charIDToTypeID('Pnt '), startDesc );
var endDesc = new ActionDescriptor();
endDesc.putUnitDouble( charIDToTypeID('Hrzn'), charIDToTypeID('#Pxl'), x2 );
endDesc.putUnitDouble( charIDToTypeID('Vrtc'), charIDToTypeID('#Pxl'), y2 );
lineDesc.putObject( charIDToTypeID('End '), charIDToTypeID('Pnt '), endDesc );
lineDesc.putUnitDouble( charIDToTypeID('Wdth'), charIDToTypeID('#Pxl'), width ); //
desc.putObject( charIDToTypeID('Shp '), charIDToTypeID('Ln '), lineDesc );
desc.putEnumerated( charIDToTypeID( "Md " ), charIDToTypeID( "BlnM" ), charIDToTypeID( "Scrn" ) ); // mode: Screen
desc.putUnitDouble( charIDToTypeID( "Opct" ), charIDToTypeID( "#Prc" ), transparency ); // [0-100] transparency
desc.putBoolean( charIDToTypeID('AntA'), false ); // important antialias should be false
executeAction( charIDToTypeID('Draw'), desc, DialogModes.NO );
} catch(e) {}
}
//////////////////////////////////
function getLayer(layername) {
var result = false;
for (var a=0; a<activeDocument.artLayers.length ; a++) {
if (String(activeDocument.artLayers[a].name) == layername) {
result = true;
break;
}
}
return result;
}
}
Copy link to clipboard
Copied
Hi R-Bin! Thanks for the quick reply. Unfortunately still doesn't work for me. Gives me the spinning cursor for a second or two but that´s it. No histogram layer. Trying this from a pixel layer (copy of the background layer)
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Double checked but does not work. Will update from 21.2.0 to 21.2.3. and see what will happen. Thanks again!
Copy link to clipboard
Copied
I recently debugged this script with estk and the probem is that the channel names are in english but i use the german version of PS. Of course i can translate that and it works fine then. But is there any way to make this work in all languages?
Copy link to clipboard
Copied
Use numbers, so 0 or 1 or 2 instead of another RGB or LAB 'colors'.
Copy link to clipboard
Copied
It also works on 21.2.3 (Win10)
Copy link to clipboard
Copied
Das hier sollte sprachunabhängig funktionieren:
#target photoshop
addHistogram(true); // this draws a layer with a coloured 8bit RGB histogram
addHistogram(false, false, true); // this draws the Max([R], [G], [B]) Luminosity RGB histogram (gets the max value of each channel)
addHistogram(false, true); // this draws a layer with 8bit Lightness channel Lab histogram
addHistogram(false, false); // this draws a layer with 8bit Luminosity RGB histogram
/////////////////////////////// HISTOGRAM IN LAYER ///////////////////////////////////
function addHistogram(RGB, Lab, MaxRGB) {
///////////////////////////////////////////////// createProgressWindow
var createProgressWindow = function(title, message, hasCancelButton) {
var win;
if (title == null) title = "Work in progress";
if (message == null) message = "Please wait...";
if (hasCancelButton == null) hasCancelButton = false;
win = new Window("palette", "" + title, undefined);
win.bar = win.add("progressbar", {x: 20, y: 12, width: 300, height: 20 }, 0, 100);
win.stMessage = win.add("statictext", { x: 10, y: 36, width: 320, height: 20 }, "" + message);
win.stMessage.justify = 'center';
if (hasCancelButton) {
win.cancelButton = win.add('button', undefined, 'Cancel');
win.cancelButton.onClick = function() {
win.close();
throw new Error('User canceled the pre-processing!');
};
}
this.reset = function(message) {
win.bar.value = 0;
win.stMessage.text = message;
return win.update();
};
this.updateProgress = function(perc, message) {
if (perc != null) win.bar.value = perc;
if (message != null) win.stMessage.text = message;
return win.update();
};
this.close = function() {
return win.close();
};
win.center(win.parent);
return win.show();
};
//
// the other layer histograms, if exist, should be invisible so the reading is only on the pixels of the image itself
if (getLayer("RGB histogram")) activeDocument.artLayers.getByName ("RGB histogram").visible = false;
if (getLayer("Lightness Lab histogram")) activeDocument.artLayers.getByName ("Lightness Lab histogram").visible = false;
if (getLayer("Luminosity RGB")) activeDocument.artLayers.getByName ("Luminosity RGB").visible = false;
if (getLayer("Luminosity Max[R][G][B]")) activeDocument.artLayers.getByName ("Luminosity Max[R][G][B]").visible = false;
//
var layerName = (RGB) ? "RGB histogram" : ((Lab) ? "Lightness Lab histogram" : ((MaxRGB) ? "Luminosity Max[R][G][B]" : "Luminosity RGB"));
//
if (!getLayer(layerName)) {
// it works only on RGB images
if (activeDocument.mode == DocumentMode.RGB) {
// if the image is 16bit/channel or more it sets 8bits/channel before read the histogram
if (!activeDocument.bitsPerChannel == BitsPerChannelType.EIGHT) activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;
$.writeln(layerName);
var wasHereLayer = activeDocument.activeLayer;
var unitsAntes = app.preferences.rulerUnits;
var foregroundPreviousColor = app.foregroundColor;
app.preferences.rulerUnits = Units.PIXELS; // importante
activeDocument.quickMaskMode = false;
activeDocument.selection.deselect();
//
// read histogram:
var hL = activeDocument.histogram;
var hR = activeDocument.channels[0].histogram;
var hG = activeDocument.channels[1].histogram;
var hB = activeDocument.channels[2].histogram;
// if you want the Luminosity of Lab, export it to Lab, read it, and revert it to RGB
if (Lab) {
activeDocument.changeMode (ChangeMode.LAB);
// read Lightness channel histogram of Lab
var hL = activeDocument.channels[0].histogram;
// revert to RGB
activeDocument.changeMode (ChangeMode.RGB);
} else {
// read Luminosity composite channel histogram of RGB
var hL = activeDocument.histogram;
}
//
var ww = activeDocument.width.as('px');
var hh = activeDocument.height.as('px');
var totalPixels = ww*hh;
var totalPixels1Col = totalPixels/256;
//
var pBar = new createProgressWindow("Histogram building...", "Please wait", false);
//
activeDocument.artLayers.add();
activeDocument.activeLayer.name = layerName;
activeDocument.activeLayer.move( activeDocument, ElementPlacement.PLACEATBEGINNING );
activeDocument.activeLayer.blendMode = BlendMode.NORMAL; // blending mode "normal"
activeDocument.activeLayer.opacity = 60; // opacity 60%
//
var hhGraph = 60;
var hY = 400; // base y of graph
var hX = 100; // base x of graph
// base transparent
app.foregroundColor.rgb.red = 0;
app.foregroundColor.rgb.green = 0;
app.foregroundColor.rgb.blue = 0;
//
drawSelectionScreen (hX-2, hY+2, 258+hX, hY-322);
// fill (filltype [, mode] [, opacity] [, preserveTransparency]) // filltype: SolidColor | mode: ColorBlendMode | opacity: [1..100]
app.activeDocument.selection.fill(app.foregroundColor, ColorBlendMode.SCREEN, 40, false);
activeDocument.selection.deselect();
//
var myHist = [];
//
if (RGB) {
for (var a in activeDocument.componentChannels) {
// criar as 3 cores R, G e B e o graph da cada uma
(a==0) ? app.foregroundColor.rgb.red = 255 : app.foregroundColor.rgb.red = 0;
(a==1) ? app.foregroundColor.rgb.green = 255 : app.foregroundColor.rgb.green = 0;
(a==2) ? app.foregroundColor.rgb.blue = 255 : app.foregroundColor.rgb.blue = 0;
//
if (a==0) myHist = hR;
if (a==1) myHist = hG;
if (a==2) myHist = hB;
//
for ( i = 0; i <= 255; i++ ) {
var col = i+hX;
var YYY = Math.min(Math.floor(myHist[i]*hhGraph/totalPixels1Col), 320);
drawSelectionScreen (col, hY, col+1, hY-YYY);
//
var percent = Math.floor(((i+1)+(a*256))*100/768);
pBar.updateProgress (percent, activeDocument.componentChannels[a].name.toUpperCase() + " Channel " + percent+ " % completed");
}
// fill (filltype [, mode] [, opacity] [, preserveTransparency]) // filltype: SolidColor | mode: ColorBlendMode | opacity: [1..100]
app.activeDocument.selection.fill(app.foregroundColor, ColorBlendMode.SCREEN, 100, false);
activeDocument.selection.deselect();
}
} else {
app.foregroundColor.rgb.red = 255;
app.foregroundColor.rgb.green = 255;
app.foregroundColor.rgb.blue = 255;
myHist = hL;
for ( i = 0; i <= 255; i++ ) {
var col = i+hX;
if (MaxRGB) {
var YYY = Math.min(Math.floor(Math.max(hR[i], hG[i], hB[i])*hhGraph/totalPixels1Col), 320);
} else {
var YYY = Math.min(Math.floor(myHist[i]*hhGraph/totalPixels1Col), 320);
}
drawSelectionScreen (col, hY, col+1, hY-YYY);
//
var percent = Math.floor((i+1)*100/256);
pBar.updateProgress (percent, "Luminosity Channel " + percent+ " % completed");
}
// fill (filltype [, mode] [, opacity] [, preserveTransparency]) // filltype: SolidColor | mode: ColorBlendMode | opacity: [1..100]
app.activeDocument.selection.fill(app.foregroundColor, ColorBlendMode.SCREEN, 100, false);
activeDocument.selection.deselect();
}
pBar.close();
// activeDocument.activeLayer = wasHereLayer;
app.preferences.rulerUnits = unitsAntes;
app.foregroundColor = foregroundPreviousColor;
$.gc();
} else {
alert("Must be an RGB image");
}
} else {
alert("Already has created this '" + layerName + "' layer!");
return;
}
function drawSelectionScreen(x1, y1, x2, y2) {
$.level = 0;
try {
// SelectionType.SELECTEDAREA | DIMINISH | EXTEND | INTERSECT | REPLACE
activeDocument.selection.select([[ x1, y1], [x2, y1], [x2, y2], [x1,y2]], SelectionType.EXTEND, 0, false);
} catch(e) {}
$.level = 1;
}
function drawLineScreen(x1, y1, x2, y2, width, transparency) {
$.level = 0;
try {
var desc = new ActionDescriptor();
var lineDesc = new ActionDescriptor();
var startDesc = new ActionDescriptor();
startDesc.putUnitDouble( charIDToTypeID('Hrzn'), charIDToTypeID('#Pxl'), x1 );
startDesc.putUnitDouble( charIDToTypeID('Vrtc'), charIDToTypeID('#Pxl'), y1 );
lineDesc.putObject( charIDToTypeID('Strt'), charIDToTypeID('Pnt '), startDesc );
var endDesc = new ActionDescriptor();
endDesc.putUnitDouble( charIDToTypeID('Hrzn'), charIDToTypeID('#Pxl'), x2 );
endDesc.putUnitDouble( charIDToTypeID('Vrtc'), charIDToTypeID('#Pxl'), y2 );
lineDesc.putObject( charIDToTypeID('End '), charIDToTypeID('Pnt '), endDesc );
lineDesc.putUnitDouble( charIDToTypeID('Wdth'), charIDToTypeID('#Pxl'), width ); //
desc.putObject( charIDToTypeID('Shp '), charIDToTypeID('Ln '), lineDesc );
desc.putEnumerated( charIDToTypeID( "Md " ), charIDToTypeID( "BlnM" ), charIDToTypeID( "Scrn" ) ); // mode: Screen
desc.putUnitDouble( charIDToTypeID( "Opct" ), charIDToTypeID( "#Prc" ), transparency ); // [0-100] transparency
desc.putBoolean( charIDToTypeID('AntA'), false ); // important antialias should be false
executeAction( charIDToTypeID('Draw'), desc, DialogModes.NO );
} catch(e) {}
$.level = 1;
}
//////////////////////////////////
function getLayer(layername) {
var result = false;
for (var a=0; a<activeDocument.artLayers.length ; a++) {
if (String(activeDocument.artLayers[a].name) == layername) {
result = true;
break;
}
}
return result;
}
}
Copy link to clipboard
Copied
Perfekt! Vielen Dank Tom! 🙂
Copy link to clipboard
Copied
What about this?