如何让任何bmp文件转化为24位的bmp?? 如何让任何bmp文件转化为24位的bmp??希望可以给出具体代码! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 你的意思是把32位,16位,8位,4位,2位bmp图像转为24位吗? 我认为无非就是将位图数据变为3个字节表示一个像素,然后修改信息头和文件头。(不用调色板)8位的最简单了,把原位图数据的每个字节扩成3个即可。4位,2位类似,先逐个取出原位图数据,再扩成3个字节即可。16位彩色图像的数据好像是5位,6位,5位,把它们分别扩成8位即可。至于32位的,我就不大清楚了。 以上只是本人的一些想法,仅供参考。我也没有具体实现过。 ////////////////////////////////////////////////////////////////////////////////bool CxImage::DecreaseBpp(DWORD nbit, bool errordiffusion, RGBQUAD* ppal){ if (!pDib) return false; if (head.biBitCount < nbit) return false; if (head.biBitCount == nbit) return true; long er,eg,eb; RGBQUAD c,ce; CxImage tmp; tmp.CopyInfo(*this); tmp.Create(head.biWidth,head.biHeight,(WORD)nbit,info.dwType);#if CXIMAGE_SUPPORT_SELECTION tmp.SelectionCopy(*this);#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA tmp.AlphaCopy(*this);#endif //CXIMAGE_SUPPORT_ALPHA switch (tmp.head.biBitCount){ case 1: if (ppal) tmp.SetPalette(ppal,16); else { tmp.SetPaletteColor(0,0,0,0); tmp.SetPaletteColor(1,255,255,255); } break; case 4: if (ppal) tmp.SetPalette(ppal,16); else tmp.SetStdPalette(); break; case 8: if (ppal) tmp.SetPalette(ppal); else tmp.SetStdPalette(); break; default: return false; } for (long y=0;y<head.biHeight;y++){ if (info.nEscape) break; info.nProgress = (long)(100*y/head.biHeight); for (long x=0;x<head.biWidth;x++){ if (!errordiffusion){ tmp.SetPixelColor(x,y,GetPixelColor(x,y)); } else { c=GetPixelColor(x,y); tmp.SetPixelColor(x,y,c); ce=tmp.GetPixelColor(x,y); er=(long)c.rgbRed - (long)ce.rgbRed; eg=(long)c.rgbGreen - (long)ce.rgbGreen; eb=(long)c.rgbBlue - (long)ce.rgbBlue; c = GetPixelColor(x+1,y); c.rgbRed = (BYTE)min(255L,max(0L,(long)c.rgbRed + ((er*7)/16))); c.rgbGreen = (BYTE)min(255L,max(0L,(long)c.rgbGreen + ((eg*7)/16))); c.rgbBlue = (BYTE)min(255L,max(0L,(long)c.rgbBlue + ((eb*7)/16))); SetPixelColor(x+1,y,c); int coeff; for(int i=-1; i<2; i++){ switch(i){ case -1: coeff=2; break; case 0: coeff=4; break; case 1: coeff=1; break; } c = GetPixelColor(x+i,y+1); c.rgbRed = (BYTE)min(255L,max(0L,(long)c.rgbRed + ((er * coeff)/16))); c.rgbGreen = (BYTE)min(255L,max(0L,(long)c.rgbGreen + ((eg * coeff)/16))); c.rgbBlue = (BYTE)min(255L,max(0L,(long)c.rgbBlue + ((eb * coeff)/16))); SetPixelColor(x+i,y+1,c); } } } } if (head.biBitCount==1){ tmp.SetPaletteColor(0,0,0,0); tmp.SetPaletteColor(1,255,255,255); } Transfer(tmp); return true;} ////////////////////////////////////////////////////////////////////////////////bool CxImage::IncreaseBpp(DWORD nbit){ if (!pDib) return false; switch (nbit){ case 4: { if (head.biBitCount==4) return true; if (head.biBitCount>4) return false; CxImage tmp; tmp.CopyInfo(*this); tmp.Create(head.biWidth,head.biHeight,4,info.dwType); tmp.SetPalette(GetPalette(),GetNumColors());#if CXIMAGE_SUPPORT_SELECTION tmp.SelectionCopy(*this);#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA tmp.AlphaCopy(*this);#endif //CXIMAGE_SUPPORT_ALPHA for (long y=0;y<head.biHeight;y++){ if (info.nEscape) break; for (long x=0;x<head.biWidth;x++){ tmp.SetPixelIndex(x,y,GetPixelIndex(x,y)); } } Transfer(tmp); return true; } case 8: { if (head.biBitCount==8) return true; if (head.biBitCount>8) return false; CxImage tmp; tmp.CopyInfo(*this); tmp.Create(head.biWidth,head.biHeight,8,info.dwType); tmp.SetPalette(GetPalette(),GetNumColors());#if CXIMAGE_SUPPORT_SELECTION tmp.SelectionCopy(*this);#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA tmp.AlphaCopy(*this);#endif //CXIMAGE_SUPPORT_ALPHA for (long y=0;y<head.biHeight;y++){ if (info.nEscape) break; for (long x=0;x<head.biWidth;x++){ tmp.SetPixelIndex(x,y,GetPixelIndex(x,y)); } } Transfer(tmp); return true; } case 24: { if (head.biBitCount==24) return true; if (head.biBitCount>24) return false; CxImage tmp; tmp.CopyInfo(*this); tmp.Create(head.biWidth,head.biHeight,24,info.dwType);#if CXIMAGE_SUPPORT_SELECTION tmp.SelectionCopy(*this);#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA tmp.AlphaCopy(*this); if (AlphaPaletteIsValid() && !AlphaIsValid()) tmp.AlphaCreate();#endif //CXIMAGE_SUPPORT_ALPHA for (long y=0;y<head.biHeight;y++){ if (info.nEscape) break; for (long x=0;x<head.biWidth;x++){ tmp.SetPixelColor(x,y,GetPixelColor(x,y),true); } } Transfer(tmp); return true; } } return false;}////////////////////////////////////////////////////////////////////////////////bool CxImage::Dither(long method){ if (!pDib) return false; if (head.biBitCount == 1) return true; switch (method){ case 1: { // Multi-Level Ordered-Dithering by Kenny Hoff (Oct. 12, 1995) #define NumRows 4 #define NumCols 4 #define NumIntensityLevels 2 #define NumRowsLessOne (NumRows-1) #define NumColsLessOne (NumCols-1) #define RowsXCols (NumRows*NumCols) #define MaxIntensityVal 255 #define MaxDitherIntensityVal (NumRows*NumCols*(NumIntensityLevels-1)) int DitherMatrix[NumRows][NumCols] = {{0,8,2,10}, {12,4,14,6}, {3,11,1,9}, {15,7,13,5} }; unsigned char Intensity[NumIntensityLevels] = { 0,1 }; // 2 LEVELS B/W //unsigned char Intensity[NumIntensityLevels] = { 0,255 }; // 2 LEVELS //unsigned char Intensity[NumIntensityLevels] = { 0,127,255 }; // 3 LEVELS //unsigned char Intensity[NumIntensityLevels] = { 0,85,170,255 }; // 4 LEVELS //unsigned char Intensity[NumIntensityLevels] = { 0,63,127,191,255 }; // 5 LEVELS //unsigned char Intensity[NumIntensityLevels] = { 0,51,102,153,204,255 }; // 6 LEVELS //unsigned char Intensity[NumIntensityLevels] = { 0,42,85,127,170,213,255 }; // 7 LEVELS //unsigned char Intensity[NumIntensityLevels] = { 0,36,73,109,145,182,219,255 }; // 8 LEVELS int DitherIntensity, DitherMatrixIntensity, Offset, DeviceIntensity; unsigned char DitherValue; GrayScale(); CxImage tmp(head.biWidth,head.biHeight,1,info.dwType);#if CXIMAGE_SUPPORT_SELECTION tmp.SelectionCopy(*this);#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA tmp.AlphaCopy(*this);#endif //CXIMAGE_SUPPORT_ALPHA for (long y=0;y<head.biHeight;y++){ info.nProgress = (long)(100*y/head.biHeight); if (info.nEscape) break; for (long x=0;x<head.biWidth;x++){ DeviceIntensity = GetPixelIndex(x,y); DitherIntensity = DeviceIntensity*MaxDitherIntensityVal/MaxIntensityVal; DitherMatrixIntensity = DitherIntensity % RowsXCols; Offset = DitherIntensity / RowsXCols; if (DitherMatrix[y&NumRowsLessOne][x&NumColsLessOne] < DitherMatrixIntensity) DitherValue = Intensity[1+Offset]; else DitherValue = Intensity[0+Offset]; tmp.SetPixelIndex(x,y,DitherValue); } } tmp.SetPaletteColor(0,0,0,0); tmp.SetPaletteColor(1,255,255,255); Transfer(tmp); break; } default: { // Floyd-Steinberg error diffusion (Thanks to Steve McMahon) long error,nlevel,coeff; BYTE level; GrayScale(); CxImage tmp(head.biWidth,head.biHeight,1,info.dwType);#if CXIMAGE_SUPPORT_SELECTION tmp.SelectionCopy(*this);#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA tmp.AlphaCopy(*this);#endif //CXIMAGE_SUPPORT_ALPHA for (long y=0;y<head.biHeight;y++){ info.nProgress = (long)(100*y/head.biHeight); if (info.nEscape) break; for (long x=0;x<head.biWidth;x++){ level=GetPixelIndex(x,y); if (level > 128){ tmp.SetPixelIndex(x,y,1); error = level-255; } else { tmp.SetPixelIndex(x,y,0); error = level; } nlevel = GetPixelIndex(x+1,y) + (error * 7)/16; level = (BYTE)min(255,max(0,(int)nlevel)); SetPixelIndex(x+1,y,level); for(int i=-1; i<2; i++){ switch(i){ case -1: coeff=3; break; case 0: coeff=5; break; case 1: coeff=1; break; } nlevel = GetPixelIndex(x+i,y+1) + (error * coeff)/16; level = (BYTE)min(255,max(0,(int)nlevel)); SetPixelIndex(x+i,y+1,level); } } } tmp.SetPaletteColor(0,0,0,0); tmp.SetPaletteColor(1,255,255,255); Transfer(tmp); } } return true;}////////////////////////////////////////////////////////////////////////////////这是从CXImage中找出来的,就是实现不同位深之间的转换。自己整理一下。 24位位图是最简单的bmp格式了,你通过LoadImage可以把任何bmp读如HBITMAP,然后就是把HBITMAP存成24位位图 CBitmap bitmap; HANDLE h=::LoadImage(0,"f:\\abc.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); bitmap.Attach(h); CFile file("F:\\abc1.bmp",CFile::modeCreate|CFile::modeWrite); BITMAP size; bitmap.GetBitmap(&size); int iHeight=size.bmHeight; int iWidth=size.bmWidth; int WIDTHBYTES; unsigned char * pBitBuf=NULL; WIDTHBYTES=(iWidth*3+3)/4*4; pBitBuf=(unsigned char *)malloc(WIDTHBYTES*iHeight); BITMAPFILEHEADER BitFileHead; BITMAPINFOHEADER BitInfoHead; BitInfoHead.biHeight=iHeight; BitInfoHead.biWidth=iWidth; BitInfoHead.biSizeImage=WIDTHBYTES*iHeight; BitInfoHead.biSize = sizeof(BITMAPINFOHEADER); BitInfoHead.biPlanes = 1; BitInfoHead.biBitCount = 24; BitInfoHead.biCompression = BI_RGB; BitInfoHead.biXPelsPerMeter = 2952; // 75 DPI BitInfoHead.biYPelsPerMeter = 2952; // 75 DPI BitInfoHead.biClrUsed = 0; BitInfoHead.biClrImportant = 0; BitFileHead.bfType = 'MB'; // Non-portable... sigh BitFileHead.bfSize = BitInfoHead.biSizeImage+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); BitFileHead.bfReserved1 = 0; BitFileHead.bfReserved2 = 0; BitFileHead.bfOffBits =sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); BITMAPINFO mapinfo; mapinfo.bmiHeader=BitInfoHead;// mapinfo.bmiColors HDC hdc = CreateIC (TEXT("DISPLAY"), NULL, NULL, NULL) ; ::GetDIBits (hdc, (HBITMAP)h,0, iHeight, pBitBuf, &mapinfo, DIB_RGB_COLORS) ; file.Write(&BitFileHead,sizeof(BITMAPFILEHEADER)); file.Write(&BitInfoHead,sizeof(BITMAPINFOHEADER)); file.Write(pBitBuf,WIDTHBYTES*iHeight); free(pBitBuf); file.Close(); :ConvertToTrueColorImage(BITMAPINFOHEADER bitInfo,HBITMAP hBitmap){ HDC hdc; CDC dc; int iBits; WORD wBitCount; DWORD dwBmBitsSize, dwDIBSize, dwWritten; BITMAPFILEHEADER bmfHdr; BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi; HANDLE hDib; try { dc.CreateDC("DISPLAY", "DISPLAY", 0, 0); hdc = dc.m_hDC; BITMAP BMP; wBitCount = 24; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = abs(bitInfo.biWidth); bi.biHeight = abs(bitInfo.biHeight); bi.biPlanes = 1; bi.biBitCount = wBitCount; bi.biCompression = BI_RGB; bi.biSizeImage = bitInfo.biSizeImage; bi.biXPelsPerMeter = bitInfo.biXPelsPerMeter; bi.biYPelsPerMeter = bitInfo.biYPelsPerMeter; bi.biClrUsed = 0; bi.biClrImportant = 0; dwBmBitsSize = ((bi.biWidth *wBitCount+31)/32)* 4*bi.biHeight ; hDib = GlobalAlloc(GHND,dwBmBitsSize+sizeof(BITMAPINFOHEADER)); lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); *lpbi = bi; // CClientDC dc(this); GetDIBits(hdc, hBitmap, 0, (UINT) bi.biHeight,(LPSTR)lpbi + sizeof(BITMAPINFOHEADER) ,(BITMAPINFO *)lpbi, DIB_RGB_COLORS); bmfHdr.bfType = 0x4D42; dwDIBSize = sizeof(BITMAPINFOHEADER)+ dwBmBitsSize; bmfHdr.bfSize = dwDIBSize; bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER); if(m_Data!=NULL) delete []m_Data; m_Data = new unsigned char[dwBmBitsSize]; unsigned char *data = (unsigned char *)lpbi; memcpy(m_Data,&data[sizeof(BITMAPINFOHEADER)],dwBmBitsSize); if(m_FileHeaderData!=NULL) delete []m_FileHeaderData; m_FileHeaderData = new unsigned char[sizeof(BITMAPFILEHEADER)]; memcpy(m_FileHeaderData,&bmfHdr,sizeof(BITMAPFILEHEADER)); if(m_InfoHeaderData!=NULL) delete []m_InfoHeaderData; m_InfoHeaderData = new unsigned char[sizeof(BITMAPINFOHEADER)]; memcpy(m_InfoHeaderData,&lpbi,sizeof(BITMAPINFOHEADER)); m_Depth = 24; m_BMPWidth = bi.biWidth ; m_BMPHeight = bi.biHeight; m_Channel = m_Depth/8; m_BytesPerLine = dwBmBitsSize/m_BMPHeight; BITMAPINFO m_bmi; ZeroMemory( &m_bmi, sizeof( BITMAPINFO ) ); m_bmi.bmiHeader= *lpbi; HBITMAP hBit = CreateDIBitmap(hdc,lpbi,CBM_INIT,m_Data,&m_bmi,DIB_RGB_COLORS|DIB_PAL_COLORS); if(m_hBitmap!=NULL) DeleteObject(m_hBitmap); m_hBitmap = (HBITMAP)CopyImage(hBit,IMAGE_BITMAP,m_BMPWidth,m_BMPHeight,LR_CREATEDIBSECTION); GlobalUnlock(hDib); GlobalFree(hDib); DeleteObject(hBit); } catch(...) { return _UNEXPECTED_ERROR; } return _NO_ERR;} mfc非主窗体的Socket在哪初始化 COM怎么给别的语言使用,都谁可以用 怎么在“A对话框”内调用“B对话框”内的函数,改变B对话框的内容 程序运行没有错误,调试时报错 Winuser.h里面有个#ifndef _MAC 宏,这个_MAC宏是什么意思 关于指针的疑惑 我重载了view的OnClose,但是程序退出时好像没有调用它 vc++6.0下,如何计算任意两天间的时间差,并显示出来? 关于CScrollView 采集卡,直接读写内存地址,如何做,做过采集的请进,急急急. 新手的问题请帮帮忙!!! 请问文档对象指针如何释放 !!!!!!!!!!!!!!!!!!!
我认为无非就是将位图数据变为3个字节表示一个像素,然后修改信息头和文件头。(不用调色板)
8位的最简单了,把原位图数据的每个字节扩成3个即可。
4位,2位类似,先逐个取出原位图数据,再扩成3个字节即可。
16位彩色图像的数据好像是5位,6位,5位,把它们分别扩成8位即可。
至于32位的,我就不大清楚了。
以上只是本人的一些想法,仅供参考。我也没有具体实现过。
bool CxImage::DecreaseBpp(DWORD nbit, bool errordiffusion, RGBQUAD* ppal)
{
if (!pDib) return false;
if (head.biBitCount < nbit) return false;
if (head.biBitCount == nbit) return true; long er,eg,eb;
RGBQUAD c,ce; CxImage tmp;
tmp.CopyInfo(*this);
tmp.Create(head.biWidth,head.biHeight,(WORD)nbit,info.dwType);#if CXIMAGE_SUPPORT_SELECTION
tmp.SelectionCopy(*this);
#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA
tmp.AlphaCopy(*this);
#endif //CXIMAGE_SUPPORT_ALPHA switch (tmp.head.biBitCount){
case 1:
if (ppal) tmp.SetPalette(ppal,16);
else {
tmp.SetPaletteColor(0,0,0,0);
tmp.SetPaletteColor(1,255,255,255);
}
break;
case 4:
if (ppal) tmp.SetPalette(ppal,16);
else tmp.SetStdPalette();
break;
case 8:
if (ppal) tmp.SetPalette(ppal);
else tmp.SetStdPalette();
break;
default:
return false;
} for (long y=0;y<head.biHeight;y++){
if (info.nEscape) break;
info.nProgress = (long)(100*y/head.biHeight);
for (long x=0;x<head.biWidth;x++){
if (!errordiffusion){
tmp.SetPixelColor(x,y,GetPixelColor(x,y));
} else {
c=GetPixelColor(x,y);
tmp.SetPixelColor(x,y,c); ce=tmp.GetPixelColor(x,y);
er=(long)c.rgbRed - (long)ce.rgbRed;
eg=(long)c.rgbGreen - (long)ce.rgbGreen;
eb=(long)c.rgbBlue - (long)ce.rgbBlue; c = GetPixelColor(x+1,y);
c.rgbRed = (BYTE)min(255L,max(0L,(long)c.rgbRed + ((er*7)/16)));
c.rgbGreen = (BYTE)min(255L,max(0L,(long)c.rgbGreen + ((eg*7)/16)));
c.rgbBlue = (BYTE)min(255L,max(0L,(long)c.rgbBlue + ((eb*7)/16)));
SetPixelColor(x+1,y,c);
int coeff;
for(int i=-1; i<2; i++){
switch(i){
case -1:
coeff=2; break;
case 0:
coeff=4; break;
case 1:
coeff=1; break;
}
c = GetPixelColor(x+i,y+1);
c.rgbRed = (BYTE)min(255L,max(0L,(long)c.rgbRed + ((er * coeff)/16)));
c.rgbGreen = (BYTE)min(255L,max(0L,(long)c.rgbGreen + ((eg * coeff)/16)));
c.rgbBlue = (BYTE)min(255L,max(0L,(long)c.rgbBlue + ((eb * coeff)/16)));
SetPixelColor(x+i,y+1,c);
}
}
}
} if (head.biBitCount==1){
tmp.SetPaletteColor(0,0,0,0);
tmp.SetPaletteColor(1,255,255,255);
} Transfer(tmp);
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool CxImage::IncreaseBpp(DWORD nbit)
{
if (!pDib) return false;
switch (nbit){
case 4:
{
if (head.biBitCount==4) return true;
if (head.biBitCount>4) return false; CxImage tmp;
tmp.CopyInfo(*this);
tmp.Create(head.biWidth,head.biHeight,4,info.dwType);
tmp.SetPalette(GetPalette(),GetNumColors());
#if CXIMAGE_SUPPORT_SELECTION
tmp.SelectionCopy(*this);
#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA
tmp.AlphaCopy(*this);
#endif //CXIMAGE_SUPPORT_ALPHA for (long y=0;y<head.biHeight;y++){
if (info.nEscape) break;
for (long x=0;x<head.biWidth;x++){
tmp.SetPixelIndex(x,y,GetPixelIndex(x,y));
}
}
Transfer(tmp);
return true;
}
case 8:
{
if (head.biBitCount==8) return true;
if (head.biBitCount>8) return false; CxImage tmp;
tmp.CopyInfo(*this);
tmp.Create(head.biWidth,head.biHeight,8,info.dwType);
tmp.SetPalette(GetPalette(),GetNumColors());#if CXIMAGE_SUPPORT_SELECTION
tmp.SelectionCopy(*this);
#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA
tmp.AlphaCopy(*this);
#endif //CXIMAGE_SUPPORT_ALPHA for (long y=0;y<head.biHeight;y++){
if (info.nEscape) break;
for (long x=0;x<head.biWidth;x++){
tmp.SetPixelIndex(x,y,GetPixelIndex(x,y));
}
}
Transfer(tmp);
return true;
}
case 24:
{
if (head.biBitCount==24) return true;
if (head.biBitCount>24) return false; CxImage tmp;
tmp.CopyInfo(*this);
tmp.Create(head.biWidth,head.biHeight,24,info.dwType);#if CXIMAGE_SUPPORT_SELECTION
tmp.SelectionCopy(*this);
#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA
tmp.AlphaCopy(*this);
if (AlphaPaletteIsValid() && !AlphaIsValid()) tmp.AlphaCreate();
#endif //CXIMAGE_SUPPORT_ALPHA for (long y=0;y<head.biHeight;y++){
if (info.nEscape) break;
for (long x=0;x<head.biWidth;x++){
tmp.SetPixelColor(x,y,GetPixelColor(x,y),true);
}
}
Transfer(tmp);
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool CxImage::Dither(long method)
{
if (!pDib) return false;
if (head.biBitCount == 1) return true;
switch (method){
case 1:
{
// Multi-Level Ordered-Dithering by Kenny Hoff (Oct. 12, 1995)
#define NumRows 4
#define NumCols 4
#define NumIntensityLevels 2
#define NumRowsLessOne (NumRows-1)
#define NumColsLessOne (NumCols-1)
#define RowsXCols (NumRows*NumCols)
#define MaxIntensityVal 255
#define MaxDitherIntensityVal (NumRows*NumCols*(NumIntensityLevels-1)) int DitherMatrix[NumRows][NumCols] = {{0,8,2,10}, {12,4,14,6}, {3,11,1,9}, {15,7,13,5} };
unsigned char Intensity[NumIntensityLevels] = { 0,1 }; // 2 LEVELS B/W
//unsigned char Intensity[NumIntensityLevels] = { 0,255 }; // 2 LEVELS
//unsigned char Intensity[NumIntensityLevels] = { 0,127,255 }; // 3 LEVELS
//unsigned char Intensity[NumIntensityLevels] = { 0,85,170,255 }; // 4 LEVELS
//unsigned char Intensity[NumIntensityLevels] = { 0,63,127,191,255 }; // 5 LEVELS
//unsigned char Intensity[NumIntensityLevels] = { 0,51,102,153,204,255 }; // 6 LEVELS
//unsigned char Intensity[NumIntensityLevels] = { 0,42,85,127,170,213,255 }; // 7 LEVELS
//unsigned char Intensity[NumIntensityLevels] = { 0,36,73,109,145,182,219,255 }; // 8 LEVELS
int DitherIntensity, DitherMatrixIntensity, Offset, DeviceIntensity;
unsigned char DitherValue;
GrayScale(); CxImage tmp(head.biWidth,head.biHeight,1,info.dwType);#if CXIMAGE_SUPPORT_SELECTION
tmp.SelectionCopy(*this);
#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA
tmp.AlphaCopy(*this);
#endif //CXIMAGE_SUPPORT_ALPHA for (long y=0;y<head.biHeight;y++){
info.nProgress = (long)(100*y/head.biHeight);
if (info.nEscape) break;
for (long x=0;x<head.biWidth;x++){ DeviceIntensity = GetPixelIndex(x,y);
DitherIntensity = DeviceIntensity*MaxDitherIntensityVal/MaxIntensityVal;
DitherMatrixIntensity = DitherIntensity % RowsXCols;
Offset = DitherIntensity / RowsXCols;
if (DitherMatrix[y&NumRowsLessOne][x&NumColsLessOne] < DitherMatrixIntensity)
DitherValue = Intensity[1+Offset];
else
DitherValue = Intensity[0+Offset]; tmp.SetPixelIndex(x,y,DitherValue);
}
}
tmp.SetPaletteColor(0,0,0,0);
tmp.SetPaletteColor(1,255,255,255);
Transfer(tmp);
break;
}
default:
{
// Floyd-Steinberg error diffusion (Thanks to Steve McMahon)
long error,nlevel,coeff;
BYTE level; GrayScale(); CxImage tmp(head.biWidth,head.biHeight,1,info.dwType);#if CXIMAGE_SUPPORT_SELECTION
tmp.SelectionCopy(*this);
#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA
tmp.AlphaCopy(*this);
#endif //CXIMAGE_SUPPORT_ALPHA for (long y=0;y<head.biHeight;y++){
info.nProgress = (long)(100*y/head.biHeight);
if (info.nEscape) break;
for (long x=0;x<head.biWidth;x++){ level=GetPixelIndex(x,y);
if (level > 128){
tmp.SetPixelIndex(x,y,1);
error = level-255;
} else {
tmp.SetPixelIndex(x,y,0);
error = level;
} nlevel = GetPixelIndex(x+1,y) + (error * 7)/16;
level = (BYTE)min(255,max(0,(int)nlevel));
SetPixelIndex(x+1,y,level);
for(int i=-1; i<2; i++){
switch(i){
case -1:
coeff=3; break;
case 0:
coeff=5; break;
case 1:
coeff=1; break;
}
nlevel = GetPixelIndex(x+i,y+1) + (error * coeff)/16;
level = (BYTE)min(255,max(0,(int)nlevel));
SetPixelIndex(x+i,y+1,level);
}
}
}
tmp.SetPaletteColor(0,0,0,0);
tmp.SetPaletteColor(1,255,255,255);
Transfer(tmp);
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////这是从CXImage中找出来的,就是实现不同位深之间的转换。
自己整理一下。
HANDLE h=::LoadImage(0,"f:\\abc.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
bitmap.Attach(h);
CFile file("F:\\abc1.bmp",CFile::modeCreate|CFile::modeWrite); BITMAP size;
bitmap.GetBitmap(&size);
int iHeight=size.bmHeight;
int iWidth=size.bmWidth;
int WIDTHBYTES;
unsigned char * pBitBuf=NULL; WIDTHBYTES=(iWidth*3+3)/4*4;
pBitBuf=(unsigned char *)malloc(WIDTHBYTES*iHeight); BITMAPFILEHEADER BitFileHead;
BITMAPINFOHEADER BitInfoHead;
BitInfoHead.biHeight=iHeight;
BitInfoHead.biWidth=iWidth;
BitInfoHead.biSizeImage=WIDTHBYTES*iHeight;
BitInfoHead.biSize = sizeof(BITMAPINFOHEADER);
BitInfoHead.biPlanes = 1;
BitInfoHead.biBitCount = 24;
BitInfoHead.biCompression = BI_RGB;
BitInfoHead.biXPelsPerMeter = 2952; // 75 DPI
BitInfoHead.biYPelsPerMeter = 2952; // 75 DPI
BitInfoHead.biClrUsed = 0;
BitInfoHead.biClrImportant = 0;
BitFileHead.bfType = 'MB'; // Non-portable... sigh
BitFileHead.bfSize = BitInfoHead.biSizeImage+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
BitFileHead.bfReserved1 = 0;
BitFileHead.bfReserved2 = 0;
BitFileHead.bfOffBits =sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); BITMAPINFO mapinfo;
mapinfo.bmiHeader=BitInfoHead;
// mapinfo.bmiColors HDC hdc = CreateIC (TEXT("DISPLAY"), NULL, NULL, NULL) ;
::GetDIBits (hdc, (HBITMAP)h,0, iHeight, pBitBuf, &mapinfo, DIB_RGB_COLORS) ;
file.Write(&BitFileHead,sizeof(BITMAPFILEHEADER));
file.Write(&BitInfoHead,sizeof(BITMAPINFOHEADER));
file.Write(pBitBuf,WIDTHBYTES*iHeight); free(pBitBuf);
file.Close();
{
HDC hdc;
CDC dc;
int iBits;
WORD wBitCount;
DWORD dwBmBitsSize, dwDIBSize, dwWritten;
BITMAPFILEHEADER bmfHdr;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
HANDLE hDib;
try
{
dc.CreateDC("DISPLAY", "DISPLAY", 0, 0);
hdc = dc.m_hDC;
BITMAP BMP;
wBitCount = 24;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = abs(bitInfo.biWidth);
bi.biHeight = abs(bitInfo.biHeight);
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = bitInfo.biSizeImage;
bi.biXPelsPerMeter = bitInfo.biXPelsPerMeter;
bi.biYPelsPerMeter = bitInfo.biYPelsPerMeter;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmBitsSize = ((bi.biWidth *wBitCount+31)/32)* 4*bi.biHeight ;
hDib = GlobalAlloc(GHND,dwBmBitsSize+sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi; // CClientDC dc(this);
GetDIBits(hdc, hBitmap, 0, (UINT) bi.biHeight,(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
,(BITMAPINFO *)lpbi, DIB_RGB_COLORS);
bmfHdr.bfType = 0x4D42;
dwDIBSize = sizeof(BITMAPINFOHEADER)+ dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER);
if(m_Data!=NULL)
delete []m_Data;
m_Data = new unsigned char[dwBmBitsSize];
unsigned char *data = (unsigned char *)lpbi;
memcpy(m_Data,&data[sizeof(BITMAPINFOHEADER)],dwBmBitsSize);
if(m_FileHeaderData!=NULL)
delete []m_FileHeaderData;
m_FileHeaderData = new unsigned char[sizeof(BITMAPFILEHEADER)];
memcpy(m_FileHeaderData,&bmfHdr,sizeof(BITMAPFILEHEADER));
if(m_InfoHeaderData!=NULL)
delete []m_InfoHeaderData;
m_InfoHeaderData = new unsigned char[sizeof(BITMAPINFOHEADER)];
memcpy(m_InfoHeaderData,&lpbi,sizeof(BITMAPINFOHEADER)); m_Depth = 24;
m_BMPWidth = bi.biWidth ;
m_BMPHeight = bi.biHeight;
m_Channel = m_Depth/8;
m_BytesPerLine = dwBmBitsSize/m_BMPHeight;
BITMAPINFO m_bmi;
ZeroMemory( &m_bmi, sizeof( BITMAPINFO ) );
m_bmi.bmiHeader= *lpbi;
HBITMAP hBit = CreateDIBitmap(hdc,lpbi,CBM_INIT,m_Data,&m_bmi,DIB_RGB_COLORS|DIB_PAL_COLORS);
if(m_hBitmap!=NULL)
DeleteObject(m_hBitmap);
m_hBitmap = (HBITMAP)CopyImage(hBit,IMAGE_BITMAP,m_BMPWidth,m_BMPHeight,LR_CREATEDIBSECTION);
GlobalUnlock(hDib);
GlobalFree(hDib);
DeleteObject(hBit);
}
catch(...)
{
return _UNEXPECTED_ERROR;
}
return _NO_ERR;
}