设置RGB值以减少PNG图像中的调色板

时间:2011-07-30 19:02:11

标签: java colors png

我有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图像中的颜色编号。

1 个答案:

答案 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

对应一种颜色 - 我将它们添加到注释行中。

最终只会在结果图像中使用这些颜色,其他所有颜色都会用最接近的颜色或近似颜色的图案近似:

(in - out)
(图像从Rekin's answer被盗。)

如果您想减少的不仅仅是6种颜色,而是更大的颜色,您只需要列出更多颜色。您可以在此处使用预定义列表,或者根据原始图像的统计数据对其进行调整(例如,如果图像主要由蓝天组成,则此处包含多个蓝色色调,但不包括其他颜色)。或者在几个预定义的调色板之间进行选择,查看与原始图像的差异最小。

使用IndexedColorModel,您也可以使用其他ColorModel实现之一。例如,这将是一个64色的空间,具有4个透明度级别,均匀分布(我认为),每个像素使用一个字节(每种颜色两位):

new DirectColorModel(8, 0xC0, 0x30, 0x0C, 0x03);

这个只使用一位透明度,而是使用三位绿色(人眼可以看得更清楚):

new DirectColorModel(8, 0xC0, 0x38, 0x06, 0x01);

我没有和PNG编码器一起测试它们,请执行此操作。