Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP/GD - Cropping and Resizing Images

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.

like image 596
Alix Axel Avatar asked Jun 16 '09 01:06

Alix Axel


1 Answers

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 = ':', $size = null) {

    $image = ImageCreateFromString(file_get_contents($image));

    if (is_resource($image)) {

        $x = 0;
        $y = 0;
        $width = imagesx($image);
        $height = imagesy($image);

        // CROP (Aspect Ratio) Section
        $crop = array_filter(explode(':', $crop));

        if (empty($crop)) {

            $crop = [$width, $height];

        } else {

            $crop[0] = $crop[0] ?: $crop[1];
            $crop[1] = $crop[1] ?: $crop[0];

        }

        $ratio = [$width / $height, $crop[0] / $crop[1]];

        if ($ratio[0] > $ratio[1]) {

            $width = $height * $ratio[1];
            $x = (imagesx($image) - $width) / 2;

        } else {

            $height = $width / $ratio[1];
            $y = (imagesy($image) - $height) / 2;

        }


        // Resize Section    
        if (is_null($size)) {

            $size = [$width, $height];

        } else {

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

            if (empty($size)) {

                $size = [imagesx($image), imagesy($image)];

            } else {

                $size[0] = $size[0] ?: round($size[1] * $width / $height);
                $size[1] = $size[1] ?: round($size[0] * $height / $width);

            }
        }

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

        if (is_resource($result)) {

            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');

?>
like image 51
monowerker Avatar answered Oct 22 '22 12:10

monowerker