Asked  7 Months ago    Answers:  5   Viewed   33 times

The code below crops the image well, which is what i want, but for larger images, it wotn work as well. Is there any way of 'zooming out of the image'

Idealy i would be able to have each image roughly the same size before cropping so that i would get good results each time

Code is

<?php

$image = $_GET['src']; // the image to crop
$dest_image = 'images/cropped_whatever.jpg'; // make sure the directory is writeable

$img = imagecreatetruecolor('200','150');
$org_img = imagecreatefromjpeg($image);
$ims = getimagesize($image);
imagecopy($img,$org_img, 0, 0, 20, 20, 200, 150);
imagejpeg($img,$dest_image,90);
imagedestroy($img);
echo '<img src="'.$dest_image.'" ><p>';

 Answers

89

If you are trying to generate thumbnails, you must first resize the image using imagecopyresampled();. You must resize the image so that the size of the smaller side of the image is equal to the corresponding side of the thumb.

For example, if your source image is 1280x800px and your thumb is 200x150px, you must resize your image to 240x150px and then crop it to 200x150px. This is so that the aspect ratio of the image won't change.

Here's a general formula for creating thumbnails:

$image = imagecreatefromjpeg($_GET['src']);
$filename = 'images/cropped_whatever.jpg';

$thumb_width = 200;
$thumb_height = 150;

$width = imagesx($image);
$height = imagesy($image);

$original_aspect = $width / $height;
$thumb_aspect = $thumb_width / $thumb_height;

if ( $original_aspect >= $thumb_aspect )
{
   // If image is wider than thumbnail (in aspect ratio sense)
   $new_height = $thumb_height;
   $new_width = $width / ($height / $thumb_height);
}
else
{
   // If the thumbnail is wider than the image
   $new_width = $thumb_width;
   $new_height = $height / ($width / $thumb_width);
}

$thumb = imagecreatetruecolor( $thumb_width, $thumb_height );

// Resize and crop
imagecopyresampled($thumb,
                   $image,
                   0 - ($new_width - $thumb_width) / 2, // Center the image horizontally
                   0 - ($new_height - $thumb_height) / 2, // Center the image vertically
                   0, 0,
                   $new_width, $new_height,
                   $width, $height);
imagejpeg($thumb, $filename, 80);

Haven't tested this but it should work.

EDIT

Now tested and working.

Wednesday, March 31, 2021
 
Rudie
answered 7 Months ago
89

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

?>
Wednesday, March 31, 2021
 
rblarsen
answered 7 Months ago
58

In your code $crop['w'] and $crop['h'] are for the source;

$tmpWidth and $tmpHeight are for the destination;

so you should switch them according to imagecopyresampled function (http://php.net//manual/fr/function.imagecopyresampled.php).

imagecopyresampled($dstRes, $srcRes, 0, 0, $crop['x'], $crop['y'], $tmpWidth, $tmpHeight, $crop['w'], $crop['h']);

edit 2

Your destination image shouldn't be set with $crop data, but with the size you want :

$dstRes = imagecreatetruecolor(180, 180);

And i'm not sure what value you have from $tmpWidth and $tmpHeight but they should be both 180 since it's the size you want :

imagecopyresampled($dstRes, $srcRes, 0, 0, $crop['x'], $crop['y'], 180, 180, $crop['w'], $crop['h']);

Edit 3

Ok last try, i've a working code for jcrop but i don't use it inside a function, it's still working the same way. I checked line by line your code and here is what i have. I removed everything about ratio, Jcrop manage it, no need to do it with PHP. Proper dest image, proper imagecopyresampled, looks good to me :/

public function Crop($file, $crop) {

    $height = $width = 180;

    // your file type checking
    $pos = strrpos($file, '.');
    $name = substr($file, 0, $pos);
    $ext = strtolower(substr($file, $pos));

    if( ! in_array($ext, array('.gif', '.jpg', '.jpeg', '.png'))) {
        return 'INVALID_EXT';
    }

    // source image
    $src = ROOT . (in_array(substr($file, 0, 1), array('/', '\')) ? substr($file, 1) : $file);
    $srcRes = imagecreatefromstring(file_get_contents($src));
    if( ! $srcRes) {
        return 'INVALID_FILE';
    }

    // destination image
    $dstRes = imagecreatetruecolor($width, $height);

    // file type transparence
    if($ext == '.gif') {
        $dstBg = imagecolorallocate($dstRes, 0, 0, 0);
        imagecolortransparent($dstRes, $dstBg);
    } elseif($ext == '.png') {
        $dstBg = imagecolorallocate($dstRes, 0, 0, 0);
        imagecolortransparent($dstRes, $dstBg);
        imagealphablending($dstRes, FALSE);
        imagesavealpha($dstRes, TRUE);
    }

    // bool imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )
    imagecopyresampled($dstRes, $srcRes, 0, 0, $crop['x'], $crop['y'], $width, $height, $crop['w'], $crop['h']);

    $dst = ROOT . (in_array(substr($name, 0, 1), array('/', '\')) ? substr($name, 1) : $name) . '-thumb' . $ext;
    if($ext == '.gif') {
        $try = imagegif($dstRes, $dst);
    } elseif($ext == '.jpg' || $ext == '.jpeg') {
        $try = imagejpeg($dstRes, $dst, 80);
    } elseif($ext == '.png') {
        $try = imagepng($newThumbImageResource, $dst);
    }

    if( ! $try) {
        return 'CREATE_ERR';
    }

    return 'SUCCESS';

}
Saturday, May 29, 2021
 
rojo
answered 5 Months ago
11

You need to create an image resource for the destination before using it in imagecopyresampled().

Add this before the imagecopyresampled() line

$this->thumb = imagecreatetruecolor(200, 112);

Update

For cropping, you should probably just look at imagecopy() instead of imagecopyresampled()

Feel free to have a look at my image manipulation class for some ideas - https://gist.github.com/880506

Saturday, May 29, 2021
 
Grzegorz
answered 5 Months ago
60

You could use imagecopy to crop a required part of an image. The command goes like this:

imagecopy  ( 
    resource $dst_im - the image object ,
    resource $src_im - destination image ,
    int $dst_x - x coordinate in the destination image (use 0) , 
    int $dst_y - y coordinate in the destination image (use 0) , 
    int $src_x - x coordinate in the source image you want to crop , 
    int $src_y - y coordinate in the source image you want to crop , 
    int $src_w - crop width ,
    int $src_h - crop height 
)

Code from PHP.net - a 80x40 px image is cropped from a source image

<?php
// Create image instances
$src = imagecreatefromgif('php.gif');
$dest = imagecreatetruecolor(80, 40);

// Copy
imagecopy($dest, $src, 0, 0, 20, 13, 80, 40);

// Output and free from memory
header('Content-Type: image/gif');
imagegif($dest);

imagedestroy($dest);
imagedestroy($src);
?>
Saturday, June 19, 2021
 
petersaints
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :