我有following method,它会缩小PNG图像中的调色板大小。
private BufferedImage setColour(BufferedImage image) {
IndexColorModel cm = new IndexColorModel(
3,
6,
new byte[]{-100, 0, 0, 0, -1, 0}, // r
new byte[]{0, -100, 60, 0, -1, 0}, // g
new byte[]{0, 0, 0, -100, -1, 0}); // b
BufferedImage img = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED,
cm);
Graphics2D g2 = img.createGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
return img;
}
据我所知,每个字节数组用于索引与PNG像素关联的调色板。我不明白的是,如何设置字节数组中的值,以便我只能 稍微 减少PNG图像中的颜色编号。
答案 0 :(得分:3)
索引颜色模型基本上列出了可以在BufferedImage中使用的所有颜色及其RGB值。
中的每一栏
// red, light green, dark green, blue, white, black
new byte[]{-100, 0, 0, 0, -1, 0}, // red part
new byte[]{ 0, -100, 60, 0, -1, 0}, // green part
new byte[]{ 0, 0, 0, -100, -1, 0} // blue part
对应一种颜色 - 我将它们添加到注释行中。
最终只会在结果图像中使用这些颜色,其他所有颜色都会用最接近的颜色或近似颜色的图案近似:
(图像从Rekin's answer被盗。)
如果您想减少的不仅仅是6种颜色,而是更大的颜色,您只需要列出更多颜色。您可以在此处使用预定义列表,或者根据原始图像的统计数据对其进行调整(例如,如果图像主要由蓝天组成,则此处包含多个蓝色色调,但不包括其他颜色)。或者在几个预定义的调色板之间进行选择,查看与原始图像的差异最小。
使用IndexedColorModel,您也可以使用其他ColorModel实现之一。例如,这将是一个64色的空间,具有4个透明度级别,均匀分布(我认为),每个像素使用一个字节(每种颜色两位):
new DirectColorModel(8, 0xC0, 0x30, 0x0C, 0x03);
这个只使用一位透明度,而是使用三位绿色(人眼可以看得更清楚):
new DirectColorModel(8, 0xC0, 0x38, 0x06, 0x01);
我没有和PNG编码器一起测试它们,请执行此操作。