PHP GD кадрирование и масштабирование изображения - PullRequest
1 голос
/ 13 сентября 2011

Я использую плагин 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 ]

5 голосов
/ 13 сентября 2011

Из документации 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_image ширины src_w и высоты 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 голос
/ 13 сентября 2011

Вместо этого используйте библиотеку 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;
    }
}
0 голосов
/ 14 февраля 2015

Вот функция, которую вы можете передать целевому измерению и масштабировать и обрезать от центра, поддерживать соотношение сторон и увеличивать масштаб.Это легко реализовать с помощью элемента изображения для адаптивного дизайна.Если вы измените конечные размеры, просто удалите выведенные файлы, и они воссоздают изображения при их отсутствии.

    <?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'); ?>">
0 голосов
/ 13 сентября 2011

Почему бы вам не посмотреть на использование imagemagik;он отлично подходит для манипулирования изображениями и кадрирования - это всего лишь простой случай использования cropImage ($ width, $ height, $ x, $ y);

...