PHP GD crop&比例图像

时间:2011-09-13 15:11:41

标签: php jquery image crop

我正在使用jQuery的imgAreaSelect插件来裁剪图像并保存缩略图,以便在比例发生变化的情况下使用。不幸的是,结果远非我所期望的,我无法做到正确。图像整体调整大小而不是被裁剪。

以下是测试示例:

<?php

/***
*
* $_GET returned values
*
* x1 = 0
* x2 = 400
* y1 = 66
* y2 = 258
* w = 400
* h = 192
* folder = widethumb
* filename = IMG_4591.jpg
* scale = 48
*
* Original image properties
*
* width = 600px
* height = 900px
*
***/

define('DOCROOT', realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR);

extract($_GET);

$fn = $filename;
$filename = DOCROOT.$filename;

list($width, $height) = getimagesize($filename);

$src = imagecreatefromjpeg($filename);
$dst = imagecreatetruecolor($w, $h);
imagecopyresampled($dst, $src, 0, 0, (int) $x1, (int) $y1, (int) $w, (int) $h, $width, $height);

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

我在这里做什么?

干杯!

4 个答案:

答案 0 :(得分:5)

来自PHP文档:

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()将一个图像的矩形部分复制到另一个图像,平滑地插入像素值,这样,特别是减小图像的大小仍然保持很大的清晰度。

换句话说,imagecopyresampled()将从宽度为src_w的src_image和高度为src_h的位置(src_x,src_y)取一个矩形区域,并将其放置在dst_image的宽度为dst_w且高度为dst_h的矩形区域中(dst_x, dst_y)。

因此,要获得您正在寻找的结果,您需要避免缩放。为此用途:

imagecopy($dst, $src, 0, 0, $x1, $y1, $w, $h);

// this can also be done but is less efficient (over 10 times slower)
imagecopyresampled($dst, $src, 0, 0, (int) $x1, (int) $y1, $w, $h, $w, $h);

在这里,我们从源头采取相同大小的矩形,因为我们将它放入目标图像 我刚刚测试过,它运行得很好。

<强>更新 我刚刚在我的测试服务器上再次尝试,它运行正常。我正在使用以下代码:

$filename = "test.jpg";

extract($_GET);

$src = imagecreatefromjpeg($filename);
$dst = imagecreatetruecolor($w, $h);
imagecopy($dst, $src, 0, 0, $x1, $y1, $w, $h);

// this is over 10 times slower, as we are only cropping we should use imagecopy
//imagecopyresampled($dst, $src, 0, 0, $x1, $y1, $w, $h, $w, $h);

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

我这样称呼它:

  

http://localserver/test/gd_crop.php?x1=906&y1=267&w=501&h=355

效果更新
由于我们没有调整大小,我们可以简单地使用imagecopy。我测量的3个函数的性能如下所示。

imagecopyresampled    69ms
imagecopyresized      5.5ms
imagecopy             4.5ms

因此重采样和其他两个功能之间存在10个速度差的顺序。

我终于想出了以下代替imagecopyresampled函数的行,尝试一下,我还更新了上面的代码清单:

imagecopy($dst, $src, 0, 0, $x1, $y1, $w, $h);

答案 1 :(得分:1)

请改用WideImage库。

这是我自己的裁剪功能:

function createThumbnail($file, $cropX, $cropY, $cropWidth, $cropHeight, $desiredWidth, $desiredHeight, $shrink = false)
{
    if(file_exists(MPS_ROOT_PATH . "$file") && $cropWidth && $cropHeight)
    {
        $source_path = MPS_ROOT_PATH . $file;

        list( $source_width, $source_height, $source_type ) = getimagesize( $source_path );
        switch ( $source_type )
        {
            case IMAGETYPE_GIF:
                $source_gdim = imagecreatefromgif( $source_path );
                break;

            case IMAGETYPE_JPEG:
                $source_gdim = imagecreatefromjpeg( $source_path );
                break;

            case IMAGETYPE_PNG:
                $source_gdim = imagecreatefrompng( $source_path );
                break;

            default:
                return false;
        }

        if(!$desiredWidth)
        {
            // Desired width not set, computing new width based on original 
            // image's aspect ratio...
            $desiredWidth = $cropWidth * ($desiredHeight / $cropHeight);
        }

        if(!$desiredHeight)
        {
            // Desired height not set, computing new height based on original
            // image's aspect ratio
            $desiredHeight = $cropHeight * ($desiredWidth / $cropWidth);
        }

        if(!$desiredWidth || !$desiredHeight)
        {
            // Desired height or width not set. 
            // Halting image processing and returning file
            return $file;
        }

        $source_aspect_ratio = $cropWidth / $cropHeight;
        $desired_aspect_ratio = $desiredWidth / $desiredHeight;

        if($shrink)
        {
            // Shrink to fit flag set. Inverting computations to make image fit
            // within the desired dimensions...
            if($source_aspect_ratio > $desired_aspect_ratio)
            {
                // Source image is wider than desired aspect ratio, 
                // setting thumbnail width to the desired width and the height 
                // will be computed based on the original image's aspect ratio
                $temp_width = $desiredWidth;
                $temp_height = (int) ($desiredWidth / $source_aspect_ratio);
            }
            else
            {
                // Source image is taller than desired aspect ratio, 
                // setting thumbnail height to the desired height and the width 
                // will be computed based on the original image's aspect ratio
                $temp_height = $desiredHeight;
                $temp_width = (int) ($desiredHeight * $source_aspect_ratio);
            }
        }
        // shrink to fit not set
        else
        {
            if($source_aspect_ratio > $desired_aspect_ratio)
            {
                // Source image is wider than desired aspect ratio, 
                // setting thumbnail height to the desired height to fill the 
                // desired aspect ratio and the width will be computed based on 
                // the original image's aspect ratio
                $temp_height = $desiredHeight;
                $temp_width = (int) ($desiredHeight * $source_aspect_ratio);
            }
            else
            {
                // Source image is taller than desired aspect ratio, 
                // setting thumbnail width to the desired width to fill the 
                // desired aspect ratio and the width will be computed based on 
                // the original image's aspect ratio");
                $temp_width = $desiredWidth;
                $temp_height = (int) ($desiredWidth / $source_aspect_ratio);
            }
        }

        $temp_gdim = imagecreatetruecolor($temp_width, $temp_height);

        // Copying a $cropWidth x $cropHeight image from the source 
        // file at ($cropX, $cropY) and resampling it to fit the temporary 
        // $temp_width x $temp_height thumbnail at (0, 0)
        imagecopyresampled(
            $temp_gdim,
            $source_gdim,
            0, 0,
            $cropX, $cropY,
            $temp_width, $temp_height,
            $cropWidth, $cropHeight
        );

        $x0 = ($desiredWidth - $temp_width) / 2;
        $y0 = ($desiredHeight - $temp_height) / 2;
        // Positioning the temporary $temp_width x $temp_height thumbnail in 
        // the center of the final $desiredWidth x $desiredHeight thumbnail...
        // Creating final thumbnail canvas at $desiredWidth x $desiredHeight
        $desired_gdim = imagecreatetruecolor($desiredWidth, $desiredHeight);

        $white = imagecolorallocate($desired_gdim, 255, 255, 255);
        imagefill($desired_gdim, 0, 0, $white);
        // Filling final thumbnail canvas with white

        // Copying a $temp_width x $temp_height image from the temporary 
        // thumbnail at (0, 0) and placing it in the final 
        // thumbnail at ($x0, $y0)
        imagecopy(
            $desired_gdim,
            $temp_gdim,
            $x0, $y0,
            0, 0,
            $temp_width, $temp_height
        );

        $pathInfo = pathinfo($file);
        $thumbFile = "images/thumbs/thumb_" . basename($pathInfo["filename"]) . ".jpg";

        if(imagejpeg($desired_gdim, MPS_ROOT_PATH . $thumbFile, 80))
        {
            return $thumbFile;
        }
        else
        {
            return 1;
        }
    }
    else
    {
        echo "Image File Does not exist or Invalid crop parameters!";
        return false;
    }
}

答案 2 :(得分:0)

你为什么不考虑使用imagemagick;它非常适合图像处理和裁剪只是使用裁剪图像的简单情况($ width,$ height,$ x,$ y);

答案 3 :(得分:0)

这是一个功能,您可以将目标尺寸传递到中心并从中心进行缩放和裁剪,保持纵横比,并且可以向上扩展。使用响应式设计的图像元素很容易实现。如果您更改目标尺寸,只需删除输出的文件,这将在他们不在时重新创建图像。

    <?php
    function scaleCrop($src, $dest, $destW, $destH, $anchor){
        if(!file_exists($dest) && is_file($src) && is_readable($src)){
            $srcSize = getimagesize($src);
            $srcW = $srcSize[0];
            $srcH = $srcSize[1];
            $srcRatio = $srcW / $srcH;
            $destRatio = $destW / $destH;
            $img = (imagecreatefromjpeg($src));
            $imgNew = imagecreatetruecolor($destW, $destH);

            if ($srcRatio < $destRatio){
                $scale = $srcW / $destW;
            }
            elseif($srcRatio >= $destRatio){
                $scale = $srcH / $destH;
            }
            $srcX = ($srcW - ($destW * $scale)) / 2;
            if($anchor = 'middle'){
                $srcY = ($srcH - ($destH * $scale)) / 2;
            }
            elseif($anchor = 'top'){
                $srcY = 0;
            }
            elseif($anchor = 'bottom'){
                $srcY = $srcH - ($destH * $scale);
            }
            if($srcX < 0){$srcX = 0;};
            if($srcY < 0){$srcY = 0;};
            imagecopyresampled($imgNew, $img, 0, 0, $srcX, $srcY, $destW, $destH, $destW * $scale, $destH * $scale);
            imagejpeg($imgNew, $dest, 70);
            imagedestroy($img);
            imagedestroy($imgNew);
        }
        return $dest;
    }
    ?>

<img src="<?php echo scaleCrop('srcfolder/srcfile.jpg', 'destfolder/destfile.jpg', 320, 240, 'top'); ?>">