use*_*558 19 php png image image-processing php-gd
我正在尝试编写一个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);
Run Code Online (Sandbox Code Playgroud)
生成的图像是这样的,图像周围到处都是透明的:
如果我设置256种颜色而不是255种颜色:
imagetruecolortopalette($resizedImg, true, 256);
Run Code Online (Sandbox Code Playgroud)
图像将具有黑色背景:
此图像也会发生类似的结果(注意255种颜色情况下的半透明):
完整功能的代码:
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)
我试过的
// 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)结果:
没变化
同样,在不调整图像大小的情况下(删除imagecopyresampled和修改变量名称),结果是相同的。
您能帮我使它正常工作并了解这种奇怪行为的原因吗?
中的一些信息phpinfo():
7.0.33GD 捆绑(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。
企鹅有明显的色带,但鸭子没问题(尽管有时色调较深)。
只有当图像只有已经完全透明的像素时,它才能很好地工作(例如鸭子)。
它使带有alpha的所有像素完全透明,如果此alpha非常低,请查看企鹅下方的阴影。鸭子边缘的一些像素也转换为黑色像素或全透明像素。
您可以在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