Php imagecopyresampled низкого качества
У меня есть php script, который сохраняет исходное изображение, а затем изменяет его размер - одно миниатюру и одно увеличенное изображение для просмотра в Интернете. Это хорошо работает, но с некоторыми изображениями качество ужасное. Кажется, он сохранен с очень низким цветовым поддоном. Вы можете увидеть результат на 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);
}
Ответы
Ответ 1
Потеря качества снижается не до imagecopyresampled()
, а для сжатия JPEG. К сожалению, алгоритмы сжатия GD не соответствуют Photoshop - на самом деле их очень мало. Но вы можете улучшить результат: уровень сжатия по умолчанию для GD по умолчанию составляет от 100 до 100.
Вы можете повысить качество с помощью третьего параметра до imagejpeg() (который, как я полагаю, вы используете для конечный результат):
imagejpeg ( $new_image, null, 99);
Играйте в диапазоне 90-100. Изображение будет больше размера файла, чем оригинал - это будет цена, которую вы платите. Но должно быть возможно достичь сопоставимого качества.
В качестве альтернативы, как говорит Джон Химмельман в комментариях, попробуйте использовать imagepng()
для лучшего качества - конечно же, по цене значительно большего размера файла.
Ответ 2
Хорошо, в документации php.net должно быть изображение imagecreatetruecolor() для вашего dest_image, если вы хотите избежать использования только цветовой палитры 255, но вы уже это сделали.
Я предполагаю, что альтернативой будет использование внешних инструментов, таких как imagemagick с вызовом system().
Ответ 3
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;
}
Ответ 4
Быстрый трюк - сделать эскизы 1000 x 1000 пикселей (или более) на imagecopyresized()
, а затем установить качество JPEG до 20 или меньше imagejpeg($img, $savePath, 20);
. Обычно выход будет меньше 100 кб.
Пусть клиент CSS выполнит изменение размера, и снимки будут быстро загружаться и выглядеть безупречно в современных браузерах при масштабировании до размера миниатюр.