5

I have a function for trimming white areas around images that works something like

if(imagecolorat($img, $x, $top) != 0xFFFFFF) {
    //sets where the top part of the image is trimmed
}

The problem is some images have an occasional stray pixel that is so near white that it's unnoticeable but screws up the cropping because it's not exactly 0xFFFFFF but 0xFFFEFF or something. How could I rewrite the above statement so that it evaluates true for those near white images, say down to 0xFDFDFD, obviously without testing for ever possible value.

hakre
  • 193,403
  • 52
  • 435
  • 836
L84
  • 974
  • 2
  • 11
  • 21

5 Answers5

6
$color = imagecolorat($img, $x, $top);
$color = array(
    'red'   => ($color >> 16) & 0xFF,
    'green' => ($color >>  8) & 0xFF,
    'blue'  => ($color >>  0) & 0xFF,
);
if ($color['red']   >= 0xFD
 && $color['green'] >= 0xFD
 && $color['blue']  >= 0xFD) {
    //sets where the top part of the image is trimmed
}

For a description of the operators used, please read:

Community
  • 1
  • 1
Alin Roman
  • 287
  • 2
  • 15
  • This isn't working for me. It won't even crop completely white images now. – L84 Oct 31 '12 at 13:35
  • @L84: Probably because you need `<` instead of `>=`. Not only copy and paste the code but try to understand it. If you have an understanding issue, ask in comments. This answer does not contain much description what's done, so there is some "work" for you left. – hakre Oct 31 '12 at 13:40
  • I was trying to test it as quickly as possible so as to accept an answer and not have the question open for no reason. :) – L84 Oct 31 '12 at 13:53
  • Yup, this when it has < instead of >= and I've checked it with FFFFFE and FFFFFC, ignores the former and stops at the latter. Thanks! – L84 Oct 31 '12 at 14:44
4

To detect these off-white colors correctly you should convert from RGB color coordinates to HSV; in HSV, all off-whites have an S near 0 and a V near 100 (normalized). This question has an answer with PHP code to do the conversion, so with that code you 'd have:

$rgb = imagecolorat($img, $x, $top);
$hsv = RBG_TO_HSV(($rgb >> 16) & 0xFF, ($rgb >> 8) & 0xFF, $rgb & 0xFF);
if ($hsv['S'] < .05 && $hsv['V'] > .95) {
    // color is off-white
}

You can tweak the constants .05 and .95 to relax or tighten the criteria as you like; you can also use an interactive color picker (e.g. this) to get a feel for how close to white the colors are for different values of S and V.

Community
  • 1
  • 1
Jon
  • 428,835
  • 81
  • 738
  • 806
0

I think this should do the job:

$range = 0xFFFFFF - 0xFFFEFF;

if((0xFFFEFF - imagecolorat($img, $x, $top)) < $range){
    // do
}
Johannes Mittendorfer
  • 1,102
  • 10
  • 17
0

Here's one way of doing this. Split your colour into its RGB component, so that with $color = 0xFFFEEF you'll end up with $red = 0xff; $green =0xfe; $blue = 0xef'. Then compare each component to your threshold. If all three are within your threshold, then it's "nearly-white". So your function would be something like (pseudo-code):

function is_nearly_white($r, $g, $b) {
    $threshold = 0xfd;
    return ($r > $threshold && $g > $threshold && $b > $threshold);
}
Aleks G
  • 56,435
  • 29
  • 168
  • 265
0

You can detect nearly white by applying an "and" to the RGB integer. Basically it's the same thing that Alin Roman said but a little bit simpler, one line.

if ((imagecolorat($img, $x, $top) & 0xF0F0F0) != 0xF0F0F0) {
    //sets where the top part of the image is trimmed
}

It should detect colors from 0xFFFFFF to 0xF0F0F0.

Apetroaei Andrei
  • 426
  • 4
  • 12