我是android ndk的新手。我已经开始通过图像处理示例学习 ruckus和by 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 ++人,对图像处理知之甚少。 谢谢
答案 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/
接下来我会回答你的问题。
如何提取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
rgb_clamp
做什么
此功能只是确保红色,绿色或蓝色值为0或更高或255和更低。
如果rbg_clamp
的参数为-20,它将返回0,这将用于设置RGB值。如果参数为rbg_clamp
为270,则返回255。
每种颜色的RGB值不得超过225或低于0.在此示例中,255为最亮,0为最暗值。
我们为什么要设置像素
看来我们正在改变像素的亮度,并准备好将值设置为显示。
pixels = (char*)pixels + info->stride;
如何运作?
在不知道info
类型的AndroidBitmapInfo
变量的结构的情况下,我猜info->stride
指的是位图的宽度(以字节为单位),因此line
将成为下一行在下一个循环迭代中。
希望有所帮助