PHP错误结果为带有PNG和透明度的imagetruecolortopalette [英] PHP wrong result for imagetruecolortopalette with PNG with transparency

查看:113
本文介绍了PHP错误结果为带有PNG和透明度的imagetruecolortopalette的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to write a PHP script that resizes a PNG image and then converts it to PNG-8 bit mode. So the size of the resulting file will be smaller but without too much quality loss.

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

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

The resize works perfectly, preserving also image transparency:

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

The problem is when I convert the image in 8 bit:

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);

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

The resulting image is this, with the transparency all around and a little inside the image:

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

If I set 256 colors instead of 255:

imagetruecolortopalette($resizedImg, true, 256);

图片将具有黑色背景:

此图像出现类似的结果(请注意255种颜色情况下的半透明):

A similar result occurs with this image (note the half transparency for the case with 255 colors):

原始: 255种颜色: 256种颜色:

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;
}

我尝试过的事情:

// 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;

结果:

  • https://stackoverflow.com/a/55402802/2342558
    • https://stackoverflow.com/a/55402802/2342558
    • 没什么改变

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

      同样,无需调整图像大小(删除imagecopyresampled并修改变量名称),结果是相同的.

      Also without resizing the image (removing imagecopyresampled and adapting the variables name) the result is the same.

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

      Can you please help me to make it work and to understand the reason for this strange behaviour?

      phpinfo()中的某些信息:

      • PHP 7.0.33
      • GD捆绑在一起(兼容2.1.0)
      • PNG Support已启用
      • libPNG 1.5.13.
      • PHP 7.0.33
      • GD bundled (2.1.0 compatible)
      • PNG Support enabled
      • libPNG 1.5.13.

      编辑:

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

      In GIMP v.2.8.22 I can save an image for Web with these properties:

      PNG-8
      256 colors palette
      Dither: Floyd-Steinberg / Floyd-Steinberg 2 / positioned
      

      它会产生与原始图像几乎相同的缩小图像.

      and it produce a reduced image almost identical of the original.

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

      Also pngquant, tinypng, and many others do the same work, but I need to do it with PHP.

      Edit2 :

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

      Unfortunetly, I can't use ImageMagick because my code is in a shared hosting without it installed.

      Edit3 :

      表示未安装imagemagick模块.

      Edit4 :

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

      The bounty expires, in the following days let's me do some tests with your responses, maybe there is a solution with only PHP.

      编辑5 :

      这些是我对您的回答的尝试(于2019-10-02更新).

      These are my attempts with your answers (updated at 2019-10-02).

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

      托马斯·休伊泽尔(Tommas Huijzer)的答案:

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

      There are visible color banding in the penguin but the duck its ok (although sometimes the color tone is darker).

      EPB的答案:

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

      Only if the image has only pixels already completely transparent does it work very well (e.g. the duck).

      马克·塞切尔的答案:

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

      It makes completely transparent all pixels with an alpha, also if this alpha is very low, see the shadow below the penguin. Also some pixel at the edge of the duck are converted in black pixel or in full-transparent pixel.

      推荐答案

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

      You can do that quite easily in ImageMagick, which is distributed on Linux and is available for Windows and Mac OSX. There are also many APIs other than the command line. Here is how to do it in ImageMagick command line.

      输入:

      convert image.png PNG8:result1.png
      


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

      PNG8: means 256 colors and binary transparency. That means either full or no transparency. This causes the aliasing (stair-stepping) around the edges. If you are willing to set a background color in place of transparency, then you can keep the smooth (antialiased) outline in the result. So for a white background.

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


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

      这篇关于PHP错误结果为带有PNG和透明度的imagetruecolortopalette的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆