Giorgio
Giorgio

Reputation: 1613

Walk an image faster

I need to find a particular pixel of an image. Let's say "89 21 24".

I'm using two nested cycles to walk the image:

for( $y=$inity; $y<$h; $y++) {
 for( $x=$initx; $x<$w; $x++) {

   $pixel = getpixelat($img,$x,$y);
   if ($pixel == "892124" and getpixelat($img,$x+1,$y) == "1212224") {
       $px = $x; $py = $y;
       break 2;
   }
}

I'd like to have a faster algorithm by increasing $y and $x not one by one, instead for example 4 by 4. (Sixteen times faster?) Of course I need to know exactly the pixels that build 4x4 square.

I would do it like:

    if ($pixel == "" and nextpixel...) {
        $px = $x - 1; $py = $y -...;
    }
   //etc.

Is there a smarter way to achieve that?

EDIT:

Here's the getpixelat function:

function getpixelat($img,$x,$y) {
$rgb = imagecolorat($img,$x,$y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
return $r.$g.$b;
}

Upvotes: 2

Views: 306

Answers (2)

Thomas
Thomas

Reputation: 2445

1.) avoide nested loops:

2.) save old value of pixle (calling an function is not that fast)

3.) dont convert colors to string/dont compare strings! (what is 1212224? it is not a Hex-Color )

$px=-1;
$py=-1;

$lineW = ($w-$initx);
$lineH = ($h-$inity);
$count = $lineW * $lineH;

$color1 =hexdec ("892124") ;
$color2 =hexdec ("1212224") ;

$x=$initx;
$y=$inity;
$new = imagecolorat($img,$x,$y);

while(true) {
  $x++;
  if ($x>=$w) {
    $x=$initx+1;
    $y++;
    if ($y>=$h) break;
    $new = imagecolorat($img,$x-1,$y);
  }
  $old = $new;
  $new = imagecolorat($img,$x,$y);

  if ($old == $color1 && $new == $color2)
  {
    $px = $x; $py = $y;
    break;
  }
}

(code is not tested :-) )

Upvotes: 1

Wookai
Wookai

Reputation: 21723

If you know that the color you are looking for always appears in patches of at least 2x2, or 3x3, or any fixed size, then yes, you can speed up the lookup by incrementing $x and $y by more than one at each iteration.

For instance, if you know that your patches are always of size at least KxL, you can do the following:

for( $y=$inity; $y<$h; $y += L) {
    for( $x=$initx; $x<$w; $x += K) {
        $pixel = getpixelat($img,$x,$y);

        if ($pixel == "892124" and getpixelat($img,$x+1,$y) == "1212224") {
            $px = $x; $py = $y;
            break 2;
        }
   }
}

Upvotes: 1

Related Questions