了解ImageProcessing代码

时间:2012-10-17 11:14:35

标签: android c++ c image-processing android-ndk

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

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以及pixel =(char *)pixels + info-&gt; stride是怎样的;作品?  我不是一个c / c ++人,对图像处理知之甚少。 谢谢

2 个答案:

答案 0 :(得分:4)

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

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

在与亮度因子相乘后,新值被写回到存储器中,这与上述提取的顺序相反,这次将它们向左移动并去除位,这是我们不想要的掩码

处理完一行图像后,会添加info->stride,因为出于优化目的,内存可能已对齐以填充32字节边界,因此单行可能比图像宽度长,因此“rest”字节被添加到指针。

答案 1 :(得分:2)

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

接下来我会回答你的问题。

  1. 如何提取RGB值

    line设置为指向像素参数:

    line = (uint32_t*)pixels;

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

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

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

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

    这里我们得到当前行,然后以0x00FF0000作为掩码的AND,得到line的24-16位。因此,使用RGB代码#123456作为示例,我们将在0x00120000变量中留下red。但它仍处于24-16位,所以我们右移16位将位移到0x00000012

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

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

  2. rgb_clamp做什么

    此功能只是确保红色,绿色或蓝色值为0或更高或255和更低。

    如果rbg_clamp的参数为-20,它将返回0,这将用于设置RGB值。如果参数为rbg_clamp为270,则返回255。

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

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

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

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

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

  5. 希望有所帮助