这个Java方法使用位运算符做什么?

3

我不熟悉位运算。这是一个图像处理算法。发生了什么?

void binarize50(int pixels[]) {
        for(int i = 0; i < pixels.length; i++) {
            int gray = ((pixels[i] & 0xff) + ((pixels[i] & 0xff00) >> 8) + ((pixels[i] & 0xff0000) >> 16)) / 3;
            pixels[i] = gray < 128 ? 0xff000000 : 0xffffffff;
        }
}

我发现 (pixels[i] & 0xff) 只是在某种程度上“标准化”,让像素/字节成为介于0到255之间的正值。
(pixels[i] & 0xff00 >> 8) 是什么意思? 0xff00是什么? 如果灰度小于128,为什么像素变成0xff000000,否则变成0xffffffff?
5个回答

5
它的功能取决于颜色模型以及颜色在内存中的表示方式。我猜它会根据50%的阈值将普通的ARGB图像转换为黑白图像。(使所有亮度小于50%的像素完全变黑,其他的完全变白。)
"pixels[i] & 0xff00 >> 8"的作用是什么?
- pixel[i]是已知的 :-) - & ff00掩盖第二个字节中的位 - >> 8向右移动8个位置(即使最右边的字节掉落到边缘)
"0xff00"是什么?
0xff00是十六进制字面量,表示值65280(或二进制1111111100000000)
如果灰度<128,像素变成0xff000000,否则为0xffffffff?
这行代码:
int gray = ((pixels[i] & 0xff) +
            ((pixels[i] & 0xff00) >> 8) +
            ((pixels[i] & 0xff0000) >> 16)) / 3;

将红、绿、蓝三个分量相加并除以三(求平均值)。

这行文字

pixels[i] = gray < 128 ? 0xff000000 : 0xffffffff;

大概意思是如果灰度小于一半,像素应该完全是黑色的,否则应该完全是白色的。


1
+1: 0xff000000 表示它是黑色而不是透明的,假设它是 ARGB 而不是 RGB 格式。 - Peter Lawrey

5
使用0xff等按位与操作符进行按位掩码运算。由于Java中的int是32位的,因此可以将0xff看作00000000_00000000_00000000_111111110xff00看作00000000_00000000_11111111_00000000等等。它们省略了前导零。
因此,如果使用pixels[i] & 0xff,发生的情况是你会获得一个int,其最后8位与pixels[i]相同,其余位设置为零。 >>操作符是右移操作。它将按位模式向右移动表示的位数。如果b包含00110011_11001100_00010110_01001100,并且执行b >> 8,则会得到00000000_00110011_11001100_00010110。最后的8位被“截去”,同时在左边填充了零。我不记得这个操作是否会在左侧填入1,如果领先的比特是1,则可能有人可以证实或否认这一点。
了解了这一点,让我们来看看这行:
int gray = ((pixels[i] & 0xff) + ((pixels[i] & 0xff00) >> 8) + ((pixels[i] & 0xff0000) >> 16)) / 3;

这里的操作是这样的:我们按如下方式创建一个int(不是准确的代码执行顺序,只是为了说明):
  • pixels [i] 被掩码,只保留最后8位,其余变成0。
  • pixels [i] 被掩码,只保留第8-15位(从右往左数,从0开始),其余变为0。然后将结果向右移动8位。如果我们以 00001111_00001111_10101010_00110011 开头,则结果为 00000000_00000000_00000000_10101010。
  • pixels [i] 被掩码,只保留位16-23,然后向右移动16位。
  • 上述三个操作的结果被相加...
  • 该结果除以3。
那么这到底实现了什么呢?基本上就是忽略了pixels [i] 的前8位,并且接下来的3个8位段分别被解释为介于0和255之间的单个值,取平均值。
然后将该结果与128进行比较。如果它更低,pixels [i] 就设置为0xff000000,否则它将设置为0xffffffff。
这是您在对编码为int的颜色进行操作时遇到的典型位操作。这可能是ARGB方案,其中int的前8位是alpha(透明度),接下来的8位是红色,再接下来的8位是绿色,最后8位是蓝色。或者是其变种。0xff000000将完全不透明黑色,而0xffffffff是完全不透明白色。

+1,对于不太了解位运算的人来说,这是一个非常好的答案! :-) - epoch

2

(pixels[i] & 0xff) = 0到255之间的蓝色值

(pixels[i] & 0xff00) >> 8 = 0到255之间的绿色值

(pixels[i] & 0xff0000) >> 16) = 0到255之间的红色值

然后你需要对上述3个值求平均。

接下来根据灰度值将其变为白色或黑色,即小于50%的灰度为黑色,否则为白色。


1

(pixels[i] & 0xff00) >> 8 取整数的第二个字节,它代表绿色 - & 使除了第8-15位之外的所有位都为零,>> 将它们向右移动8位,因此如果数字是(以位表示)0101000100001100:

0101000100001100 & 0xff = 0101000100001100 & 1111111100000000 = 0101000100000000.
0101000100000000 >> 8 = 01010001

对于((pixels[i] & 0xff0000) >> 16)也是一样的。

然后你取它们的平均值(/3),判断颜色是更接近白色还是黑色( gray < 128 )。根据这个条件,你可以将像素点变成黑色或者白色。


1

0xFF00 是一个位掩码,表示二进制表示中的 1111111100000000。

因此,当您将此掩码应用于数字时,您会留下高8位。

运算符 >> 表示向右移位。例如,11110000 >> 2 = 00111100。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接