真彩色BMP图象转256色BMP图函数

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

BOOL CTest14Dlg::Trueto256()

{

DWORD SrcBufSize,OffBits,DstBufSize,DstLineBytes;
HLOCAL hImgData;
LPBITMAPINFOHEADER lpImgData;

LPSTR lpPtr;

HLOCAL hTempImgData;

LPBITMAPINFOHEADER lpTempImgData;

LPSTR lpTempPtr;

HDC hDc;

HFILE hf;

LONG x,y;

BITMAPFILEHEADER DstBf;

BITMAPINFOHEADER DstBi;

LOGPALETTE *pPal;
HPALETTE hPalette;
HPALETTE hPrevPalette;

HLOCAL hPal;

WORD i,j;

int Red,Green,Blue,ClrIndex;

DWORD ColorHits[4096];

WORD ColorIndex[4096];

DWORD PalCounts,temp;

long ColorError1,ColorError2;
HBITMAP hBitmap;

BITMAPFILEHEADER bmfHdr; // 位图文件头结构
LPBITMAPINFOHEADER lpBI; file://指向位图信息结构的指针
DWORD dwDIBSize;

char * path=new char [100];
sprintf(path,"D:\\新建文件夹\\日本验证码\\日本验证码\\2.bmp");
CFile file;
CFileException fe;
if (!file.Open(path, CFile::modeRead | CFile::shareDenyWrite, &fe))
{
AfxMessageBox("文件打不开");
return FALSE;
}//打开文件


BITMAPFILEHEADER bf;//定义位图文件头结构
DWORD dwBitsSize;
HANDLE hDIB;
LPSTR pDIB;
BITMAPINFOHEADER *bmhdr;//指向位图信息头结构的指针
BITMAPINFOHEADER bi;
dwBitsSize = file.GetLength();//得到文件长度
if (file.Read((LPSTR)&bf, sizeof(bf)) !=sizeof(bf))
return FALSE;
if (bf.bfType != 0x4d42) //检查是否为BMP文件
return FALSE;
hDIB=(HANDLE) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);//申请缓冲区
if (hDIB == 0)
{
return FALSE;
}
pDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB); //得到申请的缓冲区的指针
if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=dwBitsSize - sizeof(BITMAPFILEHEADER) )
{
::GlobalUnlock((HGLOBAL)hDIB);
hDIB=NULL;
return FALSE;
}//读数据,包括位图信息、位图颜色表、图像像素的灰度值
bmhdr=(BITMAPINFOHEADER*)pDIB;//为指向位图信息头结构的指针付值
memcpy(&bi,pDIB,sizeof(BITMAPINFOHEADER));
::GlobalUnlock((HGLOBAL)hDIB);
if ((*bmhdr).biBitCount!=24) //验证是否为真彩色位图
return FALSE;

//由于颜色位数有可能发生了改变,所以要重新计算每行占用的字节数以及

//新图的缓冲区大小

DstLineBytes=(DWORD)WIDTHBYTES(bi.biWidth*8);

DstBufSize=(DWORD)(sizeof(BITMAPINFOHEADER)+

256*sizeof(RGBQUAD)+

(DWORD)DstLineBytes*bi.biHeight);

//DstBf和DstBi为新的BITMAPFILEHEADER和BITMAPINFOHEADER

//拷贝原来的头信息

memcpy((char *)&DstBf,(char *)&bf,sizeof(BITMAPFILEHEADER));

memcpy((char *)&DstBi,(char *)&bi,sizeof(BITMAPINFOHEADER));

//

做必要的改变

DstBf.bfSize=DstBufSize+sizeof(BITMAPFILEHEADER);

DstBf.bfOffBits=(DWORD)(256*sizeof(RGBQUAD)+

sizeof(BITMAPFILEHEADER)

+sizeof(BITMAPINFOHEADER));

DstBi.biClrUsed=0;

DstBi.biBitCount=8;

//OffBits为到实际位图数据的偏移值

OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);

//SrcBufSize为原图缓冲区的大小

int LineBytes=WIDTHBYTES(bi.biWidth*bi.biBitCount);
SrcBufSize=OffBits+bi.biHeight*LineBytes;

if((hTempImgData=LocalAlloc(LHND,DstBufSize))==NULL)
{

return FALSE;

}
hImgData=LocalAlloc(LHND,SrcBufSize);
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
memcpy(lpImgData,pDIB,dwBitsSize - sizeof(BITMAPFILEHEADER));

lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);

//拷贝位图数据

memcpy(lpTempImgData,lpImgData,OffBits);

//用新的头信息取代旧的头信息

memcpy(lpTempImgData,(char *)&DstBi,sizeof(BITMAPINFOHEADER));

//ColorHits为记录颜色使用频率的数组,ColorIndex为记录颜色索引值的

//数组

//先全部清零

memset(ColorHits,0,4096*sizeof(DWORD));

memset(ColorIndex,0,4096*sizeof(WORD));

for(y=0;y
lpPtr=(char *)lpImgData+(SrcBufSize-LineBytes-y*LineBytes);

for(x=0;x
//R,G,B各取4位

Blue=(int)(*(lpPtr++) & 0xf0);

Green=(int)(*(lpPtr++) & 0xf0);

Red=(int)(*(lpPtr++) & 0xf0);

//拼成一个12位整数

ClrIndex=(Blue<<4) + Green +(Red >>4);

//相应的数组元素加1

ColorHits[ClrIndex]++;

}

}

PalCounts=0;

//将为零的元素清除出去

for (ClrIndex = 0; ClrIndex < 4096; ClrIndex++)

{

if(ColorHits[ClrIndex]!=0){

ColorHits[PalCounts]=ColorHits[ClrIndex];

//注意调整相应的索引值

ColorIndex[PalCounts]=ClrIndex;

PalCounts++; //颜色数加1

}

}

//用起泡排序将PalCounts种颜色按从大到小的顺序排列

for (i = 0; i < PalCounts-1; i++)

for (j = i + 1; j < PalCounts; j++){

if (ColorHits[j] > ColorHits[i]){

temp = ColorHits[i];

ColorHits[i] = ColorHits[j];

ColorHits[j] = temp;

//注意调整相应的索引值

temp = ColorIndex[i];

ColorIndex[i] = ColorIndex[j];

ColorIndex[j] = (WORD)temp;

}

}

//为新的调色板分配内存

hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) +

256* sizeof(PALETTEENTRY));

pPal =(LOGPALETTE *)LocalLock(hPal);

pPal->palNumEntries =(WORD) 256;

pPal->palVersion = 0x300;

lpTempPtr=(char *)lpTempImgData+sizeof(BITMAPINFOHEADER);

for (i = 0; i < 256; i++) {

//由12位索引值得到R,G,B的最高4位值

pPal->palPalEntry[i].peRed=(BYTE)((ColorIndex[i] & 0x00f) << 4);

pPal->pa

lPalEntry[i].peGreen=(BYTE)((ColorIndex[i] & 0x0f0));

pPal->palPalEntry[i].peBlue=(BYTE)((ColorIndex[i] & 0xf00) >> 4);

pPal->palPalEntry[i].peFlags=(BYTE)0;

*(lpTempPtr++)=(unsigned char)((ColorIndex[i] & 0xf00) >> 4);

*(lpTempPtr++)=(unsigned char)((ColorIndex[i] & 0x0f0));

*(lpTempPtr++)=(unsigned char)((ColorIndex[i] & 0x00f) << 4);

*(lpTempPtr++)=0;

//ColorHits作为颜色记数的作用已经完成了,下面的作用是记录12位索

//引值对应的调色板//中的索引值

ColorHits[i]=i;

}

//其余的颜色依据最小平方误差近似为前256中最接近的一种

if (PalCounts > 256){

for (i = 256; i < PalCounts; i++){

//ColorError1记录最小平方误差,一开始赋一个很大的值

ColorError1=1000000000;

//由12位索引值得到R,G,B的最高4位值

Blue = (long)((ColorIndex[i] & 0xf00) >> 4);

Green = (long)((ColorIndex[i] & 0x0f0));

Red = (long)((ColorIndex[i] & 0x00f) << 4);

ClrIndex = 0;

for (j = 0; j < 256; j++){

//ColorError2计算当前的平方误差

ColorError2=(long)(Blue-pPal->palPalEntry[j].peBlue)*

(Blue-pPal->palPalEntry[j].peBlue)+ (long)(Green-pPal->palPalEntry[j].peGreen)*

(Green-pPal->palPalEntry[j].peGreen)+

(long)(Red-pPal->palPalEntry[j].peRed)*

(Red-pPal->palPalEntry[j].peRed);

if (ColorError2 < ColorError1){ //找到更小的了

ColorError1 = ColorError2;

ClrIndex = j; //记录对应的调色板的索引值

}

}

//ColorHits记录12位索引值对应的调色板中的索引值

ColorHits[i] = ClrIndex;

}

}

if(hPalette!=NULL)

DeleteObject(hPalette);

//产生新的逻辑调色板

hPalette=CreatePalette(pPal);

LocalUnlock(hPal);

LocalFree(hPal);
/*
hDc=GetDC(hWnd);
*/
if(hPalette){

hPrevPalette=SelectPalette(hDc,hPalette,FALSE);

RealizePalette(hDc);

}

for(y=0;y
lpPtr=(char *)lpImgData+(SrcBufSize-LineBytes-y*LineBytes);

lpTempPtr=(char*)lpTempImgData+

(DstBufSize-DstLineBytes-y*DstLineBytes);

for(x=0;x//R,G,B各取4位

Blue=(int)(*(lpPtr++) & 0xf0);

Green=(int)(*(lpPtr++) & 0xf0);

Red=(int)(*(lpPtr++) & 0xf0);

//拼成一个12位整数

ClrIndex=(Blue<<4) + Green +(Red >>4);

for (i = 0; i < PalCounts;i++)

if (ClrIndex == ColorIndex[i]){

//根据12索引值取得对应的调色板中的索引值

*(lpTempPtr++)=(unsigned char)ColorHits[i];

break;

}


}

}

if(hBitmap!=NULL)

DeleteObject(hBitmap);

//产生新的位图

hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpTempImgData,(LONG)CBM_INIT,(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD),(LPBITMAPINFO)lpTempImgData,DIB_RGB_COLORS);

if(hPalette && hPrevPalette){

SelectPalette(hDc,hPrevPalette,FALSE);

RealizePalette(hDc);

}

hf=_lcreat("c:\\256.bmp",0);

_lwrite(hf,(LPSTR)&DstBf,sizeof(BITMAPFILEHEADER));

_lwrite(hf,(LPSTR)lpTempImgData,DstBufSize);

_lclose(hf);

//释放内存和资源

LocalUnlock(hTempImgData);

LocalFree(hTempImgData);

GlobalUnlock(hImgData);

return TRUE;
}

相关文档
最新文档