Page 1 of 1

How to determine if image is almost pure white?

Posted: 2007-05-31T06:55:00-07:00
by SSJ
Hi. What's a good way for ImageMagick to determine if an image is almost pure white over an alpha channel?

My site accepts file uploads, including PNGs with an alpha layer. Normally I'd add a white background and save it as a JPEG for web viewing, but if the original image is almost pure white then it would be better to put it on a dark background instead.

My server is running ImageMagick 6.0.7 and I'm executing commands through PHP's exec() function.
Right now I've come up with this method which sort of works:

Code: Select all

# Execute the "identify -verbose" command and store the results in $results
exec("identify -verbose " . $filename, $results);

# Go through and check $results
foreach ($results as $key => $result) {
   if (eregi("Mean:", $result)) {
      # If this $results line contains a Mean value for R, G, or B then store it in an array
      $channel_mean[$i] = str_replace("Mean: ", '', $result);
      $i++;
   }
}

if ($channel_mean[0] > 250 && $channel_mean[1] > 250 && $channel_mean[2] > 250) {
   # It's probably almost completely white since the R, G, and B Mean values are all over 250... so give it a dark background instead of white
}
Some of the problems with this method are:
- It doesn't seem to work on PNG-8 image files
- If the uploaded image is largely blank alpha area with a few specks of color (not necessarily white), it still gets flagged as almost white

Can anyone think of a better way to do this? I'm kind of stuck.

Thanks!

Re: How to determine if image is almost pure white?

Posted: 2007-06-03T21:31:00-07:00
by anthony
There are a number way to get the average color of an image, but they generally assume the image has no transparency or matte channel.

I suggest you do the following.

Code: Select all

  convert image.png \
         \( -clone 0 -background white -flatten \) \
         \( -clone 0 -background black -flatten \) \
         -delete 0 -scale 1x1\! txt:
This will produce the average colors of the image on a white background and a black background.
If the results was the same, you have no transparency. If the first is very white
you image is mostly white. If the second is very black, you have mostly black. If both is the case you have an image which is basically ALL opaque.

In your case just pick the one with the largest difference, to the background color added.

If you want you can add a -colorspace Gray before the first parenthesis to leave the result as just a grey scale value. However this will not improve IMs performance, as IM still deals with the images as purely RGB values, not a single grayscale channel.

The alturnative is to get a histogram of the image, and average the non-transparent colors yourself. This may even be faster than the above
as scaling can take some time, but needs you to do the work in the API you are using....
for example this

Code: Select all

convert image.png -format %c histogram:info:- | grep -v rgba
will list all the purely opaque colors in the image, and the pixel counts. You only need to add average the colors (somehow) to get a more exact result.