PHP 对具有透明 PNG 的 imagetruecolortopalette 产生错误结果

2023-12-22

我正在尝试编写一个 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: enter image description here 255 colors: enter image description here 256 colors: enter image description here

完整函数的代码:

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 非常低,请参见企鹅下方的阴影。此外,鸭子边缘的一些像素也被转换为黑色像素或全透明像素。


您可以在 ImageMagick 中轻松完成此操作,它分布在 Linux 上,并且适用于 Windows 和 Mac OSX。除了命令行之外还有很多API。以下是如何在 ImageMagick 命令行中执行此操作。

Input:

convert image.png PNG8:result1.png

PNG8:表示 256 色和二进制透明度。这意味着要么完全透明,要么完全不透明。这会导致边缘周围出现锯齿(阶梯)。如果您愿意设置背景颜色来代替透明度,那么您可以在结果中保持平滑(抗锯齿)轮廓。所以对于白色背景。

convert image.png -background white -flatten PNG8:result2.png

ImageMagick 由 PHP Imagick 运行。所以你应该能够使用 PHP Imagick 来做到这一点。或者您可以从 PHP exec() 调用 ImageMagick 命令行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PHP 对具有透明 PNG 的 imagetruecolortopalette 产生错误结果 的相关文章

  • 免费 PHP 登录库 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • setcookie with expire=0 浏览器关闭后不会过期

    我使用setcookie来制作一个过期 0的cookie 从 PHP 文档来看 link http php net manual en function setcookie php cookie 过期的时间 这是一个 Unix 时间戳 所以
  • 在服务器上找不到本地主机或 phpMyAdmin:如何修复?

    我按照安装说明进行操作PHP MySQL and PHPMyAdmin 但是当我尝试访问时http localhost phpmyadmin 我收到此错误 未找到 在此找不到请求的 URL phpmyadmin 服务器 然后我尝试访问loc
  • 解决相关代码的低 FPS 问题以计算图像中的偏移

    我正在尝试使用相关性来跟踪对象 我在较大的图像中逐帧找到较小的补丁 为此 我发现补丁中的变化 并且相关性最大的地方 用新补丁更新补丁 我的代码是 cv Mat im float 2 imagePart out cv Mat im float
  • AWS-PHP-SDK / SNS 直接寻址返回错误

    您好 我正在使用 Laravel 4 设置来利用 AWS SNS 向我的 iOS 设备发送推送消息 从 AWS 控制台向我的设备发布命令效果很好 然后我尝试从 PHP sns AWS get sns sns gt publish array
  • CakePHP 视图包括其他视图

    我有一个 CakePHP 应用程序 在某些时候会显示带有产品媒体 图片或视频 的视图 我想知道是否有某种方式可以包含另一个威胁视频或威胁图片的视图 具体取决于标志 我想将这些 小视图 用于其他几个目的 所以它应该 像 蛋糕组件一样 以便重用
  • 如何从网站网址中隐藏 .html 扩展名

    我知道这个问题以前曾被问过 但有人知道隐藏 html 扩展名的好方法吗 我已经尝试了许多代码和许多答案https stackoverflow com https stackoverflow com 但我没有看到结果 那是我再问你一次 我有一
  • 使用 PHP/linux 将文件合并为单个 PDF

    我正在研究如何将多个 PDF 合并为一个 PDF 我正在寻找一个图书馆可靠且坚固尽可能 最好有一个库可以保留书签 鬼脚本 http pages cs wisc edu ghost 可以在保存书签的位置进行连接 但我遇到了麻烦 在一种情况下它
  • 使用值填充的 Symfony2 自定义字段类型

    这是先前问题的后续问题Symfony2 自定义表单类型或扩展 https stackoverflow com questions 24079288 symfony2 custom form type or extension 我正在尝试为订
  • Laravel Vue 组件只能传递数字?

    在我的 UserMenu vue 中我写道 export default props nameVal data return 并在blade php中
  • 通过互联网IP地址从一台计算机访问xampp到另一台计算机

    我试图从另一台计算机访问我的 xampp 它显示为禁止错误 然后我在 google 上搜索答案 因为他们告诉在 apache 文件夹中的 httpd conf 文件中更改一些设置 如下所示 Order Deny Allow Deny fro
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • PHP 编码风格回归;在开关/外壳中

    我们正在尝试为我们的团队实施新的编码风格指南 当未找到 break 时 php codeniffer 会在 switch case 语句上打印警告 如下所示 switch foo case 1 return 1 case 2 return
  • 一次从多个表中删除行

    我正在尝试将 2 个查询合并为一个这样的查询 result db gt query DELETE FROM menu WHERE name new or die db gt error result db gt query DELETE F
  • CodeIgniter:My_Lang 中的 get_instance

    我发现这个有用的国际化代码 http pastebin com SyKmPYTX http pastebin com SyKmPYTX 一切正常 除了我无法在此类中使用 CI 函数 我想从 DB 设置 languages 和 special
  • 从 Laravel 4 输入生成新数组

    我使用 Input all 从动态生成的表单中获取一些输入 我使用 jQuery 来允许用户添加字段 字段名称为 first names last names 和 emails input 变量现在看起来像这样 array size 4 t
  • PHP 检查当前日期是在设定日期之前还是之后

    我从数据库中提取一个日期 其格式为 dd mm YYYY 我想做的是检查当前日期 如果当前日期早于数据库中的日期 则需要打印数据库日期 如果是在之后 则需要打印 继续 有人能指出我正确的方向吗 if strtotime database d
  • Laravel 搜索关系

    我有两个相关的模型 我正在尝试在产品中进行搜索 并且仅显示实际搜索结果 而不是找到该产品的类别的所有产品 我不想搜索任何类别 因为无论搜索什么或找到什么 类别都会始终显示 Example I have the following categ
  • 矩形超出边界是什么意思

    PPB Graphics2D PaintImageData 矩形超出界限是什么意思 我几乎在我检查的每一段代码中都看到了它 最新的代码是 define my consumer key define my consumer secret oa
  • PHPUnit - 模拟 S3Client 无法正常工作

    库 aws aws sdk php 2 PHP 版本 PHP 5 4 24 cli 作曲家 json require php gt 5 3 1 aws aws sdk php 2 require dev phpunit phpunit 4

随机推荐