【问题标题】:How to create 8-bit PNG from BufferedImage?如何从 BufferedImage 创建 8 位 PNG?
【发布时间】:2022-02-05 18:32:19
【问题描述】:

我有一个 Java 程序,它可以创建仅包含黑色像素和 100% 透明像素的复合 png 图像。我试图尽可能减小这些复合材料的大小,我注意到 ImageIO.write 总是输出 32 位 PNG。考虑到图像总共只有两种颜色,我想将它们保存为 8 位,但我认为没有办法使用标准 Java 函数来做到这一点。

有谁知道任何可以从 BufferedImage 创建 8 位 png 的预构建函数?也欢迎任何其他减小这些 png 大小的建议!

【问题讨论】:

  • 如果将它们保存为 GIF 会怎样? (我问是因为它仅限于 256 种颜色。)
  • 平均而言,32 位 PNG 比包含相同像素的 GIF 小。
  • 这确实提醒了我,您实际上可以将 GIF 中的索引颜色数量减少到 2... 不过,我不确定如果没有外部函数我将如何实现这一点。
  • 图片是如何加载/使用的?通过您控制的其他 Java 代码?
  • 是的,图像是在我自己的程序中生成的,变成一个空白的 BufferedImage。

标签: java png bufferedimage


【解决方案1】:

我不确定,但我猜ImageIO 使用BufferedImage 使用的任何type。尝试使用可用的不同类型。 TYPE_CUSTOM 和 TYPE_BYTE_BINARY 看起来很有希望。

【讨论】:

  • 有趣的想法,但我不确定。看来 TYPE_BYTE_BINARY 不支持 alpha 通道,我需要保持透明度。不过,我想知道 TYPE_CUSTOM 。如果我将 BufferedImage 定义为 TYPE_CUSTOM 很好,但我将如何实际更改 ImageIO 的解释方式?
  • 我不知道从未使用过 TYPE_CUSTOM,唯一想到的是 BufferedImage 类型,但我没有真正的答案 :(
【解决方案2】:

我不得不把它放在后座上一会儿,但我昨天又回来了,想出了怎么做。基本上它归结为使用com.sun.imageio.plugins.png 下的类和自定义ImageWriteParam。

我必须自己构建颜色表(不太难,只是字节数组)。然后将颜色表传递给ImageTypeSpecifier.createIndexed。返回的结果 ImageTypeSpecifier 允许您创建一个 BufferedImage 我将像素复制到其中。

接下来,我使用PNGMetadata 创建了自定义PNG 标头(需要阅读大量有关PNG 规范的内容,但总体而言非常简单)。然后,我使用所述元数据和 BufferedImage 创建了一个新的IIOImage。

最后,我创建了一个PNGImageWriter 并从中获得了默认的ImageWriteParam。然后我简单地将之前的ImageTypeSpecifier 传递给它的setDestinationType 方法。最后一步是通过将 IIOImage 和 ImageWriteParam 传递给 PNGImageWriter 将 PNG 写入磁盘。

其中许多类的文档非常少,但它们的功能很棒。通过这样做,我创建了一个包含位深度为 1 的最小 PNG(因为只有两种颜色),这将我的 PNG 的大小平均减少了 78%!!!非常值得努力。

【讨论】:

  • 从现有的高彩色图像中创建最佳调色板所需的量化通常是最困难的一步,不过...
猜你喜欢
  • 1970-01-01
  • 2011-01-23
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
  • 2011-05-13
  • 1970-01-01
相关资源
最近更新 更多