PHP imagecolorat(( 函数可用于获取图像像素的 RGB 值,如文档所示:
$im = imagecreatefrompng("php.png");
$rgb = imagecolorat($im, 10, 15);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
我完全不明白最后三行;我知道它们返回正确的值,但我无法弄清楚>>
运算符和&
运算符如何协同工作以做到这一点。有人可以解释一下吗?
作为参考,当$rgb = 9750526
时,RGB 值结果为(148,199,254)
。
感谢您的任何回复。
和>>是两个不同的按位运算符(PHP中的按位运算符(。它们使用值的位表示,这为我们提供了一些有用(且快速!(的可能性。
>>是右移。如果右移一个值,则会在表示中将所有位向右移动。如果你有"11100",右移两位,你就剩下"111"(右端移出的位消失(。>>右侧的数字表示要移位的位数。
并且是按位和的。如果您有两个值表示为 111000 和 101011,并决定按位和它们,则最终将得到 101000(两个值中设置相同位的位将为 1,否则为 0(。
我们现在有了理解上述代码所需的内容。 $rgb包含一个整数值(该值不感兴趣,但位模式很有趣(,它表示 24 位(RGBA 为 32 位,但我们在这里忽略它(。该值由 8 位表示红色、8 位表示绿色和 8 位表示蓝色组成。然而,我们不感兴趣的是这24位代表的数字,而是单独的R,G和B值是什么。
我们的值表示颜色的以下位:
rrrrrrrr gggggggg bbbbbbbb
如果我们用>> 16 移动这个位掩码,我们将得到:
rrrrrrrr
这就是>> 16所做的,只给我们留下代表红色的位。由于我们现在已经将位一直向下移动,该值表示 [0, 255] 中的一个数字。然后我们添加 & 255(这里用十六进制表示法写成0xFF(以删除我们感兴趣的 8 上面的任何杂散位。现在,当我们查看如何获得 G 值时,我们将了解这种情况是如何发生的:
我们的价值观仍然勇敢地代表了不同的颜色:
rrrrrrrr gggggggg bbbbbbbb
如果我们用 8>>移动这个位掩码 8 位,我们将得到:
rrrrrrrr gggggggg
但是等等!这不仅是表示 g 的位,还包括表示 r 的位!这不是我们所追求的值(因为我们只想要g(。在上一个示例中,我们很幸运,因为我们没有在 r 上方设置任何位,但这次我们真的为我们完成了工作。但是我们知道 &,现在是时候看到它实际上是它的东西了。
我们现在有:
rrrrrrrr gggggggg
然后我们应用&255(代码中的0xFF(,它以位值表示为:
00000000 11111111
由于 & 只保留在两个操作数中设置的位,我们最终只会得到 g 值:
gggggggg
在移位值中表示红色的位现在为 0,我们只剩下表示原始颜色的绿色的位。当它们被移入代表 [0, 255] 的相同 8 位时,我们再次获得了我们的价值。
最后一个值更容易,因为它已经位于我们想要的位置:在代表 [0, 255] 的位中。我们可以在这里做&操作,然后从另一边出去:
rrrrrrrr gggggggg bbbbbbbb &
00000000 00000000 11111111
最终得到:
bbbbbbbb
我们也有蓝色值。
希望能解释它!
>>
表示逐位右移,因此位向右移动n(分别为16和8(位置:
R = 1 字节 = 8 位
RRGGBB >> 16 = 0000RR
RRGGBB >> 8 = 00RRGG
按位 AND 运算 &
用于删除结果中我们不想要的剩余内容,方法是使用除应保留的部分外所有地方均为零的掩码:
00RRGG & 0000FF = 0000GG
让我们试试:
$rgb = 9750526;
var_dump(sprintf('%032b', $rgb));
$rgb = 00000000100101001100011111111110//整数为 32 或 64 位 - b 部分为最后 8 位
您只需要第 3、2 和第 1 个字节,因此>>(移位(它们你得到二进制
$rgb >> 16 = string(32) "00000000000000000000000010010100" //r part is last 8 bits
$rgb >> 8 = string(32) "00000000000000001001010011000111" //g part is last 8 bits
0xFF 是和操作与11111111因此你得到
r = 10010100
g = 11000111
b = 11111110
我希望这些是(148,199,254(;)
我猜第一次出现,>>16,是将所有位向右移动,直到只剩下红色,然后用&0xFF切断数字的开头。虽然我无法分辨该示例中红色的位深度(我希望颜色是 3 字节的倍数(,但它有点像这样:
rrggbb = 125438 // input
>> 16 // shift right (might be 8 for this example)
0000rr = 000012 // result
& 0xFF // cut beginning
rr = 12
其他颜色也类似。
imageColorAt(( 返回一个包含红色、绿色和蓝色值的 24 位数字。红色值乘以 2^16,绿色乘以 2^8,蓝色保持"原样"。
在十六进制中,您的值是0x94C7FE;通过将其向右移动 16 位,您将丢失最后四个半字节,只剩下0x94。"& 0xFF"需要最后8位(因此它是多余的(。
通常这种转变是这样完成的:
$value = imageColorAt(...) // Gets 94C7FE
$blue = $value & 0xFF; // Takes the last "FE" (254 in decimal)
$value >>= 8; // Shifts right, 94C7 remains
$green = $value & 0xFF; // Takes "C7"
$value >>= 8; // Shifts right, 94 remains
$red = $value; // Takes "94" hex, which is 148 dec.