On Wed, March 22, 2006 9:18 pm, brian dichiara wrote:
> Is there a way to check to see if a JPEG or PDF is color or
> black/white?
> Like a function or something?

There does not appear to be a built-in function that does that...

However, this hack should work:

function image_is_color($image){
  for ($x = 0, $xmax = imagesx($image); $x < $xmax; $x++){
    for ($y = 0, $ymax = imagesy($image); $y < $ymax; $y++){
      $index = imagecolorat($image, $x, $y);
      list($r, $g, $b) = imagecolorsforindex($image, $index);
      //If all images are TrueColor, the preceding can be replaced with
      // $r = ($index >> 16) & 0xFF;
      // $g = ($index >> 8) & 0xFF;
      // $b = $index & 0xFF;
      // because in TrueColor the index is just the 24-bit color value
      if ($r != $g || $g != $b) return true;
      // You could add || $r != $b, but it's a tautology, no???
    }
  }

  //If we made it here, EVERY damn pixel has R==G==B, so it's grayscale
  return false;
}

NOTE:
This is NOT going to be fast, especially for large images, especially
for large gray-scale images, in which EVERY pixel will get checked
before we know it's grayscale.

If you have MOSTLY grayscale images and a few color, switch around the
true/false and the test and make it is_grayscale() so you can bail out
MUCH faster, when the first few pixels prove an image is NOT what you
usually have.

You could also set up a multi-threaded environment and run is_color
and is_grayscale and then time-out the one that takes forever...  This
might be best if you have humoungous images and you are checking them
in a cron job or something.

Still, if you have an image that's all grayscale, and only the
top-right corner is color, or vice versa, you're gonna wait a long
time...

Hmmmm.

If it's NOT a TrueColor image, and imagecolorstotal() returns a
"small" number, then you could MUCH faster just do:

function is_color($image){
  for ($index = 0, $total = imagecolorstotal($image); $index < $total;
$index++){
    list($r, $g, $b) = imagecolorsforindex($image, $index);
    if ($r != $g || $g != $b) return true;
  }
  return false;
}

Which then makes me think that maybe you should do:
function is_color($image){
  $xmax = imagesx($image);
  $ymax = imagesy($image);
  $count = imagecolorstotal($image);

  if ($count > ($xmax * $ymax)){
    //call my first version, cuz the image is 'small' in x/y size
  }
  else{
    //call my second version, cuz the image has few colors in palette
  }
}

Some benchmarks could be done to refine the test that chooses between
the function bodies -- If imagecolorsforindex() is inherently
slower/faster than imagecolorat() + bit-shifting, then you'd want to
factor in the speed difference.

Have fun!

-- 
Like Music?
http://l-i-e.com/artists.htm

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to