将一幅图像转换为灰度图

转载:http://www.cnblogs.com/tingshuo/archive/2011/05/16/2047797.html

灰度图是指用灰度表示的图像,灰度是在白色和黑色之间分的若干个等级,其中最常用的是256级,也就是256级灰度图。灰度图在医学、航天等领域有着广泛的应用。

那么如何将一幅彩色图像转换为灰度图呢?根据人眼对红绿蓝三色的敏感程度,可以使用以下比例式进行转换:

         Gray = R*0.3+G*0.59+B*0.11

这也是最常用的一种转换,另外还有一种常用的转换叫平均值法,即取去红绿蓝三色的平均值为灰度:

       Gray=(R+G+B)/3;

下面来写一段程序实现第一种转换算法,显然对于对于一幅256级灰度图,每个像素采用一个字节表示足矣,即为8位位图。对于8位位图的保存,真正的RGB数据是保存在调色板里的,而实际的数据仅仅是保存的调色板内的像素值的索引。

复制代码
  
  
1 #include " stdafx.h " 2 #include < stdio.h > 3 #include < string > 4 #include < math.h > 5 #include < windows.h > 6 using namespace std; 7 8 9 // 将位图转换为256色灰度图 10 void ToGray( const string & srcFile, const string & desFile) 11 { 12 BITMAPFILEHEADER bmfHeader; 13 BITMAPINFOHEADER bmiHeader; 14 15 FILE * pFile; 16 if ((pFile = fopen(srcFile.c_str(), " rb " )) == NULL) 17 { 18 printf( " open bmp file error. " ); 19 exit( - 1 ); 20 } 21 // 读取文件和Bitmap头信息 22 fseek(pFile, 0 ,SEEK_SET); 23 fread( & bmfHeader, sizeof (BITMAPFILEHEADER), 1 ,pFile); 24 fread( & bmiHeader, sizeof (BITMAPINFOHEADER), 1 ,pFile); 25 // 先不支持16位位图 26 int bitCount = bmiHeader.biBitCount; 27 if (bitCount == 16 ) 28 { 29 exit( - 1 ); 30 } 31 double byteCount = ( double )bitCount / 8 ; 32 int nClr = 0 ; 33 if (bitCount < 16 ) 34 { 35 nClr = bmiHeader.biClrUsed ? bmiHeader.biClrUsed : 1 << bitCount; 36 if (nClr > 256 ) 37 nClr = 0 ; 38 } 39 // 读取调色板 40 RGBQUAD * quad = NULL; 41 if (nClr > 0 ) 42 { 43 quad = new RGBQUAD[nClr]; 44 fread(quad, sizeof (RGBQUAD) * nClr, 1 ,pFile); 45 } 46 47 int srcW = bmiHeader.biWidth; 48 int srcH = bmiHeader.biHeight; 49 // 原图像每一行去除偏移量的字节数 50 int lineSize = bitCount * srcW >> 3 ; 51 // 偏移量,windows系统要求每个扫描行按四字节对齐 52 int alignBytes = (((bmiHeader.biWidth * bitCount + 31 ) & ~ 31 ) >> 3 ) 53 - ((bmiHeader.biWidth * bitCount) >> 3 ); 54 // 原图像缓存 55 int srcBufSize = lineSize * srcH; 56 BYTE * srcBuf = new BYTE[srcBufSize]; 57 int i,j; 58 // 读取文件中数据 59 for (i = 0 ; i < srcH; i ++ ) 60 { 61 fread( & srcBuf[lineSize * i],lineSize, 1 ,pFile); 62 fseek(pFile,alignBytes,SEEK_CUR); 63 } 64 // 256色位图调色板 65 RGBQUAD * quadDes = NULL; 66 quadDes = new RGBQUAD[ 256 ]; 67 for (i = 0 ; i < 256 ; i ++ ) 68 { 69 // 灰度图的RGB值相等 70 quadDes[i].rgbBlue = quadDes[i].rgbGreen = quadDes[i].rgbRed = i; 71 } 72 // 灰度图每个像素采用8位表示 73 int desBufSize = (((srcW * 8 + 31 ) & ~ 31 ) >> 3 ) * srcH; 74 BYTE * desBuf = new BYTE[desBufSize]; 75 // 每个扫描行占用字节数 76 int desLineSize = ((srcW * 8 + 31 ) >> 5 ) * 4 ; 77 78 for (i = 0 ; i < srcH; i ++ ) 79 { 80 for (j = 0 ; j < srcW; j ++ ) 81 { 82 // 从调色板中读取RGB值 83 if (nClr > 0 ) 84 { 85 unsigned int pos = srcBuf[i * lineSize + int (j * byteCount)]; 86 desBuf[i * desLineSize + j] = 0.3 * quad[pos].rgbRed 87 + 0.59 * quad[pos].rgbGreen 88 + 0.11 * quad[pos].rgbBlue; 89 } 90 else 91 desBuf[i * desLineSize + j] = 0.3 * srcBuf[i * lineSize + int (j * byteCount)] 92 + 0.59 * srcBuf[i * lineSize + int (j * byteCount) + 1 ] 93 + 0.11 * srcBuf[i * lineSize + int (j * byteCount) + 2 ]; 94 } 95 } 96 97 // 创建目标文件 98 HFILE hfile = _lcreat(desFile.c_str(), 0 ); 99 // 文件头信息 100 BITMAPFILEHEADER nbmfHeader; 101 nbmfHeader.bfType = 0x4D42 ; 102 nbmfHeader.bfSize = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER) 103 + 256 * sizeof (RGBQUAD) + srcW * srcH; 104 nbmfHeader.bfReserved1 = 0 ; 105 nbmfHeader.bfReserved2 = 0 ; 106 nbmfHeader.bfOffBits = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD); 107 // Bitmap头信息 108 BITMAPINFOHEADER bmi; 109 bmi.biSize = sizeof (BITMAPINFOHEADER); 110 bmi.biWidth = srcW; 111 bmi.biHeight = srcH; 112 bmi.biPlanes = 1 ; 113 bmi.biBitCount = 8 ; 114 bmi.biCompression = BI_RGB; 115 bmi.biSizeImage = 0 ; 116 bmi.biXPelsPerMeter = 0 ; 117 bmi.biYPelsPerMeter = 0 ; 118 bmi.biClrUsed = 256 ; 119 bmi.biClrImportant = 0 ; 120 121 // 写入文件头信息 122 _lwrite(hfile,(LPCSTR) & nbmfHeader, sizeof (BITMAPFILEHEADER)); 123 // 写入Bitmap头信息 124 _lwrite(hfile,(LPCSTR) & bmi, sizeof (BITMAPINFOHEADER)); 125 if (quadDes) 126 { 127 _lwrite(hfile,(LPCSTR)quadDes, sizeof (RGBQUAD) * 256 ); 128 } 129 // 写入图像数据 130 _lwrite(hfile,(LPCSTR)desBuf,desBufSize); 131 _lclose(hfile); 132 if (quad) 133 { 134 delete[] quad; 135 quad = NULL; 136 } 137 if (quadDes) 138 { 139 delete[] quadDes; 140 quadDes = NULL; 141 } 142 } 143 144 int main( int argc, char * argv[]) 145 { 146 string srcFile( " e://t.bmp " ); 147 string desFile( " e://gray.bmp " ); 148 ToGray(srcFile,desFile); 149 system( " pause " ); 150 return 0 ; 151 }
复制代码

转换前的图像:

转换后的图像:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值