24位真彩色转换为8位灰度图片(完整代码)
分类: C#2011-03-04 09:29 4343人阅读 评论(5) 收藏 举报
nullfloatgdi+byte图像处理image
图像的灰度与二值化
http://www.cnblogs.com/maozefa/archive/2011/12/09/2281656.html
图像的灰度化与二值化是图像处理中最常见的处理方法,也是很多图像处理方法的基础,如图像灰度统计、图像识别等。
图像的灰度化与二值化方法较多,处理过程也比较简单。但切不可因其简单而忽视效率。如常用的图像灰度计算公式:gray = red * 0.299 + green * 0.587 + blue * 0.114,如果在程序代码中直接套用了这个公式,因浮点数的缘故导致代码执行效率较低,如改为定点整数运算,可使执行效率大大提高。 下面是图像的灰度与二值化代码: // 定义ARGB像素结构 typedef union {
ARGB Color; struct {
BYTE Blue; BYTE Green; BYTE Red; BYTE Alpha; };
}ARGBQuad, *PARGBQuad;
//---------------------------------------------------------------------------
// 图像数据data灰度化 VOID Gray(BitmapData *data)
{
PARGBQuad p = (PARGBQuad)data->Scan0;
INT offset = data->Stride - data->Width * sizeof(ARGBQuad);
for (UINT y = 0; y < data->Height; y ++, (BYTE*)p += offset) {
for (UINT x = 0; x < data->Width; x ++, p ++) p->Blue = p->Green = p->Red =
(UINT)(p->Blue * 29 + p->Green * 150 + p->Red * 77 + 128) >> 8; } }
//---------------------------------------------------------------------------
// 图像数据data灰度同时二值化,threshold阀值
VOID GrayAnd2Values(BitmapData *data, BYTE threshold) {
PARGBQuad p = (PARGBQuad)data->Scan0;
INT offset = data->Stride - data->Width * sizeof(ARGBQuad);
for (UINT y = 0; y < data->Height; y ++, (BYTE*)p += offset) {
for (UINT x = 0; x < data->Width; x ++, p ++) {
if (((p->Blue * 29 + p->Green * 150 + p->Red * 77 + 128) >> 8) < threshold) p->Color &= 0xff000000; else
p->Color |= 0x00ffffff; } } }
//---------------------------------------------------------------------------
因本文使用的是32位图像数据,所以图像的二值化没有采用通常的赋值操作p->Blue = p->Green = p->Red = 0(或者255),而是采用了位运算。
下面是使用BCB2007和GDI+图像数据实现图像灰度和二值化的例子代码: // 锁定GDI+位位图扫描线到data FORCEINLINE
VOID LockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data) {
Gdiplus::Rect r(0, 0, bmp->GetWidth(), bmp->GetHeight()); bmp->LockBits(&r, ImageLockModeRead | ImageLockModeWrite, PixelFormat32bppARGB, data); }
//---------------------------------------------------------------------------
// GDI+位图扫描线解锁 FORCEINLINE
VOID UnlockBitmap(Gdiplus::Bitmap *bmp, BitmapData *data) {
bmp->UnlockBits(data); }
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender) {
Gdiplus::Bitmap *bmp = new Gdiplus::Bitmap(L\ Gdiplus::Graphics *g = new Gdiplus::Graphics(Canvas->Handle); g->DrawImage(bmp, 0, 0); BitmapData data; LockBitmap(bmp, &data); // Gray(&data);
GrayAnd2Values(&data, 128);
UnlockBitmap(bmp, &data); g->DrawImage(bmp, data.Width, 0); delete g; delete bmp; }
//---------------------------------------------------------------------------
24位真彩色转换为8位灰度图片(完整代码)
//Code By xets007 //转载请注明出处 #include
BOOL BMP24to8(char *szSourceFile,char *szTargetFile);
int main(int argc,char* argv[]) {
//调用这个函数直接把24位真彩色灰度化
BOOL stat=BMP24to8(\ return 0; }
BOOL BMP24to8(char *szSourceFile,char *szTargetFile) {
HANDLE hSourceFile=INVALID_HANDLE_VALUE,hTargetFile=INVALID_HANDLE_VALUE; DWORD dwSourceSize=0,dwTargetSize=0; PBYTE pSource=NULL,pTarget=NULL;
hSourceFile=CreateFile(szSourceFile,GENERIC_READ,FILE_SHARE_READ,NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(hSourceFile==INVALID_HANDLE_VALUE) return FALSE;
dwSourceSize=GetFileSize(hSourceFile,NULL);
pSource=(PBYTE)VirtualAlloc(NULL,dwSourceSize,MEM_COMMIT,PAGE_READWRITE); //分配空间失败或者文件太小(BMP文件不可能小于54个字节)
if(pSource==NULL||dwSourceSize<=54) {
CloseHandle(hSourceFile); return FALSE; }
DWORD dwTemp=0;
ReadFile(hSourceFile,pSource,dwSourceSize,&dwTemp,NULL);
BITMAPFILEHEADER *pSourceFileHeader=(BITMAPFILEHEADER*)pSource; BITMAPINFOHEADER
*pSourceInfoHeader=(BITMAPINFOHEADER*)(pSource+sizeof(BITMAPFILEHEADER)); //不是BMP文件或者不是24位真彩色
if(pSourceFileHeader->bfType!=0x4d42||pSourceInfoHeader->biBitCount!=24) {
CloseHandle(hSourceFile);
VirtualFree(pSource,NULL,MEM_RELEASE); return FALSE; }
CloseHandle(hSourceFile);
LONG nWidth=pSourceInfoHeader->biWidth; LONG nHeight=pSourceInfoHeader->biHeight;
LONG nSourceWidth=nWidth*3;if(nSourceWidth%4) nSourceWidth=(nSourceWidth/4+1)*4; LONG nTargetWidth=nWidth;if(nTargetWidth%4) nTargetWidth=(nTargetWidth/4+1)*4;
dwTargetSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256+nHeight*nTargetWidth;
pTarget=(PBYTE)VirtualAlloc(NULL,dwTargetSize,MEM_COMMIT,PAGE_READWRITE); memset(pTarget,0,dwTargetSize); if(pTarget==NULL) {
VirtualFree(pTarget,NULL,MEM_RELEASE); return FALSE; }
BITMAPFILEHEADER *pTargetFileHeader=(BITMAPFILEHEADER *)pTarget; BITMAPINFOHEADER *pTargetInfoHeader =
(BITMAPINFOHEADER *)(pTarget+sizeof(BITMAPFILEHEADER)); pTargetFileHeader->bfType=pSourceFileHeader->bfType; pTargetFileHeader->bfSize=dwTargetSize; pTargetFileHeader->bfReserved1=0; pTargetFileHeader->bfReserved2=0;
pTargetFileHeader->bfOffBits=sizeof(BITMAPFILEHEADER)