Jump to content

PHP GD Help - Filtering out colors in image


danbarnett813

Recommended Posts

I am trying to develop an image processing script that takes radar images from the National Weather Service and filters out the ground clutter then outputs an animated gif.  The script "works" but sometimes it takes so long to process the images that it timesout.  So, I am looking for a more efficient way to process these images.  See the code below. (Note: This script runs at preset intervals using CRON.)  Any help would be greatly appreciated.

 

 

Also, all my scripts are released under GPL v3 so feel free to use the code, just credit me please.

 

 

<?php
require_once "includes/GIFEncoder.class.php";

remove('radar/');

$imgName = "";

$time = time();

getList('http://radar.weather.gov/ridge/RadarImg/N0Z/EAX/');
filterList();
getImages();
filterImage();
makeAni();


function getImages()
{
   global $time;
   global $imgName;
   $counter = 0;
   $myFile = "radar.txt";
   $data_dir = "http://radar.weather.gov/ridge/RadarImg/N0Z/EAX";

   if(!file_exists($myFile)) {
      die("getImages --> Can't open file " . $myFile);
   }

   $handle = fopen($myFile, "r");
   while(!feof($handle)) {
      $buffer = fgets($handle, 4096);

      $files = array();
      $files = explode(".", $buffer);

      if(($files[0] != '') && ($files[1] != ''))
      {
         if(strtolower(trim($files[1])) === 'gif')
         {
            $url = $data_dir . "/" . trim($files[0]) . ".gif";

            $counter += 1;

            $imgName = trim($files[0]);

            getRadarImage($url);
         }
      }
   }
   fclose($handle);

   return null;
}


function filterList()
{
   $readFile = "radarTXT.txt";
   $writeFile = "radar.txt";

   $fh = fopen($writeFile, 'w') or die("getList --> Can't create file " . $writeFile);
   $stringData = "";
   fwrite($fh, $stringData);
   fclose($fh);
   chmod($writeFile, 0777);

   $matches = array();

   if(!file_exists($readFile)) {
      die("filterList --> Can't open file " . $readFile);
   }

   $handle = fopen($readFile, "r");
   while(!feof($handle)) {
      $buffer = fgets($handle, 4096);

      preg_match_all("/(a href\=\")([^\?\"]*)(\")/i", $buffer, $matches);

      if(file_exists($writeFile))
      {
         $fh = fopen($writeFile, 'a') or die("getList --> Can't append file " . $writeFile);

         foreach($matches[2] as $match)
         {
               if( trim($match) != '/ridge/RadarImg/N0Z/')
               {
                  $stringData = $match . "\n";
                  fwrite($fh, $stringData);
               }
         }

         fclose($fh);
      }
   }

   fclose($handle);

   return null;
}

function getList($filename)
{
   $myFile = "radarTXT.txt";

   $fp = fopen($myFile, "w");

   $ch = curl_init($filename);

   curl_setopt($ch, CURLOPT_FILE, $fp);
   curl_setopt($ch, CURLOPT_HEADER, 0);

   curl_exec($ch);
   fclose($fp);
   chmod($myFile, 0777);
   curl_close($ch);

   return null;
}


function remove($dirname = '.')
{
        if (is_dir($dirname))
        {
                if ($handle = @opendir($dirname))
                {
                        while (($file = readdir($handle)) !== false)
                        {
                                if ($file != "." && $file != "..")
                                {
                                        $fullpath = $dirname . '/' . $file;

                                        if (is_dir($fullpath))
                                        {
                                                remove($fullpath);
                                                @rmdir($fullpath);
                                        }
                                        else
                                        {
                                                @unlink($fullpath);
                                        }
                                }
                        }
                        closedir($handle);
                }
        }

   return null;
}


function getRadarImage( $uri )
{
   global $time;
   global $imgName;

   $dir = "radar/";
   $filename = $imgName . ".gif";
   $name = $dir.$filename;

   $hourAgo = $time - 3000;

   $fp = fopen($name, "wb");

   $ch = curl_init($uri);

   curl_setopt($ch, CURLOPT_FILE, $fp);
   curl_setopt($ch, CURLOPT_HEADER, 0);
   curl_setopt($ch, CURLOPT_FILETIME, true);

   curl_exec($ch);
   fclose($fp);
   chmod($name, 0777);
   $fileInfo = curl_getinfo($ch);
   curl_close($ch);

   if(($fileInfo['filetime']) < $hourAgo)
   {
      chdir($dir);
      unlink($filename);
   }

   return null;
}


function filterImage()
{
   $data_dir = "radar";

   $filenames = array();
   $nav = opendir($data_dir);
   while($file = readdir($nav)) {
      if($file != "." && $file != "..") {
         array_push($filenames, $file);
      }
   }
   closedir($nav);

   foreach($filenames as $key => $file)
   {
      $files = explode(".", $file);

      if(($files[0] != '') && ($files[1] != ''))
      {
         if(strtolower(trim($files[1])) === 'gif')
         {
            $path = $data_dir . "/" . trim($files[0]) . ".gif";

            $im = imagecreatefromgif($path);
            $w = imagesx($im);
            $h = imagesy($im);

            $trans_color = imagecolorallocatealpha($im, 0, 0, 0, 127);

            getPoints($im, 1, 159, 244, 0, $w, $h, $trans_color);
            getPoints($im, 4, 233, 231, 0, $w, $h, $trans_color);
            getPoints($im, 3, 0, 244, 0, $w, $h, $trans_color);
            getPoints($im, 100, 100, 100, 0, $w, $h, $trans_color);
            getPoints($im, 153, 153, 102, 0, $w, $h, $trans_color);
            getPoints($im, 204, 204, 153, 0, $w, $h, $trans_color);
            getPoints($im, 255, 255, 255, 0, $w, $h, $trans_color);
            getPoints($im, 255, 255, 255, 127, $w, $h, $trans_color);

            imagecolortransparent($im, $trans_color);

            imagesavealpha($im, true);

            $layer1 = imagecreatefromgif('EAX_County_Long.gif');
            $layer2 = imagecreatefromgif('EAX_Highways_Long.gif');
            $layer3 = imagecreatefromgif('EAX_City_Long.gif');
            $currImg = trim($files[0]);
            $currImg = str_replace("_N0Z", "_Long_Warnings", $currImg);
            $warningsURI = "http://radar.weather.gov/ridge/Warnings/Long/EAX/" . $currImg . ".gif";
            $layer4 = imagecreatefromgif($warningsURI);
            $layer5 = imagecreatefromgif('EAX_Legend_Long.gif');

            $new = imagecreatetruecolor(600, 550);
            imagecopymerge($new, $layer1, 0, 0, 0, 0, 600, 550, 100);
            imagecopymerge($new, $im, 0, 0, 0, 0, 600, 550, 100);
            imagecopymerge($new, $layer2, 0, 0, 0, 0, 600, 550, 100);
            imagecopymerge($new, $layer3, 0, 0, 0, 0, 600, 550, 100);
            imagecopymerge($new, $layer4, 0, 0, 0, 0, 600, 550, 100);
            imagecopymerge($new, $layer5, 0, 0, 0, 0, 600, 550, 100);

            $boxColor = imagecolorallocate($new, 0, 0, 0);

            imagefilledrectangle($new, 0, 0, 160, 22, $boxColor);

            $txtColor = imagecolorallocate($new, 115, 115, 115);

            $makeTimeStamp = explode("_", trim($files[0]));
            $timeYear = substr($makeTimeStamp[1], 0, 4);
            $timeMonth = substr($makeTimeStamp[1], 4, 2);
            $timeDay = substr($makeTimeStamp[1], 6, 2);
            $timeHour = substr($makeTimeStamp[2], 0, 2);
            $timeMin = substr($makeTimeStamp[2], 2, 2);

            if(date("I", time()) == 1) { $offset = 18000; $timeZone = "CDT"; } else { $offset = 21600; $timeZone = "CST"; }

            $timeStamp = mktime($timeHour, $timeMin, 0, $timeMonth, $timeDay, $timeYear) - $offset;
            $text = strtoupper(trim($makeTimeStamp[0])) . " " . date("Ymd H:i", $timeStamp) . " " . $timeZone;

            imagettftext($new, 8, 0, 8, 15, $txtColor, 'Vera.ttf', $text);

            imagegif($new, "radar/" . trim($files[0]) . ".gif");
            imagedestroy($im);
         }
      }
   }

   return null;
}


function getPoints($image, $r, $g, $b, $a, $sizex, $sizey, $color)
{
   set_time_limit(45);

   for ($x = 0; $x < $sizex; $x++)
   {
      for ($y = 0; $y < $sizey; $y++)
      {
         $colors = imagecolorsforindex($image, imagecolorat($image, $x, $y));
         if(($colors['red'] == $r) && ($colors['green'] == $g) && ($colors['blue'] == $b) && ($colors['alpha'] == $a))
         {
            imagesetpixel($image, $x, $y, $color);
         }
      }
   }
   return null;
}


function makeAni()
{
   if ( $dh = opendir("radar/" ) ) {
while ( false !== ( $dat = readdir ( $dh ) ) ) {
	if ( $dat != "." && $dat != ".." ) {
		   $frames [ ] = "radar/$dat";
		   $framed [ ] = 75;
	}
}
closedir ( $dh );
   }

   $gif = new GIFEncoder($frames, $framed, 0, 2, 0, 0, 0, "url");

   FWrite ( FOpen ( "radar.gif", "wb" ), $gif->GetAnimation ( ) );

// Make the log string
$logString = date("M j, Y H:i:s", $time) . "\tradar.php";

// Set the log file
$logFile = "radarLog.txt";

// Write the log string to the log file
if(file_exists($logFile)) {
   $fh = fopen($logFile, 'a');
   $stringData = strtoupper(trim($logString)) . "\n";
   fwrite($fh, $stringData);
   fclose($fh);
} else {
   $fh = fopen($logFile, 'w');
   $stringData = strtoupper(trim($logString)) . "\n";
   fwrite($fh, $stringData);
   fclose($fh);
   chmod($logFile, 0777);
}

   return null;
}
?>

Sorry.  The problem is in the finding the specified colored pixels and replacing them with transparent.  To do this I call getPoints (for each color I want to replace in each image)...

 

            getPoints($im, 1, 159, 244, 0, $w, $h, $trans_color);
            getPoints($im, 4, 233, 231, 0, $w, $h, $trans_color);
            getPoints($im, 3, 0, 244, 0, $w, $h, $trans_color);
            getPoints($im, 100, 100, 100, 0, $w, $h, $trans_color);
            getPoints($im, 153, 153, 102, 0, $w, $h, $trans_color);
            getPoints($im, 204, 204, 153, 0, $w, $h, $trans_color);
            getPoints($im, 255, 255, 255, 0, $w, $h, $trans_color);
            getPoints($im, 255, 255, 255, 127, $w, $h, $trans_color);

 

Which finds the pixels with the specified RGB color and replaces it with the transparent.

 

function getPoints($image, $r, $g, $b, $a, $sizex, $sizey, $color)
{
   set_time_limit(45);

   for ($x = 0; $x < $sizex; $x++)
   {
      for ($y = 0; $y < $sizey; $y++)
      {
         $colors = imagecolorsforindex($image, imagecolorat($image, $x, $y));
         if(($colors['red'] == $r) && ($colors['green'] == $g) && ($colors['blue'] == $b) && ($colors['alpha'] == $a))
         {
            imagesetpixel($image, $x, $y, $color);
         }
      }
   }
   return null;
}

 

 

So, my real problem is finding a more efficient way to do this.

Well, you can always add to the top:

<?php
set_time_limit(300);//5 minute timelimit
?>

"0" (unlimited time) is not recommended

The reason I don't recommend unlimited is that it's possible your error comes from a delay on their webserver that may never go through.  Such as trying to get the image while their webserver is too busy or something.

 

Edit: I know this doesn't solve your efficiency, but it's an alternative

 

Edit2: Maybe check every other pixel instead of every?  Might be twice as fast?  Depends on what passes for acceptable quality for you.

Sorry for the double post, I was looking at the GD functions list, and came across this:

 

http://us2.php.net/manual/en/function.imagecolortransparent.php

 

int imagecolortransparent  ( resource $image  [, int $color  ] ) — Define a color as transparent

Note: The transparent color is a property of the image, transparency is not a property of the color. Once you have set a color to be the transparent color, any regions of the image in that color that were drawn previously will be transparent.

 

However I'm not sure this would help as it seems to read as "set one color to transparent".

If you are working with a paletted image (eg gif) you can set colors in the pallette instead of every pixel.

 

(Sorry, I see Third_Degree covered that now I've looked up the actual function to change the pallette)

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.