views:

3704

answers:

2

I've coded a function that crops an image to a given aspect ratio and finally then resizes it and outputs it as JPG:

<?php

function Image($image, $crop = null, $size = null)
{
    $image = ImageCreateFromString(file_get_contents($image));

    if (is_resource($image) === true)
    {
     $x = 0;
     $y = 0;
     $width = imagesx($image);
     $height = imagesy($image);

     /*
     CROP (Aspect Ratio) Section
     */

     if (is_null($crop) === true)
     {
      $crop = array($width, $height);
     }

     else
     {
      $crop = array_filter(explode(':', $crop));

      if (empty($crop) === true)
      {
       $crop = array($width, $height);
      }

      else
      {
       if ((empty($crop[0]) === true) || (is_numeric($crop[0]) === false))
       {
        $crop[0] = $crop[1];
       }

       else if ((empty($crop[1]) === true) || (is_numeric($crop[1]) === false))
       {
        $crop[1] = $crop[0];
       }
      }

      $ratio = array
      (
       0 => $width / $height,
       1 => $crop[0] / $crop[1],
      );

      if ($ratio[0] > $ratio[1])
      {
       $width = $height * $ratio[1];
       $x = (imagesx($image) - $width) / 2;
      }

      else if ($ratio[0] < $ratio[1])
      {
       $height = $width / $ratio[1];
       $y = (imagesy($image) - $height) / 2;
      }

      /*
      How can I skip (join) this operation
      with the one in the Resize Section?
      */

      $result = ImageCreateTrueColor($width, $height);

      if (is_resource($result) === true)
      {
       ImageSaveAlpha($result, true);
       ImageAlphaBlending($result, false);
       ImageFill($result, 0, 0, ImageColorAllocateAlpha($result, 255, 255, 255, 127));

       ImageCopyResampled($result, $image, 0, 0, $x, $y, $width, $height, $width, $height);

       $image = $result;
      }
     }

     /*
     Resize Section
     */

     if (is_null($size) === true)
     {
      $size = array(imagesx($image), imagesy($image));
     }

     else
     {
      $size = array_filter(explode('x', $size));

      if (empty($size) === true)
      {
       $size = array(imagesx($image), imagesy($image));
      }

      else
      {
       if ((empty($size[0]) === true) || (is_numeric($size[0]) === false))
       {
        $size[0] = round($size[1] * imagesx($image) / imagesy($image));
       }

       else if ((empty($size[1]) === true) || (is_numeric($size[1]) === false))
       {
        $size[1] = round($size[0] * imagesy($image) / imagesx($image));
       }
      }
     }

     $result = ImageCreateTrueColor($size[0], $size[1]);

     if (is_resource($result) === true)
     {
      ImageSaveAlpha($result, true);
      ImageAlphaBlending($result, true);
      ImageFill($result, 0, 0, ImageColorAllocate($result, 255, 255, 255));
      ImageCopyResampled($result, $image, 0, 0, 0, 0, $size[0], $size[1], imagesx($image), imagesy($image));

      header('Content-Type: image/jpeg');

      ImageInterlace($result, true);
      ImageJPEG($result, null, 90);
     }
    }

    return false;
}

?>

The function works as expected but I'm creating a non-required GD image resource, how can I fix it? I've tried joining both calls but I must be doing some miscalculations.

<?php

/*
Usage Examples
*/

Image('http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png', '1:1', '600x');
Image('http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png', '2:1', '600x');
Image('http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png', '2:', '250x300');

?>

Any help is greatly appreciated, thanks.

+4  A: 

You will have to modify your resizing code not to be based on the cropped image to start with. Since you want to do the cropping and resizing in one go you need to calculate it independently.

<?php
function Image($image, $crop = null, $size = null) {
    $image = ImageCreateFromString(file_get_contents($image));

    if (is_resource($image) === true) {
        $x = 0;
        $y = 0;
        $width = imagesx($image);
        $height = imagesy($image);

        /*
        CROP (Aspect Ratio) Section
        */

        if (is_null($crop) === true) {
            $crop = array($width, $height);
        } else {
            $crop = array_filter(explode(':', $crop));

            if (empty($crop) === true) {
                    $crop = array($width, $height);
            } else {
                if ((empty($crop[0]) === true) || (is_numeric($crop[0]) === false)) {
                        $crop[0] = $crop[1];
                } else if ((empty($crop[1]) === true) || (is_numeric($crop[1]) === false)) {
                        $crop[1] = $crop[0];
                }
            }

            $ratio = array(0 => $width / $height, 1 => $crop[0] / $crop[1]);

            if ($ratio[0] > $ratio[1]) {
                $width = $height * $ratio[1];
                $x = (imagesx($image) - $width) / 2;
            }

            else if ($ratio[0] < $ratio[1]) {
                $height = $width / $ratio[1];
                $y = (imagesy($image) - $height) / 2;
            }

        }

        /*
        Resize Section
        */

        if (is_null($size) === true) {
            $size = array($width, $height);
        }

        else {
            $size = array_filter(explode('x', $size));

            if (empty($size) === true) {
                    $size = array(imagesx($image), imagesy($image));
            } else {
                if ((empty($size[0]) === true) || (is_numeric($size[0]) === false)) {
                        $size[0] = round($size[1] * $width / $height);
                } else if ((empty($size[1]) === true) || (is_numeric($size[1]) === false)) {
                        $size[1] = round($size[0] * $height / $width);
                }
            }
        }

       $result = ImageCreateTrueColor($size[0], $size[1]);

        if (is_resource($result) === true) {
            ImageSaveAlpha($result, true);
            ImageAlphaBlending($result, true);
            ImageFill($result, 0, 0, ImageColorAllocate($result, 255, 255, 255));
            ImageCopyResampled($result, $image, 0, 0, $x, $y, $size[0], $size[1], $width, $height);

            ImageInterlace($result, true);
            ImageJPEG($result, null, 90);
        }
    }

    return false;
}

header('Content-Type: image/jpeg');
Image('http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png', '1:1', '600x');

?>
monowerker
Thanks, it's working fine now, just one more question where it says $size = array(imagesx($image), imagesy($image)); shouldn't it be $size = array($width, $height); instead?
Alix Axel
Yes, I missed that one. All the imagesx($image), imagesy($image) got changed to the new calculated width and height instead.
monowerker
A: 

Great code... it works fine but when call the function (header(...); Image(...);) from a different file (after I "include('Image.php');" of course) then load it the browser returns a broken image icon... for some reason I can only get it to work if the function definition and its calls are located in the same file. What the heck am I doing wrong?

Stephen