php imagecopyresampled низкого качества - PullRequest
11 голосов
/ 27 февраля 2010

У меня есть скрипт php, который сохраняет исходное изображение, а затем изменяет его размер - один эскиз и одно изображение большего размера для просмотра в Интернете. Это работает хорошо, за исключением того, что с некоторыми изображениями качество ужасно. Похоже, что он сохранен с очень низким цветом поддона. Вы можете увидеть результат на http://kalpaitch.com/index.php?filter=white - нажмите на первый эскиз с заголовком «белый белый белый»

Ниже приведен код, используемый для повторной выборки изображения:

function resizeImg($name, $extension, $size1, $size2) {
if (preg_match('/jpg|jpeg|JPG|JPEG/',$extension)){
    $image = imagecreatefromjpeg($name);
}
if (preg_match('/gif|GIF/',$extension)){
    $image = imagecreatefromgif($name);
}

$old_width = imageSX($image);
$old_height = imageSY($image);
$old_aspect_ratio = $old_width/$old_height; 

if($size2 == 0){
    $new_aspect_ratio = $old_aspect_ratio;
    if($old_width > $old_height){
        $new_width = $size1;
        $new_height = $new_width / $old_aspect_ratio;
    } else {
        $new_height = $size1;
        $new_width = $new_height * $old_aspect_ratio;
    }
} elseif($size2 > 0){
    $new_aspect_ratio = $size1/$size2;
    //for landscape potographs
    if($old_aspect_ratio >= $new_aspect_ratio) {
        $x1 = round(($old_width - ($old_width * ($new_aspect_ratio/$old_aspect_ratio)))/2);
        $old_width = round($old_width * ($new_aspect_ratio/$old_aspect_ratio));
        $y1 = 0;
        $new_width = $size1;
        $new_height = $size2;
        //for portrait photographs
    } else{
        $x1 = 0;
        $y1 = 0;
        $old_height = round($old_width/$new_aspect_ratio);
        $new_width = $size1;
        $new_height = $size2;
    }
}

$new_image = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($new_image, $image, 0, 0, $x1, $y1, $new_width, $new_height, $old_width, $old_height);

return $new_image;

Большое спасибо

P.S. [фотографии удалены с сервера]

А вот и код загрузки:

// Move the original to the right place
        $result = @move_uploaded_file($image['tmp_name'], $origlocation);

        // Resize the image and save the thumbnail
        $new_image = resizeImg($origlocation, $extension, 500, 0);

        if (preg_match("/gif/",$extension)){
            imagegif($new_image, $normallocation); 
        } else {
            imagejpeg($new_image, $normallocation); 
        }

        // Resize the image and save the thumbnail
        $new_image = resizeImg($origlocation, $extension, 190, 120);

        if (preg_match("/gif/",$extension)){
            imagegif($new_image, $thumblocation); 
        } else { 
            imagejpeg($new_image, $thumblocation);
        }

Ответы [ 4 ]

24 голосов
/ 27 февраля 2010

Потеря качества снижается не до imagecopyresampled(), а до сжатия JPEG. К сожалению, алгоритмы сжатия GD не соответствуют Photoshop - на самом деле, очень немногие. Но вы можете улучшить результат: уровень сжатия JPG в GD по умолчанию составляет 75 из 100.

Вы можете повысить качество с помощью третьего параметра до imagejpeg () (который, я полагаю, вы используете для окончательного вывода):

imagejpeg  ( $new_image, null, 99);

Тренировка в диапазоне 90-100. Изображение станет больше по размеру файла, чем оригинал - это будет цена, которую вы заплатите. Но должно быть возможно добиться сопоставимого качества.

В качестве альтернативы, как уже сказал Джон Химмельман в комментариях, попробуйте использовать imagepng() для лучшего качества - конечно же, за счет значительно большего размера файла.

2 голосов
/ 04 января 2018

Быстрый грязный трюк состоит в том, чтобы сделать миниатюры 1000 x 1000 пикселей (или больше) на imagecopyresized(), а затем установить JPEG качество на 20 или меньше на imagejpeg($img, $savePath, 20); , Вывод обычно будет меньше чем 100 кб .

Пусть клиентский CSS выполнит изменение размера, и изображения будут быстро загружаться и выглядеть безупречно в современных браузерах при масштабировании до размера миниатюры.

1 голос
/ 27 февраля 2010

Что ж, в документации php.net говорится, что у вас должно быть изображение imagecreatetruecolor () для вашего dest_image, если вы хотите избежать использования только 255 цветовой палитры, но вы уже это делаете.

Я полагаю, что альтернативой может быть использование внешних инструментов, таких как imagemagick , с вызовом system ().

0 голосов
/ 07 сентября 2015
function img_resize( $tmpname, $size, $save_dir, $save_name, $maxisheight = 0 )
{
    $save_dir .= ( substr($save_dir,-1) != "/") ? "/" : "";
    $gis = getimagesize($tmpname);
    $type = $gis[2];

    switch($type)
    {
        case "1": $imorig = imagecreatefromgif($tmpname); break;
        case "2": $imorig = imagecreatefromjpeg($tmpname);break;
        case "3": $imorig = imagecreatefrompng($tmpname); break;
        default:  $imorig = imagecreatefromjpeg($tmpname);
    }

    $x = imagesx($imorig);
    $y = imagesy($imorig);

    $woh = (!$maxisheight)? $gis[0] : $gis[1] ;
    if($woh <= $size)
    {
        $aw = $x;
        $ah = $y;
    }
    else
    {
        if(!$maxisheight)
        {
            $aw = $size;
            $ah = $size * $y / $x;
        }
        else
        {
            $aw = $size * $x / $y;
            $ah = $size;
        }
    }
    $im = imagecreatetruecolor($aw,$ah);

    if (imagecopyresampled($im,$imorig , 0,0,0,0,$aw,$ah,$x,$y))

    if (imagejpeg($im, $save_dir.$save_name))

        return true;

    else

        return false;

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...