转自:http://hi.baidu.com/liaowuxukong/item/ea8553107da45e0ab98a1a8d
毕设中,第一步就是将一个图片转化为灰度图。
遂尝试用256的BMP转成灰度图,于是去查,啥东东是灰度图,得到如下解释。
什么叫灰度图?任何颜色都有红、绿、蓝三原色组成,假如原来某点的颜色为RGB(R,G,B),那么,我们可以通过下面几种方法,将其转换为灰度:
1.浮点算法:Gray=R*0.3+G*0.59+B*0.11
2.整数方法:Gray=(R*30+G*59+B*11)/100
3.移位方法:Gray =(R*28+G*151+B*77)>>8;
4.平均值法:Gray=(R+G+B)/3;
5.仅取绿色:Gray=G;
通过上述任一种方法求得Gray后,将原来的RGB(R,G,B)中的R,G,B统一用Gray替换,形成新的颜色RGB(Gray,Gray,Gray),用它替换原来的RGB(R,G,B)就是灰度图了。
太他妈坑爹了这个东西。
出个啥RGB,不能忍了,要知道我做的是256BMP,里面只有 颜色板 和 图像数据阵列。
于是绞尽脑汁的在图像数据阵列中将 RGB,分离出来,然后根据某个公式,求的GRAY。
但是之后,就囧了,将求得的GRAY赋给了原来的值。之后,验证了一下,果断是错的。
想着,BMP中的图像数据阵列都是索引值啊,这个直接赋值,肯定不是灰色的啊。
但是这个又是256色的,要体现256灰,怎么可能。
于是想到了,是不是要去改变一下这个图像的调色板。
根据这句话:通过上述任一种方法求得Gray后,将原来的RGB(R,G,B)中的R,G,B统一用Gray替换,形成新的颜色RGB(Gray,Gray,Gray),用它替换原来的RGB(R,G,B)就是灰度图了。
是不是调色板也要统一的改变一下呢,遂上网查了查,果然如此啊。。现将代码奉献如下:
BOOL WINAPI Gray(LPSTR lpDIBBits, LPBITMAPINFO lpbmi ,LPBITMAPCOREINFO lpbmc, LONG lWidth, LONG lHeight)
{
// 指向DIB象素的指针
BYTE * lpSrc;
// 图像每行的字节数
LONG lLineBytes;
// 灰度映射表
BYTE bMap[256];
// 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板
int i,j;
for (i = 0; i < 256; i ++)
{
// 计算该颜色对应的灰度值
bMap[i] = (BYTE)(0.299 * lpbmi->bmiColors[i].rgbRed +
0.587 * lpbmi->bmiColors[i].rgbGreen +
0.114 * lpbmi->bmiColors[i].rgbBlue + 0.5);
// 更新DIB调色板红色分量
lpbmi->bmiColors[i].rgbRed = i;
// 更新DIB调色板绿色分量
lpbmi->bmiColors[i].rgbGreen = i;
// 更新DIB调色板蓝色分量
lpbmi->bmiColors[i].rgbBlue = i;
// 更新DIB调色板保留位
lpbmi->bmiColors[i].rgbReserved = 0;
}
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值)
//逐行扫描
for(i = 0; i < lHeight; i++)
{
//逐列扫描
for(j = 0; j < lWidth; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 变换
*lpSrc = bMap[*lpSrc];
}
}
return TRUE;
}