使用 imagecopyresampled 调整大小时图像颜色被破坏

Image color ruined while resizing it using imagecopyresampled

将图片上传到我的网站后,正在调整图片的大小。我正在使用 imagecreatefromjpegimagecopyresampled 函数。我注意到颜色与原始图像中的颜色不同。

在这里你可以看到不同之处。您可以看到带有当前颜色的闪烁图像以及来自我网站的图像后面的图像。

原图: https://c2.staticflickr.com/6/5754/23693488109_74c67f012a_k.jpg

调整后: https://www.isrart.co.il/img/uploads/art/viewer/big/photo-2b971e861c7aa2c57b8f7667ec666c3d.jpg

这是我的 PHP 代码:

    $type = @getImageSize($_FILES['photo']['tmp_name'])[2];
    switch ($type) { 
        case 1 : 
            $img = imageCreateFromGif($_FILES['photo']['tmp_name']); 
        break; 
        case 2 : 
            $img = imageCreateFromJpeg($_FILES['photo']['tmp_name']); 
        break; 
        case 3 : 
            $img = imageCreateFromPng($_FILES['photo']['tmp_name']); 
        break; 
        case 6 : 
            $img = imageCreateFromBmp($_FILES['photo']['tmp_name']); 
        break; 
    }    

    $orig_width = imagesx($img);
    if($orig_width < $width)
        return $img;

    $orig_height = imagesy($img);

    $height = (($orig_height * $width) / $orig_width);

    $new_image = imagecreatetruecolor($width, $height);

    imagecopyresampled($new_image, $img, 0, 0, 0, 0, $width, $height, $orig_width, $orig_height);

    imagejpeg($new_image, $_SERVER['DOCUMENT_ROOT'] . "/img/uploads/" . $path, 100);

我确定它是一个 PNG 文件,并且其中有一个名为 "gAMA" 的信息块。这是一种伽玛校正的东西,有些观众使用它,有些则不使用。当您加载图像时,GD 库会忽略此信息。但 Imagick 应该可以解决问题:

http://php.net/manual/en/imagick.getimageproperties.php

希望对您有所帮助。

您的原始图像有一个与之关联的 560 字节 ICC 配置文件,而您的重采样图像没有。

您可以像这样使用 ImageMagick 从原始图像中提取配置文件:

convert orig.jpg profile.icm

如果我把两个文件区别一下,你可以在这里看到:

我注意到,如果我使用 ImageMagick 在 command-line 对您的原始图像重新采样,如下所示:

convert orig.jpg -resize 1110x1570! myresampled.jpg

然后 ICC 配置文件被结转。我可以这样检查:

identify -verbose orig.jpg myresampled.jpg | grep -i profile

  Profiles:
    Profile-icc: 560 bytes
  Profiles:
    Profile-icc: 560 bytes

压缩后的图像与原始图像相比显得暗淡的原因在于它的颜色格式。原始使用 4:4:4 色度 sub-sampling 而压缩后使用 4:2:0 sub-sampling。这会导致颜色信息丢失。

为了克服这个问题,我们可以使用 ffmpeg 或 avconv 进行缩放,并且可以从 PHP 中的 shell 执行。

我使用 avconv 和以下 2 个命令生成了高质量的缩放图像。

avconv -i Input.jpg -pix_fmt yuvj444p -vf scale=1110:1570 Output.yuv

avconv -y -s 1110x1570 -f rawvideo -pix_fmt yuv444p -i Output.yuv Output.jpg

扩展 @Mark Setchell 的回答:

使用此文件将原始图像的 ICC 配置文件复制到调整后图像的 ICC 配置文件。比问题解决。它是一个没有任何依赖关系的文件。

https://github.com/slavicv/jpeg-icc/blob/master/class.jpeg_icc.php

对于我的用例,我编辑了文件,因此它可以在不使用文件系统的情况下处理内存中的图像。