imagecopyresampled()在透明PNG中引入了工件

时间:2014-06-02 11:52:37

标签: php gd

我为图像添加了透明的PNG水印。水印是高分辨率的,因此在将其重叠在原始图像中之前,我将其调整大小。这似乎在水印中引入了一些我无法避免的文物。

原始图片: enter image description here

调整大小的图像(看看水平线条"污垢"字母和#34之间;): enter image description here

缩放调整大小的图像(不透明)以澄清我的意思是"污垢"字母之间。 " s"之间的区域和" t"我已使用选择工具进行清理并删除(在新标签页中打开以查看完整尺寸,其中更清晰): enter image description here

以下是我使用的代码:

function resizeImage($image_filename, $out_filename, $width, $height){
  // Get image info
  $image_info = @getimagesize($image_filename);
  if ($image_info == false) return false;
  $org_width = $image_info[0];
  $org_height = $image_info[1];
  $image_type = $image_info[2];

  // Open image
  if ($image_type == IMAGETYPE_JPEG) $org_image = @imagecreatefromjpeg($image_filename);
  else if ($image_type == IMAGETYPE_GIF) $org_image = @imagecreatefromgif($image_filename);
  else if ($image_type == IMAGETYPE_PNG) $org_image = @imagecreatefrompng($image_filename);
  else return false;

  // Open stream for resized image
  $resized_image = @imagecreatetruecolor($width, $height);
  if ($resized_image == false) return false;

  // Handle transparency in PNGs
  if ($image_type == IMAGETYPE_PNG){
    $transparent = imagecolorallocatealpha($resized_image, 255, 255, 255, 127);
    imagefilledrectangle($resized_image, 0, 0, $width, $height, $transparent);
    imagealphablending($resized_image, false);
    imagesavealpha($resized_image, true);
  }

  // Resize
  $resize_result = @imagecopyresampled($resized_image, $org_image, 0, 0, 0, 0, $width, $height, $org_width, $org_height);

  // Free original image
  @imagedestroy($org_image);

  // Save
  if ($image_type == IMAGETYPE_JPEG) $save_result = imagejpeg($resized_image, $out_filename, 90); // 90 = compression
  else if ($image_type == IMAGETYPE_GIF) $save_result = imagegif($resized_image, $out_filename);
  else if ($image_type == IMAGETYPE_PNG) $save_result =  imagepng($resized_image, $out_filename, 0);

  // Free resized image
  if ($resize_result) @imagedestroy($resized_image);

  return ($resize_result && $save_result);
}

有关造成这些文物的原因的任何想法吗?

3 个答案:

答案 0 :(得分:2)

正如我在回答SørenLøvborgs的评论中写的那样回答它看起来很简单[GD / imagecopyresampled()][1]的一个问题,这是不容易避免的。 GD Quality Issue with Transparent PNGs也存在同样的问题。

可以使用SørenLøvborgs建议的解决方法,请记住,由于调整原始图像的大小两次,它可能会引入显着的质量降低。

我建议使用照片编辑器调整水印大小,然后重叠。这不是那么灵活,但它会保持图像质量而不会增加任何噪音。

答案 1 :(得分:2)

这似乎不会出现在黑色背景上,因此另一个黑客将是在调整大小之前反转图像并在

之后再次执行此操作
imagefilter($org_image, IMG_FILTER_NEGATE);
imagecopyresampled($resized_image, $org_image, 0, 0, 0, 0, $width, $height, $org_width, $org_height);
imagefilter($resized_image, IMG_FILTER_NEGATE);

答案 2 :(得分:1)

好的,首先,这是你的“脏”测试图像,RGB通道(上图)和alpha通道(下图)分开:

Dirty image split into channels

我用蓝色替换纯白色(#FFFFFF)/ 100%透明以突出斑点。

如您所见,GD为RGB通道和Alpha通道添加了斑点。

在没有检查GD代码的情况下,我猜测它是由舍入错误引起的,导致一些像素被1或2关闭。

我注意到您在源PNG中有一个嵌入的颜色配置文件。尝试删除;人工制品可能是由GD进行色彩校正引起的。 (在Photoshop中,您应该使用Save for Web。)

否则,我无法在不修复GD代码的情况下建议解决此问题的方法,但是,我可以建议一个可能有效的脏方法:

不是将水印调整为目标图像大小,而是将其覆盖在目标图像上,您可以将目标图像调整为水印大小,覆盖水印,删除Alpha通道,然后调整为旧的目标图像大小。这样,您可以避免在具有Alpha通道的情况下调整任何图像的大小,这可以避免可见的伪像。