Tag: image

2010-08-13

Image Resize and Crop Function

by Charles — Categories: PHP — Tags: , , 2 Comments

I thought I would share this function with the PHP community, as it seems to be working pretty well. I created it as part of a page for creating screensaver images for the Amazon Kindle. It accepts the path to a JPEG image file and the desired width and height, then returns a PHP image resource of the resized image, which can then be displayed, saved, or otherwise modified. (In the linked page, it is also converted to a gray-scale image.

An obvious enhancement possibility would be to add support for other image types, which I may do soon as I would also like to add the ability to fetch the resulting image as a PNG file instead of JPEG. So feel free to use and modify it as desired, and let me know if you come up with any useful mods.

/**
* Resize image to specific dimension, cropping as needed
* @return resource Resized image resource, or boolean false on failure
* @param string $imgFile Path to image to be resized
* @param int $width
* @param int $height
* @param string $error Error message
*/
function resize($imgFile, $width, $height, &$error = null)
{
   $attrs = @getimagesize($imgFile);
   if($attrs == false or $attrs[2] != IMG_JPEG)
   {
      $error = "Uploaded image is not JPEG or is not readable by this page.";
      return false;
   }
   if($attrs[0] * $attrs[1] > 3000000)
   {
      $error = "Max pixels allowed is 3,000,000. Your {$attrs[0]} x " .
               "{$attrs[1]} image has " . $attrs[0] * $attrs[1] . " pixels.";
      return false;
   }
   $ratio = (($attrs[0] / $attrs[1]) < ($width / $height)) ?
            $width / $attrs[0] : $height / $attrs[1];
   $x = max(0, round($attrs[0] / 2 - ($width / 2) / $ratio));
   $y = max(0, round($attrs[1] / 2 - ($height / 2) / $ratio));
   $src = imagecreatefromjpeg($imgFile);
   if($src == false)
   {
      $error = "Unknown problem trying to open uploaded image.";
      return false;
   }
   $resized = imagecreatetruecolor($width, $height);
   $result = imagecopyresampled($resized, $src, 0, 0, $x, $y, $width, $height,
             round($width / $ratio, 0), round($height / $ratio));
   if($result == false)
   {
      $error = "Error trying to resize and crop image.";
      return false;
   }
   else
   {
      return $resized;
   }
}

2009-11-18

Memory Usage in PHP GD Image Functions

by Charles — Categories: PHP — Tags: , , 1 Comment

When working with the PHP GD Image functions, memory usage can become a serious issue. Where PHP developers often stumble is in not realizing that the various imagecreate*() functions create a bitmap in memory with data for each and every pixel. Therefore a source JPEG file that is only a few tens of kilobytes in size might need several megabytes of memory when used as the source of an image (e.g. imagecreatefromjpeg()).

As a rule of thumb to estimate the memory usage of a given image, figure that you’ll need 4 bytes per pixel (3 for the RGB color and 1 for the alpha channel). If you multiply that times the width and height of the image, you will then have a good working number.

Fortunately, PHP’s getimagesize() function will give you the dimensions of an image file without having to first convert it into a GD image, thus allowing you to decide if it’s too big for your application to use or not.

$imgAttrs = getimagesize('path/to/file.jpg');
$estimatedMemory = $imgAttrs[0] * $imgAttrs[1] * 4;

You can then use the result of that estimate to decide if you want to go ahead and process that image, or raise a red flag and do something else, instead.

2008-08-05

Securing Uploaded Image Files

by Charles — Categories: PHP — Tags: , , 4 Comments

I just saw this post by “jazz_snob” posted at PHPBuilder.com, suggesting a means to secure untrusted image files. The basic idea is to use PHP’s GD image functions to create a copy of the file. As doing so would decompose the specified file into GD’s native bitmap format, and then recompose it into the desired image file type, any embedded “nastiness” within the original file ought to be left behind. It could be implemented into a function something like:

<?php
/**
 * Copy an image to help ensure it is not "infected"
 * @author Charles Reace (www.charles-reace.com)
 * @param  string    path to image file to be copied
 * @return resource  GD image resource, boolean false if error
 */
function secureImage($filePath)
{
   $sizeData = getimagesize($filePath);
   if($sizeData === false)
   {
      user_error(__FUNCTION__ . "(): Unable to get imsge data");
      return false;
   }
   list($unused, $type) = explode('/', $sizeData['mime']);
   switch($type)
   {
      case 'gif':
         $fh = imagecreatefromgif($filePath);
         break;
      case 'png':
         $fh = imagecreatefrompng($filePath);
         break;
      case 'jpeg':
         $fh = imagecreatefromjpeg($filePath);
         break;
      default:
         user_error(__FUNCTION__ . "(): Unsupported image type '$type'");
         return false;
   }
   return $fh;
}

// Sample usage:
$fh = secureImage('bg.gif');
if(!$fh)
{
   header('HTTP/1.0: 404 Not Found');
   exit;
}
header('Content-Type: image/gif');
imagegif($fh);

If any of you readers happens to have access to an “infected” image file and a safe sandbox where you could test the above, I’d be very interested to know if it does, in fact, filter out the non-image virus or whatever is embedded, or at the very least reject it with an error.

© 2012 PHP Musings All rights reserved - Wallow theme v0.46.4 by ([][]) TwoBeers - Powered by WordPress - Have fun!