0
 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);

我阅读了 << 位移位运算符,但我仍然不明白它是如何工作的。有人可以在这里帮助我吗?

4

3 回答 3

2

您需要将 Red、Green 和 Blue 的单独值转换为单个变量,因此您将它们分别推向“左”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.

您可以使用unions获得类似的结果。以下是我们为什么这样做的详细说明。访问变量的唯一方法是获取它的地址(通常绑定到变量名或别名)。

这意味着我们只有第一个字节的地址,并且还保证如果它是一个 3 字节宽的变量,则紧邻我们寻址字节的以下两个字节属于我们。所以我们可以从字面上将位“推”到左边(移动它们),这样它们就“流入”到变量的剩余字节中。我们也可以在那里对指针进行指针算术运算,或者正如我已经提到的,使用联合。

于 2012-05-25T14:46:54.287 回答
1

位移位按您指定的数字移动构成该值的位。

在这种情况下,它使用颜色值完成,以便您可以在单个 4 字节结构(例如 int)中存储多个 1 字节组件(例如 0-255 范围内的 RGBA)

取这个字节:

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

然后这些位看起来像这样:

00000000 00000000 00000000 00000011

你会有你的价值'3'

基本上,它只是一种在存储结构中移动位的方式,以便您可以更好地操作值。将 RGBA 值放入单个值通常称为填充位

于 2012-05-25T14:51:07.773 回答
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 位(实际上是 24,因为 Alpha 与此示例无关)颜色。

于 2012-05-25T14:55:36.060 回答