PHP错误结果为带有PNG和透明度的imagetruecolortopalette

use*_*558 19 php png image image-processing php-gd

我正在尝试编写一个PHP脚本,该脚本将调整PNG图像的大小,然后将其转换为PNG-8位模式。因此,生成的文件的大小将较小,但不会造成过多的质量损失。

编辑:引用图像的样式以更好地显示其透明度

调整大小效果完美,同时还保留了图像透明度:

originalImage

问题是当我将图像转换为8位时:

imagetruecolortopalette($resizedImg, true, 255);

imagealphablending($resizedImg, false);

$transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
if(!imagefill($resizedImg, 0, 0, $transparent)) return false;

imagesavealpha($resizedImg, true);
Run Code Online (Sandbox Code Playgroud)

生成的图像是这样的,图像周围到处都是透明的:

在此处输入图片说明

如果我设置256种颜色而不是255种颜色:

imagetruecolortopalette($resizedImg, true, 256);
Run Code Online (Sandbox Code Playgroud)

图像将具有黑色背景:

在此处输入图片说明

此图像也会发生类似的结果(注意255种颜色情况下的半透明):

原版的: 在此处输入图片说明 255种颜色: 在此处输入图片说明 256种颜色: 在此处输入图片说明

完整功能的代码:

function resizePng($originalPath, $xImgNew='', $yImgNew='', $newPath='')
{
    if(!trim($originalPath) || !$xyOriginalPath = getimagesize("$originalPath")) return false;
    list($xImg, $yImg) = $xyOriginalPath;

    if(!$originalImg = imagecreatefrompng($originalPath)) return false;

    if(!$resizedImg = imagecreatetruecolor($xImgNew, $yImgNew)) return false;

    // preserve alpha
    imagealphablending($resizedImg, false);
    $transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
    if(!imagefill($resizedImg, 0, 0, $transparent)) return false;
    imagesavealpha($resizedImg, true);

    // copy content from originalImg to resizedImg
    if(!imagecopyresampled($resizedImg, $originalImg, 0, 0, 0, 0, $xImgNew, $yImgNew, $xImg, $yImg)) return false;

    // PNG-8 bit conversion
    imagetruecolortopalette($resizedImg, true, 255);

    // preserve alpha
    imagealphablending($resizedImg, false);
    $transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
    if(!imagefill($resizedImg, 0, 0, $transparent)) return false;
    imagesavealpha($resizedImg, true);

    if(!imagepng($resizedImg, ($newPath) ?: null, 8)) return false;

    return true;
}
Run Code Online (Sandbox Code Playgroud)

我试过的

  • /sf/answers/570123431/

    // PNG-8 bit conversion
    imagetruecolortopalette($resizedImg, true, 255);
    
    imagesavealpha($resizedImg, true);
    imagecolortransparent($resizedImg, imagecolorat($resizedImg,0,0));
    
    // preserve alpha
    imagealphablending($resizedImg, false);
    $transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
    if(!imagefill($resizedImg, 0, 0, $transparent)) return false;
    imagesavealpha($resizedImg, true);
    
    if(!imagepng($resizedImg, ($newPath) ?: null, 8)) return false;
    
    Run Code Online (Sandbox Code Playgroud)

结果:

在此处输入图片说明 在此处输入图片说明

没变化

  • 其他SO帖子和一些Web帖子

同样,在不调整图像大小的情况下(删除imagecopyresampled和修改变量名称),结果是相同的。

您能帮我使它正常工作并了解这种奇怪行为的原因吗?

中的一些信息phpinfo()

  • 的PHP 7.0.33
  • GD 捆绑(2.1.0兼容)
  • PNG Support 已启用
  • libPNG 1.5.13。

编辑

在GIMP v.2.8.22中,我可以使用以下属性为Web保存图像:

PNG-8
256 colors palette
Dither: Floyd-Steinberg / Floyd-Steinberg 2 / positioned
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明 在此处输入图片说明

并产生几乎与原始图像相同的缩小图像。

pngquant,tinypng和许多其他工具也做同样的工作,但是我需要使用PHP来做

编辑2

不幸的是,我无法使用ImageMagick,因为我的代码未安装就位于共享主机中。

编辑3

phpinfo()结果该imagemagick模块没有安装。

编辑4

赏金期满,接下来的几天让我对您的响应进行一些测试,也许只有PHP才能解决。

编辑5

这些是我尝试的答案(2019年10月2日更新)。

注意:我放置了一个基础网格以更好地显示alpha。

托马斯·休伊泽(Thomas Huijzer)的答案

在此处输入图片说明 在此处输入图片说明

企鹅有明显的色带,但鸭子没问题(尽管有时色调较深)。

EPB的答案

在此处输入图片说明 在此处输入图片说明

只有当图像只有已经完全透明的像素时,它才能很好地工作(例如鸭子)。

马克·谢彻尔(Mark Setchell)的答案

在此处输入图片说明 在此处输入图片说明

它使带有alpha的所有像素完全透明,如果此alpha非常低,请查看企鹅下方的阴影。鸭子边缘的一些像素也转换为黑色像素或全透明像素。

fmw*_*w42 5

您可以在ImageMagick中轻松地做到这一点,ImageMagick在Linux上发行,可用于Windows和Mac OSX。除了命令行以外,还有许多API。这是在ImageMagick命令行中执行的方法。

输入:

在此处输入图片说明

convert image.png PNG8:result1.png
Run Code Online (Sandbox Code Playgroud)


在此处输入图片说明

PNG8:表示256种颜色和二进制透明度。这意味着完全或没有透明度。这会导致边缘出现锯齿(阶梯状)。如果您愿意设置背景色来代替透明度,则可以在结果中保留平滑(抗锯齿)的轮廓。因此对于白色背景。

convert image.png -background white -flatten PNG8:result2.png
Run Code Online (Sandbox Code Playgroud)


在此处输入图片说明

ImageMagick由PHP Imagick运行。因此,您应该可以使用PHP Imagick做到这一点。或者,您可以从PHP exec()调用ImageMagick命令行。


小智 -1

正如您在https://www.php.net/manual/en/function.imagetruecolortopalette.php中看到的:

这并不像人们希望的那样有效。通常最好只是生成真彩色输出图像,这样可以保证最高的输出质量。

您可以使用 ImageMagick:https://www.php.net/manual/en/imagick.affinetransformimage.php