了解 BufferedImage.getRGB 输出值

Posted

技术标签:

【中文标题】了解 BufferedImage.getRGB 输出值【英文标题】:Understanding BufferedImage.getRGB output values 【发布时间】:2014-11-03 20:49:02 【问题描述】:

我正在使用这种方法获取图像中像素的整数值:

int colour = img.getRGB(x, y);

然后我打印出这些值,我看到黑色像素对应于“-16777216”之类的值,一种蓝色对应于“-16755216”之类的值等。有人可以解释一下这背后的逻辑吗价值?

【问题讨论】:

官方解释:DirectColorModel 【参考方案1】:

RGB int 颜色在其位中包含颜色的红、绿、蓝分量。您必须查看其二进制或十六进制表示,而不是将其视为整数(而不是查看其十进制表示)。

int 有 32 位,3x8 = 24 用于存储 RGB 分量(每个 8 位),格式如下:

               2          1          0
bitpos      32109876 54321098 76543210
------   --+--------+--------+--------+
bits     ..|RRRRRRRR|GGGGGGGG|BBBBBBBB|

您可以使用位掩码提取或设置组件:

int color = img.getRGB(x, y);

// Components will be in the range of 0..255:
int blue = color & 0xff;
int green = (color & 0xff00) >> 8;
int red = (color & 0xff0000) >> 16;

如果颜色还具有 alpha 分量(透明度)ARGB,则获取最后剩余的 8 位。

           3          2          1          0
bitpos    10987654 32109876 54321098 76543210
------   +--------+--------+--------+--------+
bits     |AAAAAAAA|RRRRRRRR|GGGGGGGG|BBBBBBBB|

以及价值:

int alpha = (color & 0xff000000) >>> 24; // Note the >>> shift
                                         // required due to sign bit

alpha 值为 255 表示颜色完全不透明,值为 0 表示颜色完全透明。

你的颜色:

你的颜色是color = -16755216,它有:

blue : 240         // Strong blue
green:  85         // A little green mixed in
red  :   0         // No red component at all
alpha: 255         // Completely opaque

【讨论】:

我投了赞成票,因为这是我找到的最清楚的解释,不过,我不明白上面 bitpos32222222 22222222 111111 的含义,你能澄清一下吗? @juanmf int 有 32 位,范围从 0 到 31(如果从零开始,即第一个为 0)。我写了 bitpos vertically33 2222222222 1111111111 是 bitpos 的第一个数字(十位)。最右边的位有位位置0,所以最左边的位位置是31,旁边是30,旁边是29,依此类推。您必须一起阅读数字及其下方的数字:垂直。这只是一个很好的布局格式。 我使用的是>> 而不是>>>,这并不明显。谢谢。 你需要什么掩码不能直接移位吗? “由于符号位而需要”是什么意思? @Lupos 这意味着如果数字为负数(最高位为 1),则使用 >> 将引入非零值。 >>> 带零,即使数字是负数。【参考方案2】:

getRGB(int x, int y) 返回位置 (x,y) 的颜色像素值。 您误解了返回的值。 它是二进制格式。 就像 11...11010101 一样,它作为 int 值提供给您。 如果您想获得该值的 RGB(即红、绿、蓝)分量,请使用 Color 类。例如

Color mycolor = new Color(img.getRGB(x, y));

然后您可以使用getRed()getGreen()getBlue()getAlpha() 获得红色、绿色或蓝色值。 然后这些方法将以熟悉的格式返回一个int 值,其值为0 < value < 255

int red = mycolor.getRed();

如果您不想使用Color 类,则需要使用按位运算来获取其值。

【讨论】:

这个答案很好,但无法解决 alpha 通道。查看其他答案。 @Brick Color 类也有 getAlpha() 方法,它会给你 alpha 值。我在回答中提到了它。【参考方案3】:

我是explained in the docs:

返回默认 RGB 颜色模型 (TYPE_INT_ARGB) [...]

中的整数像素

所以你得到 8 位 alpha 通道,8 位红色,8 位绿色,8 位蓝色。

检查该值的一种简单(且缓慢的方法)是使用new java.awt.Color(colour, true);,然后调用getter。

或者您可以将该值打印为无符号 32 位十六进制值:Integer.toString(colour, 16)。输出的每两个字符将是 ARGB 集的一部分。

【讨论】:

【参考方案4】:

查看ColorModel.getRgb的implementation:

589  public int getRGB(int pixel) 
590        return (getAlpha(pixel) << 24)
591             | (getRed(pixel) << 16)
592             | (getGreen(pixel) << 8)
593             | (getBlue(pixel) << 0);
594   

【讨论】:

【参考方案5】:

其实,你可以通过Integer.toBinaryString(-16755216)将int转换成二进制字符串,即11111111000000000101010111110000。它由4个字节组成:alpha,red,green,blue。这些值是未预乘的,这意味着任何透明度都仅存储在 alpha 组件中,而不是存储在颜色组件中。组件存储如下 (alpha

【讨论】:

以上是关于了解 BufferedImage.getRGB 输出值的主要内容,如果未能解决你的问题,请参考以下文章

e671. 在缓冲图像中存取像素

解决oracle中sqlplus工具输错字符乱码,空格乱码的问题

一场员工高管间的口水战,员工输了

Docker员工自述:我们为什么“输”给了Kubernetes?

Docker员工自述:我们为什么“输”给了Kubernetes?

WebSocket 基础与应用系列—— Engine.IO 原理了解