php imagecopyresampled 质量差

Posted

技术标签:

【中文标题】php imagecopyresampled 质量差【英文标题】:php imagecopyresampled poor quality 【发布时间】:2010-02-26 23:56:46 【问题描述】:

我有一个 php 脚本,它保存原始图像,然后调整它的大小 - 一个缩略图和一个更大的图像用于网络查看。这很好用,除了一些图像质量很差。它似乎是用一个非常低的颜色托盘保存的。您可以在http://kalpaitch.com/index.php?filter=white 看到结果 - 点击标题为“white white 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;

非常感谢

附: [从服务器中删除的照片]

这里是其余的上传代码:

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

【问题讨论】:

你能展示一个前后的例子吗? 我不是 100% 清楚,但听起来你得到的一些图像有一定的大小,你的脚本实际上调整它的大小比原来更大?如果你这样做,质量会很糟糕。 如果只给定一种尺寸,脚本不会按比例调整图像大小。如果给定两个尺寸,它将调整大小并裁剪其余的而不改变纵横比。重采样图像的分辨率总是比原始图像低得多。上图不是原图,都是一样的分辨率,但是之前是用photoshop保存的,后一张是用我的脚本保存的。 脚本的其余部分在哪里?它可能是您正在使用的图像输出功能。尝试使用 imagepng() 输出图像并将压缩质量设置为“0”以进行测试。 us2.php.net/manual/en/function.imagepng.php 我做了一个快速测试,但 imagepng() 似乎并没有太大的不同。好吧,真的没有。但我发布了脚本的另一半,仅供参考。 【参考方案1】:

质量下降不是imagecopyresampled(),而是JPEG压缩。不幸的是,GD 的压缩算法与 Photoshop 的不匹配——事实上,很少有。但是您可以改进结果:GD 的默认 JPG 压缩级别是 75 of 100。

您可以使用第三个参数将质量提高到imagejpeg()(我假设您将其用于最终输出):

imagejpeg  ( $new_image, null, 99);

在 90-100 范围内玩。图像的文件大小将比原始图像大 - 这将是您付出的代价。但是应该可以达到相当的质量。

或者,正如 John Himmelman 在 cmets 中所说,尝试使用 imagepng() 以获得更好的质量 - 当然,代价是文件大小要大得多。

【讨论】:

作为好奇的人的最后一点。我已将 imagejpeg() 质量更改为 99,我得到了更好的图像。虽然 - 这与默认值之间的区别是文件大小增加了 1000%(默认为 12kb,高质量压缩为 110kb) 只是我在阅读本文后提出的一个建议。使用我的缩略图系统,不要求缩略图图像与原始全尺寸图像的格式相同,我的实用程序功能被询问“此图像的缩略图文件是什么,它是否已经存在?”所以如果被问及file.jpg,它会返回thumbnail_cache/file.jpg。我改变了这种方法,总是用 .png 格式的缩略图回复,所以如果被问及 file.jpg 它会返回 thumbnail_cache/file.png 并生成一个 png 缩略图。这避免了对 GD jpg 压缩的任何担忧。 重采样结果模糊,是GD问题,不支持lanczos。一个技巧是使用 imagescale 将大小调整为 200%,然后再调整为 100% (50%)。它不是lanczos,而是更锐利。 ImageMagick 总是更好。【参考方案2】:

好吧,php.net 文档说如果您想避免只使用 255 调色板但您已经这样做了,您应该为您的 dest_image 提供一个 imagecreatetruecolor() 图像。

我想另一种方法是使用带有 system() 调用的外部工具,例如 imagemagick。

【讨论】:

是的,不确定 php 是否很有帮助。如您所见,我使用 imagecopyresized 完成了第三张测试图像,效果稍微好一点,但还不够。 谢谢,使用 imagecreatetruecolor 解决了我在自定义图像的颜色计数低时遇到的问题!【参考方案3】:

一个肮脏的技巧是imagecopyresized()上的缩略图设置为1000 x 1000像素(或更高),然后在@上将JPEG质量设置为20或更低987654322@。输出通常小于 100 kb

让客户端 CSS 来调整大小,当缩放到缩略图大小时,图片将可以快速加载并且在现代浏览器中看起来完美无瑕。

【讨论】:

【参考方案4】:
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;


【讨论】:

关于这个函数中实际发生的事情的信息非常少。尺寸应该是多少?数组?一个字符串?百分比?

以上是关于php imagecopyresampled 质量差的主要内容,如果未能解决你的问题,请参考以下文章

PHP imagecopyresampled + 如何获得最佳结果

PHP GD imagecopyresampled() 并将其水平翻转

php imagecopyresampled - 保存后图像为空(全黑)

突破php 的imagecopyresampled 和imagecopyresized 实现图片马 JPG

在 PHP imagecopyresampled 中裁剪图像 - 挤压而不是裁剪

使用PHP的GDlib imagecopyresampled时可以保留PNG图像透明度吗?