for(unsigned int h=0; h<ImageBits.iHeight; h++)
{
for(unsigned int w=0; w<ImageBits.iWidth; w++)
{
// So in this loop - if our data isn't aligned to 4 bytes, then its been padded
// in the file so it aligns...so we check for this and skip over the padded 0's
// Note here, that the data is read in as b,g,r and not rgb as you'd think!
unsigned char r,g,b;
fread(&b, 1, 1, fp);
fread(&g, 1, 1, fp);
fread(&r, 1, 1, fp);
ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);
}// End of for loop w
//If there are any padded bytes - we skip over them here
if( iNumPaddedBytes != 0 )
{
unsigned char skip[4];
fread(skip, 1, 4 - iNumPaddedBytes, fp);
}// End of if reading padded bytes
}// End of for loop h
我不明白这个陈述以及它如何存储像素的rgb值
ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);
我读了&lt;&lt;&lt;&lt;&lt;按位移位运算符,但我仍然不明白它是如何工作的。有人可以帮助我。
答案 0 :(得分:2)
您需要将红色,绿色和蓝色的单独值转换为单个变量,因此分别将它们16和8位推送到“左”,这样它们对齐红色的8位(开始 - 16),然后你获得8位绿色(开始 - 8)和剩余颜色。
请考虑以下事项:
Red -> 00001111
Green -> 11110000
Blue -> 10101010
Then RGB -> that has 24 bits capacity would look like this initially ->
-> 00000000 00000000 00000000
(there would actually be some random rubbish but it's easier to
demonstrate like this)
Shift the Red byte 16 places to the left, so we get 00001111 00000000 00000000.
Shift the Green byte 8 places to the left, so we have 00001111 11110000 00000000.
Don't shift the Blue byte, so we have 00001111 11110000 10101010.
您可以使用联盟获得类似的结果。以下是关于我们为什么这样做的说明。访问变量的唯一方法是使其具有地址(通常绑定到变量名称或别名)。
这意味着我们只有第一个字节的地址,并且还保证如果它是一个3字节宽的变量,则我们所寻址的字节旁边的以下两个字节属于我们。所以我们可以从字面上“推动位”到左边(移位),以便它们“流”到变量的剩余字节中。我们也可以在那里使用指针算术指针,或者正如我已经提到的那样,使用union。
答案 1 :(得分:1)
位移动将构成值的位移动到您指定的数字。
在这种情况下,它使用颜色值完成,这样您就可以在单个4字节结构中存储多个1字节组件(例如RGBA,范围为0-255),例如int
取这个字节:
00000011
等于3的十进制数。如果我们想为RGB和A通道存储值3,我们需要将此值存储在int中(int为32位)
R G B A
00000011 00000011 00000011 00000011
正如你所看到的那样,这些位被设置为4组,每组8,并且都等于值3,但是如何以这种方式存储R值是什么意思?
如果你摆脱了G / B / A值,你就会被遗弃
00000011 00000000 00000000 00000000
仍然不等于3 - (实际上它是一些大数字 - 我认为是12884901888)
为了将此值放入int的最后一个字节,您需要将位移到右侧24位。例如
12884901888&gt;&gt; 24
然后这些位看起来像这样:
00000000 00000000 00000000 00000011
你会得到你的价值'3'
基本上它只是一种在存储结构中移动位的方法,以便您可以更好地操纵值。将RGBA值放入单个值通常称为填充位
答案 2 :(得分:1)
让我们把它想象成几个步骤,然后你会看到它有多简单。
假设我们有ARGB 32位变量,可以看作是
int rgb = {a: 00, r: 00, g: 00, b: 00}
(当然,这不是有效的代码,让我们暂时离开A)。
当然,每种颜色的值都是8位。
现在我们要放置一个新值,每种颜色都有三个8位变量:
unsigned char r = 0xff, g=0xff, b=0xff
。
我们实际上在做的是采用32位变量,然后执行此操作:
rgb |= r << 16
(向左移动红色16位。它右边的所有内容都将保持为0)
现在我们有了
rgb = [a: 00, r: ff, g: 00, b: 00]
现在我们这样做:
rgb = rgb | (g << 8)
(意思是取现有价值并将其与绿色一起移动到其位置)
所以我们有[a: 00, r: ff, g: ff, b: 00]
最后......
rgb = rgb | b
(意思是取值并将其与蓝色8位进行或运算。其余的保持不变)
给我们留下[a: 00, r: ff, g: f, b: ff]
表示32位(实际上是因为Alpha与此示例无关)24种颜色。