Detect image's overall brightness

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
stevepugh
Posts: 43
Joined: 2008-01-21T12:34:36-07:00

Detect image's overall brightness

Post by stevepugh »

Hi all,

I would like my slate generator to be able to draw text over a variety of images, and want to automatically set my fill color to WHITE when the image is overall dark, and BLACK when the image is overall light.

Is there a way to detect the overall brightness of the image (assuming that my backgrounds are going to be fairly uniform without a lot of variation in brightness) so that I can programatically make this choice?

Many thanks,
Steve
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Detect image's overall brightness

Post by fmw42 »

This was pretty much answered just a few questions earlier in the list. See viewtopic.php?f=1&t=11297 although their question was a bit more involved. In summary, extract the mean value of the image.

If you are using IM 6.4.0-11 or later:

convert <image> -colorspace Gray -format "%[fx:quantumrange*image.mean]" info:


If you are using IM 6.3.9-1 or later

convert <image> -colorspace Gray -format "%[mean]" info:


Or if prior to that:

data=`convert <image> -colorspace gray -verbose info:`
mean=`echo "$data" | sed -n '/^.*[Mm]ean:.*[(]\([0-9.]*\).*$/{ s//\1/; p; q; }'`
convert xc: -format "%[fx:quantumrange*$mean]" info:

All values will be returned in the range of 0 to quantumrange (Q8=255, Q16=65535)


Alternately, if you want your mean value to be returned in the range of 0-1 then use:

convert <image> -colorspace Gray -format "%[fx:image.mean]" info:

or

mean=`convert <image> -colorspace Gray -format "%[mean]" info:`
convert xc: -format "%[fx:$mean/quantumrange]" info:

or

data=`convert <image> -colorspace gray -verbose info:`
echo "$data" | sed -n '/^.*[Mm]ean:.*[(]\([0-9.]*\).*$/{ s//\1/; p; q; }'


One other approach is to resize the image to 1x1 and get its value

convert <image> -colorspace gray -resize 1x1 -format "%[pixel:p{0,0}]" info:

This reports a triple in percent.

or

convert logo: -colorspace gray -resize 1x1 -fx "debug(u)" null:

which reports each channel in range 0-1
stevepugh
Posts: 43
Joined: 2008-01-21T12:34:36-07:00

Re: Detect image's overall brightness

Post by stevepugh »

Darn, I was hoping for a couple different solutions :-)

That's fantastic, thank you!! I feel a bit sheepish not seeing the earlier post, but I did a search for "detect brightness" and didn't turn anything up. My mad search skillz are not that mad after all.

Many thanks again for your response!

Best,
Steve
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Detect image's overall brightness

Post by fmw42 »

Hi Steve,

I bet Anthony will come up with even more ways to skin the cat which will probably be even more elegant/efficient.

Perhaps he should write up all the different ways in his excellent examples as this topic or something akin to it has come up several times now in the past few months. Also one can express the values in range 0-1, 0-100% or 0-QuantumRange, but each person wants it differently.

Fred
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Detect image's overall brightness

Post by anthony »

Note that their is no ideal solution to this the best fill color to use, other than to use two colors, one for the text and the other to outline the text or dim the surrounding image to improve the contrast of the text.
See http://imagemagick.org/Usage/annotate/ for examples of this.

Some solutions is to get a images 'average color, then try to pick the color at the corner of the RGB color space furthest from that color (typically Black and White, but could also be Red, Green, Blue, Maroon, Cyan, or Yellow). but in highly colorfl images even this will fail!

The other difficulty is that unless you run multiple IM commands, with some temporary image files, or use a API interface, it is impossible to set the -fill setting using information of images in memory.

That is you can not in a single command, read in an image, figure out the best color for -fill and set the -fill color, before drawing your text. You will need at least two IM commands, as previously described.

This problem is in the long term FUTURE to do like and will likely be added in the lead up to a IM v7 release, which can have some major differences in the formating of existing options.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply