Skip to main content
Inspiring
December 12, 2011
Answered

Determine Light Area vs. Dark Area

  • December 12, 2011
  • 1 reply
  • 3350 views

Here's another unusual one for you.  Is there a way to have Photoshop determine if the majority of a selected area is lighter color or darker.

As an example, some photos have a fairly consistent brightness/darkness across the image, meaning there aren't any areas that are exceptionally dark or bright.  In other cases, a photo might be average brightness over most of the photo with areas of extreme darkness (basically black) so the "average" brightness is brought down quite a bit by that extra dark area even though the majority of the image isn't necessarily that dark.

Is there any way to split these up to get an estimate of just how much of a selected area is extremely dark, how much is mid-toned, and how much is extremely bright?  Thanks!

dgolberg

This topic has been closed for replies.
Correct answer Michael_L_Hale

Could you posterize with 3 levels then read 0,127 & 255 from the histogram?


Following c.pfaffenbichler suggestion you could do something like this to get the pixels below 33 lum ...

var hist = app.activeDocument.histogram;

var count = 0;

var dark = 0;

for( var index = 0; index < 256; index++ ) {

    count = count + hist[ index ];

    if( index < (33*(100/255)) ) dark = dark + hist[ index ];

}

alert("Pixels in selection: " + count + "\rPixels below 33 lum: " + dark +"\rPercent below 33 lum " + ( dark/ count ) * 100 );

You can edit the if index statement to get midtones or highlights or add a couple more if statements to get all three in one pass.

1 reply

dgolbergAuthor
Inspiring
December 12, 2011

You can get a visual representation of what I'm trying to do by going to Filters > Artistic > Cutout, and setting the "Number of Levels" to 3 and the "Edge Simplicity" to 0.  I just need to somehow figure out how much of the picture is made up of the light, how much are the dark, and how much are the mid-tone pixels in this representation and store that info in a variable(s).

Note: The image/selection you use this on should be the same general hue/saturation and only have major variations in brightness to get the desired result.  Alternatively, just de-saturate an image before applying the filter to get a decent representation.

c.pfaffenbichler
Community Expert
Community Expert
December 13, 2011

You could use the Histogram.

Inspiring
December 15, 2011

Messing around with the code some, I noticed the math is a little out of order; so I had to flip 100/255 to 255/100 to get the right read-out.  Also, the "index < (33*(255/100))" is actually the lighter parts rather than the darker parts.  To get the darker parts I did "index > (66*(255/100))".

All testing completed, I end up with the code below to check the percentage of luminosity in the light, mid, and dark tone ranges of the image:

#target photoshop

var hist = app.activeDocument.histogram;

var count = 0;

var dark = 0;

var midtone = 0;

var light = 0;

for( var index = 0; index < 256; index++ ) {

    count = count + hist[ index ];

    if( index < (33*(255/100)) ) light = light + hist[ index ];

    if( index > (66*(255/100)) ) dark = dark + hist[ index ];

    if( index > (33*(255/100)) && index < (66*(255/100)) ) midtone = midtone + hist[ index ];

}

var total = light + dark + midtone;

if (total = count) {

    var darkPer = (dark/total)*100;

    var midPer = (midtone/total)*100;

    var lightPer = (light/total)*100;

    var totalPer = darkPer + lightPer + midPer;

    alert("Dark: " +darkPer+"\rMidtone: "+midPer+"\rLight: "+lightPer+"\rTotal Percent: "+totalPer);

    alert("Pixels in selection: " + count + "\rPixels below 33 lum: " + dark + "\rPixels between 33 & 66 lum: " + midtone + "\rPixels above 66 lum: " + light +"\rPercent below 33 lum: " + ( dark/ count ) * 100);

}

else {

    alert("Some pixels are unaccounted for!");

}

Figured I'd post my findings in case anyone else should need to do something similar.  But now I should be able to extract what I need from the results and make my adjustments accordingly (I just hope my theory works out, otherwise there will likely be another thread for another method in the near future, lol).  Thanks again for the help guys!

Edit: Accidentally had a } in the wrong spot... should be fixed now...


dgolberg wrote:

I noticed the math is a little out of order; so I had to flip 100/255 to 255/100 to get the right read-out.

You are right that the math was out of order but it was not the 100/255. Luminance it from 0 to 100 and the historgram values are always 0 to 255. You need the 100/255 to convert the histogram values to luminance values. However the if statement should have been ...

// convert index to 0-100 scale then compare

if( (index*(100/255)) < 33 )

I was just converting the wrong part of the expression. The if statement above will get you the first 85 histogram elements, which is about 33 lum with rounding. The original if statement only stored the first 13 elements.

Your edits to the math does work because it still converts the wrong part of the expression but it is hard to read. Anything above a luminance of 66 should be light but this seems to count it as dark.