请问彩色BMP图像如何转换成黑白的256图像?(求算法) 请问彩色BMP图像如何转换成黑白的256图像?(求算法)现在想吧24位彩色图像转换成黑白的256图像,请问改如何转换?能否保证从彩色到黑白是1对1的关系?情大家给电意见,回答者有分! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 DWORD SrcBufSize,DstBufSize,DstLineBytes; LPBITMAPINFOHEADER lpImgData; LPSTR lpPtr; HLOCAL hTempImgData; LPBITMAPINFOHEADER lpTempImgData; LPSTR lpTempPtr; HDC hDc; HFILE hf; LONG x,y; BITMAPFILEHEADER DstBf; BITMAPINFOHEADER DstBi; LOGPALETTE *pPal; HPALETTE hPrevPalette; HLOCAL hPal; DWORD NewNumColors; WORD NewBitCount; float Y; DWORD i; unsigned char Red,Green,Blue,Gray; NewNumColors=NumColors; NewBitCount=bi.biBitCount; if(NumColors==0) //true color { NewNumColors=256; NewBitCount=8; } DstLineBytes=(DWORD)WIDTHBYTES(bi.biWidth*NewBitCount); DstBufSize=(DWORD)(sizeof(BITMAPINFOHEADER)+NewNumColors*sizeof(RGBQUAD)+(DWORD)DstLineBytes*bi.biHeight); memcpy((char *)&DstBf,(char *)&bf,sizeof(BITMAPFILEHEADER)); memcpy((char *)&DstBi,(char *)&bi,sizeof(BITMAPINFOHEADER)); DstBf.bfSize=DstBufSize+sizeof(BITMAPFILEHEADER); DstBf.bfOffBits=(DWORD)(NewNumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER) +sizeof(BITMAPINFOHEADER)); DstBi.biClrUsed=0; DstBi.biBitCount=NewBitCount; SrcBufSize=bf.bfSize-sizeof(BITMAPFILEHEADER); if((hTempImgData=LocalAlloc(LHND,DstBufSize))==NULL) { MessageBox("Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION); return FALSE; } lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData); lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData); //copy image data memcpy(lpTempImgData,lpImgData,DstBufSize); //overwrite bitmapinfoheader with the new one memcpy(lpTempImgData,(char *)&DstBi,sizeof(BITMAPINFOHEADER)); lpPtr=(char *)lpImgData+sizeof(BITMAPINFOHEADER); lpTempPtr=(char *)lpTempImgData+sizeof(BITMAPINFOHEADER); hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) + NewNumColors* sizeof(PALETTEENTRY)); pPal =(LOGPALETTE *)LocalLock(hPal); pPal->palNumEntries =(WORD) NewNumColors; pPal->palVersion = 0x300; if(NumColors==0) //true color for (i = 0; i < 256; i++) { pPal->palPalEntry[i].peRed=(BYTE)i; pPal->palPalEntry[i].peGreen=(BYTE)i; pPal->palPalEntry[i].peBlue=(BYTE)i; pPal->palPalEntry[i].peFlags=(BYTE)0; *(lpTempPtr++)=(unsigned char)i; *(lpTempPtr++)=(unsigned char)i; *(lpTempPtr++)=(unsigned char)i; *(lpTempPtr++)=0; } else for (i = 0; i < NewNumColors; i++) { Blue=(unsigned char )(*lpPtr++); Green=(unsigned char )(*lpPtr++); Red=(unsigned char )(*lpPtr++); Y=(float)(Red*0.299+Green*0.587+Blue*0.114); Gray=(BYTE)Y; lpPtr++; pPal->palPalEntry[i].peRed=Gray; pPal->palPalEntry[i].peGreen=Gray; pPal->palPalEntry[i].peBlue=Gray; pPal->palPalEntry[i].peFlags=0; *(lpTempPtr++)=(unsigned char)Gray; *(lpTempPtr++)=(unsigned char)Gray; *(lpTempPtr++)=(unsigned char)Gray; *(lpTempPtr++)=0; } if(hPalette!=NULL) DeleteObject(hPalette); hPalette=CreatePalette(pPal); LocalUnlock(hPal); LocalFree(hPal); hDc=::GetDC(m_hWnd); if(hPalette){ hPrevPalette=SelectPalette(hDc,hPalette,FALSE); RealizePalette(hDc); } if(NumColors==0) for(y=0;y<bi.biHeight;y++){ lpPtr=(char *)lpImgData+(SrcBufSize-LineBytes-y*LineBytes); lpTempPtr=(char *)lpTempImgData+(DstBufSize-DstLineBytes-y*DstLineBytes); for(x=0;x<bi.biWidth;x++){ Blue=(unsigned char )(*lpPtr++); Green=(unsigned char )(*lpPtr++); Red=(unsigned char )(*lpPtr++); Y=(float)(Red*0.299+Green*0.587+Blue*0.114); Gray=(BYTE)Y; *(lpTempPtr++)=(unsigned char)Gray; } } if(hBitmap!=NULL) DeleteObject(hBitmap); hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT, (LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +NewNumColors*sizeof(RGBQUAD), (LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS); if(hPalette && hPrevPalette){ SelectPalette(hDc,hPrevPalette,FALSE); RealizePalette(hDc); } hf=_lcreat(BmpFileName,0); _lwrite(hf,(LPSTR)&DstBf,sizeof(BITMAPFILEHEADER)); _lwrite(hf,(LPSTR)lpTempImgData,DstBufSize); _lclose(hf); ::ReleaseDC(m_hWnd,hDc); LocalUnlock(hTempImgData); LocalFree(hTempImgData); GlobalUnlock(hImgData); return TRUE; HFILE hf; LPBITMAPINFOHEADER lpImgData; LOGPALETTE *pPal; LPRGBQUAD lpRGB; HPALETTE hPrevPalette; HDC hDc; HLOCAL hPal; DWORD ImgSize; DWORD i; if((hf=_lopen(BmpFileName,OF_READ))==HFILE_ERROR){ MessageBox("Can not Load file","Error",MB_OK|MB_ICONEXCLAMATION); return FALSE; } _lread(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER)); _lread(hf,(LPSTR)&bi,sizeof(BITMAPINFOHEADER)); ImgWidth=bi.biWidth; ImgHeight=bi.biHeight; LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount); ImgSize=(DWORD)LineBytes*bi.biHeight; if(bi.biClrUsed!=0) NumColors=(DWORD)bi.biClrUsed; else switch(bi.biBitCount){ case 1: NumColors=2; break; case 4: NumColors=16; break; case 8: NumColors=256; break; case 24: NumColors=0; break; default: MessageBox("Invalid color numbers!","Error Message",MB_OK|MB_ICONEXCLAMATION); _lclose(hf); return FALSE; NumColors = 0; break; } if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER) +sizeof(BITMAPINFOHEADER))) { MessageBox("Invalid color numbers!","Error Message" ,MB_OK| MB_ICONEXCLAMATION); _lclose(hf); return FALSE; } bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize; if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+ NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL) { MessageBox("Error alloc memory!","ErrorMessage",MB_OK| MB_ICONEXCLAMATION); _lclose(hf); return FALSE; } lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData); _llseek(hf,sizeof(BITMAPFILEHEADER),FILE_BEGIN); _hread(hf,(char *)lpImgData,(long)sizeof(BITMAPINFOHEADER) +(long)NumColors*sizeof(RGBQUAD)+ImgSize); _lclose(hf); if(NumColors!=0) { hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) + NumColors* sizeof(PALETTEENTRY)); pPal =(LOGPALETTE *)LocalLock(hPal); pPal->palNumEntries =(WORD) NumColors; pPal->palVersion = 0x300; lpRGB = (LPRGBQUAD)((LPSTR)lpImgData + (DWORD)sizeof(BITMAPINFOHEADER)); for (i = 0; i < NumColors; i++) { pPal->palPalEntry[i].peRed=lpRGB->rgbRed; pPal->palPalEntry[i].peGreen=lpRGB->rgbGreen; pPal->palPalEntry[i].peBlue=lpRGB->rgbBlue; pPal->palPalEntry[i].peFlags=(BYTE)0; lpRGB++; } hPalette=CreatePalette(pPal); LocalUnlock(hPal); LocalFree(hPal); } hDc=::GetDC(m_hWnd); if(hPalette){ hPrevPalette=SelectPalette(hDc,hPalette,FALSE); RealizePalette(hDc); } hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpImgData, (LONG)CBM_INIT, (LPSTR)lpImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD), (LPBITMAPINFO)lpImgData, DIB_RGB_COLORS); if(hPalette && hPrevPalette){ SelectPalette(hDc,hPrevPalette,FALSE); RealizePalette(hDc); } ::ReleaseDC(m_hWnd,hDc); GlobalUnlock(hImgData); 黑白?那不就成二值图了,用8位色太浪费空间了吧~~~或许你想说的是灰度?灰度化的实质就是把RGB三个通道的值都取亮度不过亮度的取值又和设备的色彩空间标准有关,一般用的比较多的是近似的NTSC亮度计算公式Y=0.3*Red+0.59*Green+0.11*Blue又可以近似的用下面的代码计算Gray=(77*Red+151*Green+28*Blue)>>8;第二个问题嘛,留给你自己思考,似乎很容易得到答案 //仅对8位,24位图像进行灰度处理,将灰度图存为 8 位,并赋值处理数组。void CDib::Gray(){ long linebits = WIDTHBYTES(8*m_nWidth); //分配处理数组内存 if(!m_pDataS) { m_pDataS = new double[linebits*m_nHeight]; } unsigned char bitCount=GetBitCount(); // 灰度映射表 unsigned char bMap[256]; if(bitCount==8) { for(int i=0;i<256;i++) { bMap[i]=(unsigned char)(0.299*m_pRGBQuad[i].rgbRed+ 0.587*m_pRGBQuad[i].rgbGreen+ 0.114*m_pRGBQuad[i].rgbBlue+0.5); m_pRGBQuad[i].rgbRed=i; m_pRGBQuad[i].rgbGreen=i; m_pRGBQuad[i].rgbBlue=i; m_pRGBQuad[i].rgbReserved=0; } // 更换每个象素的颜色索引(即按照灰度映射表换成灰度值) long lw=WIDTHBYTES(m_nWidth*8); for(long j=0l;j<m_nHeight;j++) { for(long i=0l;i<m_nWidth;i++) { long jj=j*lw+i; m_pDibData[jj]=bMap[m_pDibData[jj]]; m_pDataS[j*m_nWidth+i]=(double)bMap[m_pDibData[jj]]; } } } else if(bitCount==24) { //计算相应的 8 位图大小 unsigned long dwFileSize = sizeof(BITMAPFILEHEADER) + m_pBitmapInfoHeader->biSize + 256 * sizeof(RGBQUAD) + WIDTHBYTES(m_nWidth*8) * m_nHeight; //写 BITMAPFILEHEADER BITMAPFILEHEADER bfh; memcpy(&bfh,m_pBitmapFileHeader,sizeof(BITMAPFILEHEADER)); bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + m_pBitmapInfoHeader->biSize + 256 * sizeof(RGBQUAD); bfh.bfSize = dwFileSize; m_fileLeng = dwFileSize; //写 BITMAPINFOHEADER BITMAPINFOHEADER bih; memcpy(&bih,m_pBitmapInfoHeader,m_pBitmapInfoHeader->biSize); bih.biBitCount = 8; bih.biSizeImage = (unsigned long)WIDTHBYTES(m_nWidth*8) * (unsigned long)m_nHeight; bih.biClrUsed = 256; //写 RGBQUAD RGBQUAD rgbq[256]; for(int i=0;i<256;i++) { rgbq[i].rgbRed=i; rgbq[i].rgbGreen=i; rgbq[i].rgbBlue=i; rgbq[i].rgbReserved=0; } //写位图数据 unsigned char* pData = new unsigned char[bih.biSizeImage]; long lw=WIDTHBYTES(m_nWidth*24); for(long j=0l;j<m_nHeight;j++) { for(long i=0l;i<m_nWidth;i++) { long jj=j*lw; long ii=3*i; unsigned char gray = (unsigned char)(0.299*(m_pDibData[jj+ii])+ 0.587*(m_pDibData[jj+ii+1])+0.114*(m_pDibData[jj+ii+2])+0.5); pData[j*linebits+i] = gray; m_pDataS[j*linebits+i] = gray; } } //重新申请内存文件 m_pFileData = m_memFile.Detach(); ASSERT(m_pFileData = (BYTE *) realloc((void * )m_pFileData,dwFileSize)); m_memFile.Attach(m_pFileData,dwFileSize, GROWBYTES); m_memFile.Seek(0l,CFile::begin); m_memFile.Write(&bfh,sizeof(BITMAPFILEHEADER)); m_memFile.Write(&bih,sizeof(BITMAPINFOHEADER)); m_memFile.Write(rgbq,256 * sizeof(RGBQUAD)); m_memFile.Write(pData,bih.biSizeImage); SetPara(); delete[] pData; }}理论如楼上所说,,需要代码的话给我留言! 变成灰阶一般是0.3*r+0.59*g+0.11*b也可以直接(r+g+b)/3 这是我参考一个网上朋友的,运行没错,但是保存成文件时,文件位空,大家能否帮我看看那儿的错误啊?HDIB MakeGrayFile(HDIB pColorBmp,long nDisplayHeight,long nDisplayWidth){ //将RGB模式的位图转换为256色灰度位图 long BmpLength = WIDTHBYTES(8*nDisplayWidth)*nDisplayHeight + sizeof(RGBQUAD)*256;// + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); HDIB hGrayDIB = (HDIB)::GlobalAlloc(GHND,BmpLength+sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); LPSTR pGrayDIB = (LPSTR)GlobalLock((HGLOBAL)hGrayDIB); LPSTR pColorDIB = (LPSTR)GlobalLock((HGLOBAL)pColorBmp); char *pgray = new char[BmpLength]; LPSTR read = ::FindDIBBits(pColorDIB);//(char*)pColorBmp + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) ; char *write = pgray; //构造调色板信息 for(int i=0;i<256;i++) { *(write+i*4) = i; *(write+i*4+1) = i; *(write+i*4+2) = i; *(write+i*4+3) = 0; } write += sizeof(RGBQUAD)*256; //指针条到象素数据区 int r,g,b; float Y; BYTE gray; for(int h=0;h<nDisplayHeight;h++) { for(int w=0;w<nDisplayWidth;w++) { g = (unsigned char)*read++; b = (unsigned char)*read++; r = (unsigned char)*read++; //提取灰度分量 Y=(float)(r*0.299+g*0.587+b*0.114); gray = (BYTE)Y; *write = gray; write++; } } //拷贝新的灰度位图调色板信息和像素数据 //设置位图文件头 BITMAPFILEHEADER bmfHdr; bmfHdr.bfType = DIB_HEADER_MARKER;//0x4D41;//2; // "BM" //BmpLength = bmfHdr.bfSize = nDisplayWidth*nDisplayHeight + sizeof(RGBQUAD)*256 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); bmfHdr.bfSize = (DWORD)WIDTHBYTES(8*nDisplayWidth)*nDisplayHeight + (DWORD)(sizeof(RGBQUAD)*256) + (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256; //拷贝位图文件头 memcpy(pGrayDIB, &bmfHdr, sizeof(BITMAPFILEHEADER)); //设置位图信息头 BITMAPINFOHEADER bi; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = nDisplayWidth; bi.biHeight = nDisplayHeight; bi.biPlanes = 1; bi.biBitCount = 8; bi.biCompression = BI_RGB; bi.biSizeImage = WIDTHBYTES(8*nDisplayWidth)*nDisplayHeight; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; memcpy(pGrayDIB + sizeof(BITMAPFILEHEADER), &bi, sizeof(BITMAPINFOHEADER)); //拷贝新的灰度位图调色板信息和像素数据 memcpy(pGrayDIB + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER), pgray, BmpLength); //释放分配的临时空间 delete pgray; GlobalUnlock((HGLOBAL)hGrayDIB); return hGrayDIB;} 就这样简单CImage img;img.Load("c:\\test.bmp");for(int x=0;x<image.GetWidth();x++){ for(int y=0;y<img.GetHeight();y++) { c=img.GetPixel(x,y); r=GetRValue(c); g=GetRValue(c); b=GetRValue(c); newcolor=(r+g+b)/3>128?255:0; img.SetPixel(x,y,RGB(newcolor,newcolor,newcolor)); }}img.Save("c:\\test1.jpg")图象已经成为黑白的了!注意包含头文件:"atlimage.h" you can see freeimage.dll 孙鑫VC第一课菜鸟问题 如何给UDP包加上序号 分用光了,好心人回答,如何录系统当前播放的声音,谢谢! 谁给我个视频的例子? 关于重绘控件? DEBUG 版可以通过 ,RELEASE 不可以,请高手支招 如何让程序执行的时候自动打开一个对话筐,运算结束时自动关闭? dwg控件 有关指针 文件共享 NetTalk视频聊天源码共享[VC++] 怎样判断光驱是不是物理光驱?
LPBITMAPINFOHEADER lpImgData;
LPSTR lpPtr;
HLOCAL hTempImgData;
LPBITMAPINFOHEADER lpTempImgData;
LPSTR lpTempPtr;
HDC hDc;
HFILE hf;
LONG x,y;
BITMAPFILEHEADER DstBf;
BITMAPINFOHEADER DstBi;
LOGPALETTE *pPal;
HPALETTE hPrevPalette;
HLOCAL hPal;
DWORD NewNumColors;
WORD NewBitCount;
float Y;
DWORD i;
unsigned char Red,Green,Blue,Gray; NewNumColors=NumColors;
NewBitCount=bi.biBitCount;
if(NumColors==0) //true color
{
NewNumColors=256;
NewBitCount=8;
} DstLineBytes=(DWORD)WIDTHBYTES(bi.biWidth*NewBitCount);
DstBufSize=(DWORD)(sizeof(BITMAPINFOHEADER)+NewNumColors*sizeof(RGBQUAD)+(DWORD)DstLineBytes*bi.biHeight);
memcpy((char *)&DstBf,(char *)&bf,sizeof(BITMAPFILEHEADER));
memcpy((char *)&DstBi,(char *)&bi,sizeof(BITMAPINFOHEADER));
DstBf.bfSize=DstBufSize+sizeof(BITMAPFILEHEADER);
DstBf.bfOffBits=(DWORD)(NewNumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)
+sizeof(BITMAPINFOHEADER));
DstBi.biClrUsed=0;
DstBi.biBitCount=NewBitCount; SrcBufSize=bf.bfSize-sizeof(BITMAPFILEHEADER); if((hTempImgData=LocalAlloc(LHND,DstBufSize))==NULL)
{
MessageBox("Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
} lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData); //copy image data
memcpy(lpTempImgData,lpImgData,DstBufSize);
//overwrite bitmapinfoheader with the new one
memcpy(lpTempImgData,(char *)&DstBi,sizeof(BITMAPINFOHEADER)); lpPtr=(char *)lpImgData+sizeof(BITMAPINFOHEADER);
lpTempPtr=(char *)lpTempImgData+sizeof(BITMAPINFOHEADER); hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) + NewNumColors* sizeof(PALETTEENTRY));
pPal =(LOGPALETTE *)LocalLock(hPal);
pPal->palNumEntries =(WORD) NewNumColors;
pPal->palVersion = 0x300; if(NumColors==0) //true color
for (i = 0; i < 256; i++) {
pPal->palPalEntry[i].peRed=(BYTE)i;
pPal->palPalEntry[i].peGreen=(BYTE)i;
pPal->palPalEntry[i].peBlue=(BYTE)i;
pPal->palPalEntry[i].peFlags=(BYTE)0;
*(lpTempPtr++)=(unsigned char)i;
*(lpTempPtr++)=(unsigned char)i;
*(lpTempPtr++)=(unsigned char)i;
*(lpTempPtr++)=0;
}
else
for (i = 0; i < NewNumColors; i++) {
Blue=(unsigned char )(*lpPtr++);
Green=(unsigned char )(*lpPtr++);
Red=(unsigned char )(*lpPtr++);
Y=(float)(Red*0.299+Green*0.587+Blue*0.114);
Gray=(BYTE)Y;
lpPtr++;
pPal->palPalEntry[i].peRed=Gray;
pPal->palPalEntry[i].peGreen=Gray;
pPal->palPalEntry[i].peBlue=Gray;
pPal->palPalEntry[i].peFlags=0;
*(lpTempPtr++)=(unsigned char)Gray;
*(lpTempPtr++)=(unsigned char)Gray;
*(lpTempPtr++)=(unsigned char)Gray;
*(lpTempPtr++)=0;
} if(hPalette!=NULL)
DeleteObject(hPalette);
hPalette=CreatePalette(pPal);
LocalUnlock(hPal);
LocalFree(hPal); hDc=::GetDC(m_hWnd);
if(hPalette){
hPrevPalette=SelectPalette(hDc,hPalette,FALSE);
RealizePalette(hDc);
}
if(NumColors==0)
for(y=0;y<bi.biHeight;y++){
lpPtr=(char *)lpImgData+(SrcBufSize-LineBytes-y*LineBytes);
lpTempPtr=(char *)lpTempImgData+(DstBufSize-DstLineBytes-y*DstLineBytes);
for(x=0;x<bi.biWidth;x++){
Blue=(unsigned char )(*lpPtr++);
Green=(unsigned char )(*lpPtr++);
Red=(unsigned char )(*lpPtr++);
Y=(float)(Red*0.299+Green*0.587+Blue*0.114);
Gray=(BYTE)Y;
*(lpTempPtr++)=(unsigned char)Gray;
}
} if(hBitmap!=NULL)
DeleteObject(hBitmap);
hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT,
(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +NewNumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS); if(hPalette && hPrevPalette){
SelectPalette(hDc,hPrevPalette,FALSE);
RealizePalette(hDc);
} hf=_lcreat(BmpFileName,0);
_lwrite(hf,(LPSTR)&DstBf,sizeof(BITMAPFILEHEADER));
_lwrite(hf,(LPSTR)lpTempImgData,DstBufSize);
_lclose(hf); ::ReleaseDC(m_hWnd,hDc);
LocalUnlock(hTempImgData);
LocalFree(hTempImgData);
GlobalUnlock(hImgData);
return TRUE;
LPBITMAPINFOHEADER lpImgData;
LOGPALETTE *pPal;
LPRGBQUAD lpRGB;
HPALETTE hPrevPalette;
HDC hDc;
HLOCAL hPal;
DWORD ImgSize;
DWORD i;
if((hf=_lopen(BmpFileName,OF_READ))==HFILE_ERROR){
MessageBox("Can not Load file","Error",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
_lread(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));
_lread(hf,(LPSTR)&bi,sizeof(BITMAPINFOHEADER));
ImgWidth=bi.biWidth;
ImgHeight=bi.biHeight;
LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount);
ImgSize=(DWORD)LineBytes*bi.biHeight;
if(bi.biClrUsed!=0)
NumColors=(DWORD)bi.biClrUsed;
else
switch(bi.biBitCount){
case 1:
NumColors=2;
break;
case 4:
NumColors=16;
break;
case 8:
NumColors=256;
break;
case 24:
NumColors=0;
break;
default:
MessageBox("Invalid color numbers!","Error Message",MB_OK|MB_ICONEXCLAMATION);
_lclose(hf);
return FALSE;
NumColors = 0;
break;
}
if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)
+sizeof(BITMAPINFOHEADER)))
{
MessageBox("Invalid color numbers!","Error Message" ,MB_OK|
MB_ICONEXCLAMATION);
_lclose(hf);
return FALSE;
}
bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize;
if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+
NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL)
{
MessageBox("Error alloc memory!","ErrorMessage",MB_OK|
MB_ICONEXCLAMATION);
_lclose(hf);
return FALSE;
}
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
_llseek(hf,sizeof(BITMAPFILEHEADER),FILE_BEGIN);
_hread(hf,(char *)lpImgData,(long)sizeof(BITMAPINFOHEADER)
+(long)NumColors*sizeof(RGBQUAD)+ImgSize);
_lclose(hf);
if(NumColors!=0)
{
hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) + NumColors* sizeof(PALETTEENTRY));
pPal =(LOGPALETTE *)LocalLock(hPal);
pPal->palNumEntries =(WORD) NumColors;
pPal->palVersion = 0x300;
lpRGB = (LPRGBQUAD)((LPSTR)lpImgData + (DWORD)sizeof(BITMAPINFOHEADER));
for (i = 0; i < NumColors; i++) {
pPal->palPalEntry[i].peRed=lpRGB->rgbRed;
pPal->palPalEntry[i].peGreen=lpRGB->rgbGreen;
pPal->palPalEntry[i].peBlue=lpRGB->rgbBlue;
pPal->palPalEntry[i].peFlags=(BYTE)0;
lpRGB++;
}
hPalette=CreatePalette(pPal);
LocalUnlock(hPal);
LocalFree(hPal);
}
hDc=::GetDC(m_hWnd);
if(hPalette){
hPrevPalette=SelectPalette(hDc,hPalette,FALSE);
RealizePalette(hDc);
}
hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpImgData, (LONG)CBM_INIT,
(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);
if(hPalette && hPrevPalette){
SelectPalette(hDc,hPrevPalette,FALSE);
RealizePalette(hDc);
}
::ReleaseDC(m_hWnd,hDc);
GlobalUnlock(hImgData);
void CDib::Gray()
{
long linebits = WIDTHBYTES(8*m_nWidth);
//分配处理数组内存
if(!m_pDataS)
{
m_pDataS = new double[linebits*m_nHeight];
} unsigned char bitCount=GetBitCount();
// 灰度映射表
unsigned char bMap[256];
if(bitCount==8)
{
for(int i=0;i<256;i++)
{
bMap[i]=(unsigned char)(0.299*m_pRGBQuad[i].rgbRed+
0.587*m_pRGBQuad[i].rgbGreen+
0.114*m_pRGBQuad[i].rgbBlue+0.5);
m_pRGBQuad[i].rgbRed=i;
m_pRGBQuad[i].rgbGreen=i;
m_pRGBQuad[i].rgbBlue=i;
m_pRGBQuad[i].rgbReserved=0;
}
// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值)
long lw=WIDTHBYTES(m_nWidth*8);
for(long j=0l;j<m_nHeight;j++)
{
for(long i=0l;i<m_nWidth;i++)
{
long jj=j*lw+i;
m_pDibData[jj]=bMap[m_pDibData[jj]];
m_pDataS[j*m_nWidth+i]=(double)bMap[m_pDibData[jj]];
}
}
}
else if(bitCount==24)
{
//计算相应的 8 位图大小
unsigned long dwFileSize = sizeof(BITMAPFILEHEADER) + m_pBitmapInfoHeader->biSize
+ 256 * sizeof(RGBQUAD) + WIDTHBYTES(m_nWidth*8) * m_nHeight;
//写 BITMAPFILEHEADER
BITMAPFILEHEADER bfh;
memcpy(&bfh,m_pBitmapFileHeader,sizeof(BITMAPFILEHEADER));
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + m_pBitmapInfoHeader->biSize
+ 256 * sizeof(RGBQUAD);
bfh.bfSize = dwFileSize;
m_fileLeng = dwFileSize;
//写 BITMAPINFOHEADER
BITMAPINFOHEADER bih;
memcpy(&bih,m_pBitmapInfoHeader,m_pBitmapInfoHeader->biSize);
bih.biBitCount = 8;
bih.biSizeImage = (unsigned long)WIDTHBYTES(m_nWidth*8) * (unsigned long)m_nHeight;
bih.biClrUsed = 256;
//写 RGBQUAD
RGBQUAD rgbq[256];
for(int i=0;i<256;i++)
{
rgbq[i].rgbRed=i;
rgbq[i].rgbGreen=i;
rgbq[i].rgbBlue=i;
rgbq[i].rgbReserved=0;
} //写位图数据
unsigned char* pData = new unsigned char[bih.biSizeImage];
long lw=WIDTHBYTES(m_nWidth*24);
for(long j=0l;j<m_nHeight;j++)
{
for(long i=0l;i<m_nWidth;i++)
{
long jj=j*lw;
long ii=3*i;
unsigned char gray = (unsigned char)(0.299*(m_pDibData[jj+ii])+
0.587*(m_pDibData[jj+ii+1])+0.114*(m_pDibData[jj+ii+2])+0.5);
pData[j*linebits+i] = gray;
m_pDataS[j*linebits+i] = gray;
}
}
//重新申请内存文件
m_pFileData = m_memFile.Detach();
ASSERT(m_pFileData = (BYTE *) realloc((void * )m_pFileData,dwFileSize));
m_memFile.Attach(m_pFileData,dwFileSize, GROWBYTES);
m_memFile.Seek(0l,CFile::begin);
m_memFile.Write(&bfh,sizeof(BITMAPFILEHEADER));
m_memFile.Write(&bih,sizeof(BITMAPINFOHEADER));
m_memFile.Write(rgbq,256 * sizeof(RGBQUAD));
m_memFile.Write(pData,bih.biSizeImage); SetPara();
delete[] pData;
}
}理论如楼上所说,,需要代码的话给我留言!
也可以直接(r+g+b)/3
HDIB MakeGrayFile(HDIB pColorBmp,long nDisplayHeight,long nDisplayWidth)
{
//将RGB模式的位图转换为256色灰度位图
long BmpLength = WIDTHBYTES(8*nDisplayWidth)*nDisplayHeight + sizeof(RGBQUAD)*256;// + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
HDIB hGrayDIB = (HDIB)::GlobalAlloc(GHND,BmpLength+sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
LPSTR pGrayDIB = (LPSTR)GlobalLock((HGLOBAL)hGrayDIB);
LPSTR pColorDIB = (LPSTR)GlobalLock((HGLOBAL)pColorBmp); char *pgray = new char[BmpLength];
LPSTR read = ::FindDIBBits(pColorDIB);//(char*)pColorBmp + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) ;
char *write = pgray; //构造调色板信息
for(int i=0;i<256;i++)
{
*(write+i*4) = i;
*(write+i*4+1) = i;
*(write+i*4+2) = i;
*(write+i*4+3) = 0;
}
write += sizeof(RGBQUAD)*256; //指针条到象素数据区 int r,g,b;
float Y;
BYTE gray;
for(int h=0;h<nDisplayHeight;h++)
{
for(int w=0;w<nDisplayWidth;w++)
{
g = (unsigned char)*read++;
b = (unsigned char)*read++;
r = (unsigned char)*read++;
//提取灰度分量
Y=(float)(r*0.299+g*0.587+b*0.114);
gray = (BYTE)Y;
*write = gray;
write++;
}
} //拷贝新的灰度位图调色板信息和像素数据
//设置位图文件头
BITMAPFILEHEADER bmfHdr;
bmfHdr.bfType = DIB_HEADER_MARKER;//0x4D41;//2; // "BM"
//BmpLength = bmfHdr.bfSize = nDisplayWidth*nDisplayHeight + sizeof(RGBQUAD)*256 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmfHdr.bfSize = (DWORD)WIDTHBYTES(8*nDisplayWidth)*nDisplayHeight + (DWORD)(sizeof(RGBQUAD)*256) + (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)
+ (DWORD)sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256;
//拷贝位图文件头
memcpy(pGrayDIB, &bmfHdr, sizeof(BITMAPFILEHEADER)); //设置位图信息头
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = nDisplayWidth;
bi.biHeight = nDisplayHeight;
bi.biPlanes = 1;
bi.biBitCount = 8;
bi.biCompression = BI_RGB;
bi.biSizeImage = WIDTHBYTES(8*nDisplayWidth)*nDisplayHeight;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
memcpy(pGrayDIB + sizeof(BITMAPFILEHEADER), &bi, sizeof(BITMAPINFOHEADER)); //拷贝新的灰度位图调色板信息和像素数据
memcpy(pGrayDIB + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER),
pgray, BmpLength);
//释放分配的临时空间
delete pgray;
GlobalUnlock((HGLOBAL)hGrayDIB);
return hGrayDIB;
}
CImage img;
img.Load("c:\\test.bmp");
for(int x=0;x<image.GetWidth();x++)
{
for(int y=0;y<img.GetHeight();y++)
{
c=img.GetPixel(x,y);
r=GetRValue(c);
g=GetRValue(c);
b=GetRValue(c);
newcolor=(r+g+b)/3>128?255:0;
img.SetPixel(x,y,RGB(newcolor,newcolor,newcolor));
}
}
img.Save("c:\\test1.jpg")
图象已经成为黑白的了!
注意包含头文件:"atlimage.h"