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

发布于 2024-11-27 03:49:39 字数 732 浏览 4 评论 0原文

我有以下方法,减少 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图像中的颜色数。

I have the following method, that reduces the palette size in a PNG image.

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;
}

I understand that each byte array is used for indexing the palette associated with a PNG pixel. What I don't understand, is how to set the values in the byte arrays so that I could only slightly reduce the colour number in the PNG image.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

单身情人 2024-12-04 03:49:39

索引颜色模型本质上列出了 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的回答 .)

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

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

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

这个空间将仅使用一位用于透明度,而不是使用三位来表示透明度。绿色(人眼看得更清楚):

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

我没有将它们与PNG编码器一起测试,请这样做。

The indexed color model essentially lists all colors that can be used in the BufferedImage, with their RGB values.

Each column in

//          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

corresponds to one color - I added them in the comment line.

Only these colors will finally be used in the resulting image, everything else will be approximated by the nearest color, or a pattern from the two nearest colors:

(in - out)
(Image stolen from Rekin's answer.)

If you want to reduce to not only 6 colors, but a larger number, you simply have to list more of them. You could either use a predefined list here, or adapt them from statistics of the original image (e.g. if the image consists mainly of blue sky, include several blue hues here, but not so much of the other colors). Or select between several predefined palettes, looking which gives the smallest difference to the original image.

Instead using IndexedColorModel, you could also use one of the other ColorModel implementations. For example, this would be a 64-color space with 4 transparency levels, equally distributed (I think), using one byte per pixel (two bits per color):

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

This one would use only one bit for transparency, instead using three bits for green (which human eyes can see more clearly):

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

I did not test them together with the PNG encoder, please do this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文