使用ImageMagick将32位PNG转换为8位PNG,并保留半透明像素。

17

我想使用ImageMagick将32位PNG转换为8位PNG,但是半透明像素会丢失。如何解决这个问题?我正在使用以下命令:

convert original.png PNG8:output.png

相关:https://dev59.com/JnM_5IYBdhLWcg3wPAdF - Ilmari Karonen
3
这个问题不是重复的。这位作者抱怨在从24位转换为8位后失去了半透明像素。他已经拥有了从24位转换为8位的(正确)语法,他想知道它为什么会表现出这种方式(并且有一个很好的答案)。 - Mahmoud Al-Qudsi
1个回答

24
显然,即使PNG格式实际上允许8位索引色PNG中的任何颜色都可以完全或部分透明,但ImageMagick的“PNG8”格式说明符仅支持GIF样式的1位透明度。
使用ImageMagick可以通过使用PNG8:说明符,而只是使用-colors 256-colors 255*来减少图像中的颜色数量来生成索引8位PNG。不幸的是,至少根据我使用ImageMagick 6.8.9进行的测试,生成的图像具有一些相当奇怪且不必要丑陋的颜色量化伪影。
幸运的是,这个特定工作有一个更好的工具: pngquant。使用它,将32位RGBA PNG转换为8位彩色映射PNG并最小化质量损失就像这样简单:
pngquant 256 < original.png > output.png

作为一个快速演示,这里有一张简单的测试图片(带有半透明的阴影的星形图案),使用不同的方法转换成8位PNG格式:

Original pngquant 256 ImageMagick convert (-colors 255) ImageMagick convert (PNG8) ImageMagick convert (-colors 255, PNG8)

从左到右:

  1. 原始的32位RGBA PNG
  2. 使用pngquant 256 < input.png > output.png量化
  3. 使用convert input.png -colors 255 output.png*量化
  4. 使用convert input.png PNG8:output.png量化
  5. 使用convert input.png -colors 255 PNG8:output.png*量化

*) 在下面的评论中,建议使用-colors 255是必要的,“为‘背景’颜色保留一个条目。” 经过我的测试,我并没有观察到这实际上是正确的;使用-colors 256仍将生成8位颜色映射PNG,其量化伪影在质量上与-colors 255的输出相似,但细节有所不同。 尽管如此,为了保险起见,我以上面的示例使用了-colors 255。 通过减少一种颜色的颜色映射表大小本身不应显着影响结果的质量,因为使用pngquant 255进行测试将会演示


2
是的,我都试过了。第二个会把完全透明的像素变成黑色。我开始使用 pngquant 命令行工具代替 ImageMagick。它可以正确地保留 alpha 通道。 - Karmar
请尝试使用-colors 255而不是-colors 256。ImageMagick需要为“背景”颜色保留一个条目。 - Glenn Randers-Pehrson
@GlennRanders-Pehrson:理论上来说,PNG8格式允许256种颜色都可以是半透明的,所以不应该需要这样做。但显然ImageMagick不支持这一点,只能在调色板图像中输出类似GIF的1位透明度。无论如何,感谢您促使我更新这个旧答案。 :) - Ilmari Karonen
ImageMagick支持带有半透明度的8位索引PNG,但它不称之为“PNG8”。但是,无论PNG8是否支持半透明颜色都不重要;留出背景颜色的空间的要求仍然存在。尝试使用“convert in.png -colors 255 output.png”进行转换。 - Glenn Randers-Pehrson
2
不必保留背景颜色,但ImageMagick默认会保留一个。您可以使用“-define png:exclude-chunk=bKGD”来避免这种情况。使用“-colors 255”可能会使量化效果更好,并且不要指定PNG8:(PNG8使用一种快速而粗糙的量化方法,只需将较低位清零)。但实际上,我更喜欢使用pngquant而不是ImageMagick进行调色板生成。 - Glenn Randers-Pehrson
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接