1

我是 android ndk 的新手。我已经开始通过
ruckusIBM 博客的图像处理示例进行学习。我没有得到下面几行。任何人都可以帮助我理解代码片段吗?

static void brightness(AndroidBitmapInfo* info, void* pixels, float brightnessValue){
    int xx, yy, red, green, blue;
    uint32_t* line;

    for(yy = 0; yy < info->height; yy++){
            line = (uint32_t*)pixels;
            for(xx =0; xx < info->width; xx++){


              //extract the RGB values from the pixel
                red     = (int) ((line[xx] & 0x00FF0000) >> 16);
                green   = (int)((line[xx] & 0x0000FF00) >> 8);
                blue    = (int) (line[xx] & 0x00000FF );

        //manipulate each value
        red = rgb_clamp((int)(red * brightnessValue));
        green = rgb_clamp((int)(green * brightnessValue));
        blue = rgb_clamp((int)(blue * brightnessValue));

        // set the new pixel back in
        line[xx] =
          ((red << 16) & 0x00FF0000) |
          ((green << 8) & 0x0000FF00) |
          (blue & 0x000000FF);
            }

            pixels = (char*)pixels + info->stride;
        }
}
`
    static int rgb_clamp(int value) {
  if(value > 255) {
    return 255;
  }
  if(value < 0) {
    return 0;
  }
  return value;
}

RGB 值是如何被提取的,这个 rgb_clamp 做了什么。为什么我们要设置新的 Pixell 以及像素 = (char*)pixels + info->stride; 作品?我不是 ac/c++ 人,对图像处理了解不多。谢谢

4

2 回答 2

4

首先让我们谈谈一个像素。据我所见,它是至少 3 个通道的组合:r、g 和 b,它们都存储在一个uint32_t值中,格式为 0x00RRGGBB(32bit / 4 个通道 = 8bit 每通道,因此值范围为0..255)。因此,要获得分离的 r、g 和 b 值,您需要将它们屏蔽掉,这在下面的三行中完成//extract the RGB values。例如红色组件... 使用掩码 0x00FF0000 和&运算符,您将除红色通道中设置的位之外的每个位都设置为 0。但是当你只是用 来掩盖它们时0x00RRGGBB & 0x00FF0000 = 0x00RR0000,你会得到一个非常大的数字。要获得 0 到 255 之间的值,您还必须将位向右移动,这就是使用>>-操作员。>> 16因此对于后一个示例:应用掩码后,您得到0x000000RR0x00RR0000 ,然后将这 16 位右移(由于蓝色值已经在“正确”位位置,因此无需移位。

第二个问题:做什么rgb_clamp很容易解释。它确保您的 r、g 或 b 值乘以您的亮度因子,不会超过值范围 0..255。

在与亮度因子相乘之后,新值被写回内存,这与上述提取的顺序相反,这次将它们向左移动并删除位,这是我们不希望使用掩码的。

处理完图像的一行后,info->stride将添加指针。

于 2012-10-17T12:07:31.070 回答
2

首先,我建议你在这里阅读 C 书:http ://publications.gbdirect.co.uk/c_book/

接下来,我将解决您的问题。

  1. 如何提取 RGB 值

    line设置为指向像素参数:

    line = (uint32_t*)pixels;

    那是pixels一个 32 位无符号整数数组

    &然后对于位图的高度和宽度,使用按位与 ( ) 和位移右 ( )的组合提取 RGB 值>>

    让我们看看你是如何变红的:

    red = (int) ((line[xx] & 0x00FF0000) >> 16);

    在这里,我们得到当前行,然后与0x00FF0000作为掩码的 AND,这从line. 因此,以 RGB 代码 #123456 为例,我们将保留0x00120000red变量中。但它仍然在 24-16 位位置,所以我们右移 16 位以将位向下移动到0x00000012.

    我们对绿色和蓝色值执行此操作,调整 AND 掩码和位数以右移。

    有关二进制算术的更多信息,请参见:http ://publications.gbdirect.co.uk/c_book/chapter2/expressions_and_arithmetic.html

  2. rgb_clamp做什么

    此函数仅确保红色、绿色或蓝色值为 0 或以上或 255 及以下。

    如果参数 torbg_clamp为 -20 则返回 0,用于设置 RGB 值。如果参数是rbg_clamp270,它将返回 255。

    每种颜色的 RGB 值不得超过 225 或低于 0。在此示例中,255 是最亮的值,0 是最暗的值。

  3. 为什么我们要设置像素回来

    看来我们正在更改像素的亮度,并将值设置回准备显示。

  4. 如何pixels = (char*)pixels + info->stride;工作?

    在不知道类型info变量的结构的情况下AndroidBitmapInfo,我猜想info->stride是指位图的宽度(以字节为单位),因此line将成为下一次循环迭代的下一行。

希望有帮助

于 2012-10-17T11:59:09.127 回答