Java 如何从BuffereImage创建8位PNG?

Java 如何从BuffereImage创建8位PNG?,java,png,bufferedimage,Java,Png,Bufferedimage,我有一个Java程序,可以创建只包含黑色像素和100%透明像素的复合png图像。我试图尽可能地减小这些合成的大小,我注意到ImageIO.write总是输出32位PNG。考虑到图像总共只有两种颜色,我想将它们另存为8位,但我不认为有办法用标准Java函数实现这一点 有人知道有任何预构建的函数可以从BuffereImage创建8位png吗?任何其他建议,以减少这些png的大小也是欢迎的 我不确定,但我猜ImageIO使用BufferedImage使用的任何类型。尝试使用可用的不同类型TYPE\u

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


有人知道有任何预构建的函数可以从BuffereImage创建8位png吗?任何其他建议,以减少这些png的大小也是欢迎的

我不确定,但我猜
ImageIO
使用
BufferedImage
使用的任何类型。尝试使用可用的不同类型
TYPE\u CUSTOM
TYPE\u BYTE\u BINARY
看起来很有希望。

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

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

接下来,我使用
PNGMetadata
创建了定制的PNG头文件(需要大量阅读PNG规范,但总体来说非常简单)。然后,我使用所述元数据和BuffereImage创建了一个新的
IIOImage

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


关于这些类的文档非常稀少,但是它们的功能非常强大。通过这样做,我创建了一个最小的PNG,其中包含一点深度1(因为只有两种颜色),这使我的PNG的大小平均减少了78%!!!非常值得付出努力。

如果将它们保存为GIF会发生什么?(我问是因为它被限制为256色。)平均而言,32位PNG比包含相同像素的GIF小。这确实提醒了我,你实际上可以将GIF中索引颜色的数量减少到2。。。不过,我也不确定如果没有外部功能,我将如何实现这一点。图像是如何加载/使用的?由您控制的其他Java代码生成?是的,图像是在我自己的程序中生成到一个空白的BuffereImage中。这个想法很有趣,但我不确定。似乎TYPE_BYTE_BINARY不支持alpha通道,我需要保持透明度。不过我想知道什么样的定制。如果我将BuffereImage定义为TYPE_CUSTOM,这很好,但是我该如何改变ImageIO对它的解释呢?我不知道从未使用过TYPE_CUSTOM,BuffereImage类型是我唯一想到的,但我没有真正的答案:(从现有的彩色图像中创建最佳调色板所需的量化通常是最困难的一步,尽管。。。