我正在尝试编写一个 PHP 脚本来调整 PNG 图像的大小,然后将其转换为 PNG-8 位模式。因此,生成的文件的大小会更小,但质量不会有太大损失。
调整大小效果非常好,还保留了图像透明度:
问题是当我将图像转换为 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);
生成的图像是这样的,图像周围和内部都有一点透明度:
如果我设置 256 种颜色而不是 255:
imagetruecolortopalette($resizedImg, true, 256);
图像将具有黑色背景:
此图像会出现类似的结果(请注意 255 种颜色的情况下的半透明度):
Original:
255 colors:
256 colors:
完整函数的代码:
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;
}
我尝试过的:
https://stackoverflow.com/a/8144620/2342558 https://stackoverflow.com/a/8144620/2342558
// 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;
Results:
Also: https://stackoverflow.com/a/55402802/2342558 https://stackoverflow.com/a/55402802/2342558
没有改变。
另外:其他 SO 帖子和网络上的一些
也无需调整图像大小(删除imagecopyresampled
并调整变量名称)结果是相同的。
我怎样才能让它发挥作用并理解这种奇怪行为的原因?
一些信息在phpinfo()
:
- PHP
7.0.33
-
GD
捆绑(兼容 2.1.0)
-
PNG Support
enabled
-
libPNG
1.5.13.
Edit:
在 GIMP v.2.8.22 中,我可以使用以下属性保存 Web 图像:
PNG-8
256 colors palette
Dither: Floyd-Steinberg / Floyd-Steinberg 2 / positioned
它会产生与原始图像几乎相同的缩小图像。
pngquant、tinypng 和许多其他工具也执行相同的工作,但是我需要用 PHP 来做.
Edit 2:
很遗憾,我无法使用 ImageMagick因为我的代码位于共享主机中,但没有安装。
Edit 3:
in phpinfo()
结果表明imagemagick
模块未安装。
Edit 4:
让我对你的回复做一些测试,也许有一个只用 PHP 的解决方案。
Edit 5:
这些是我对你的答案的尝试。
注意:我放置了一个底层网格以更好地显示 Alpha。
托马斯·惠泽尔的回答 https://stackoverflow.com/a/58075858/2342558:
企鹅有明显的色带,但鸭子还可以(尽管有时色调较暗)。
环保局的答复 https://stackoverflow.com/a/58126977/2342558:
只有当图像只有已经完全透明的像素时,它才能很好地工作(例如鸭子)。
马克·塞切尔的回答 https://stackoverflow.com/a/58132349/2342558:
它使所有具有 Alpha 的像素完全透明,如果该 Alpha 非常低,请参见企鹅下方的阴影。此外,鸭子边缘的一些像素也被转换为黑色像素或全透明像素。