常用的图像处理小算法
2013-09-25 21:40
405 查看
1.RGB24数据的RGB互换
BOOL BGRFromRGB(BYTE *buf, UINT widthPix, UINT height)
{
if (buf==NULL)
return FALSE;
UINT col, row;
for (row=0;row<height;row++) {
for (col=0;col<widthPix;col++) {
LPBYTE pRed, pGrn, pBlu;
pRed = buf + row * widthPix * 3 + col * 3;
pGrn = buf + row * widthPix * 3 + col * 3 + 1;
pBlu = buf + row * widthPix * 3 + col * 3 + 2;
// 交换红色和蓝色
BYTE tmp;
tmp = *pRed;
*pRed = *pBlu;
*pBlu = tmp;
}
}
return TRUE;
}
2.从一个RGB24数据缓冲得到一个小的矩形RGB24缓冲
void GetPartImage( BYTE* image, int imageWidth, int imageHeight, BYTE* part, int left,int top, int right ,int bottom )
{
int w = right - left;
int h = bottom - top;
UINT nSize=((imageWidth*(24/8)+3)&~3);
for( int i=0; i<h; i++ )
{
for( int j=0; j<w; j++ )
{
part[j*3+i*w*3+0] = image[(left+j)*3+(top+i)*nSize+0];
part[j*3+i*w*3+1] = image[(left+j)*3+(top+i)*nSize+1];
part[j*3+i*w*3+2] = image[(left+j)*3+(top+i)*nSize+2];//imageWidth*3
}
}
}
3.对RGB24重新采样(最近邻算法)
BOOL ResampleBmp(BITMAPINFOHEADER& bih, BYTE* inBuf,int newx,int newy,BYTE* outBuf)
{
if (newx==0 || newy==0) return FALSE;
if (bih.biWidth==newx && bih.biHeight==newy){
if(outBuf)
{
memcpy(outBuf,inBuf,bih.biSizeImage);
}
return TRUE;
}
float xScale, yScale, fX, fY;
xScale = (float)bih.biWidth / (float)newx;
yScale = (float)bih.biHeight / (float)newy;
//DWORD对齐的扫描行的字节宽度
int dwEffWidth1 = ((((bih.biBitCount * bih.biWidth) + 31) / 32) * 4);
bih.biWidth=newx;
bih.biHeight=newy;
int dwEffWidth2 = ((((bih.biBitCount * bih.biWidth) + 31) / 32) * 4);
for(long y=0; y<newy; y++)
{
fY = y * yScale;
for(long x=0; x<newx; x++)
{
fX = x * xScale;
//得到源位图的每个象素点的RGB
BYTE* iSrc = inBuf + (int)fY*dwEffWidth1 + (int)fX*3;
RGBQUAD rgb;
rgb.rgbBlue = *iSrc++;
rgb.rgbGreen= *iSrc++;
rgb.rgbRed = *iSrc;
//设置目标位图的每个象素点的RGB
BYTE* iDst = outBuf + y*dwEffWidth2 + x*3;
*iDst++ = rgb.rgbBlue;
*iDst++ = rgb.rgbGreen;
*iDst = rgb.rgbRed;
}
}
bih.biSizeImage=dwEffWidth2*bih.biHeight;
return TRUE;
}
4.水平或垂直镜像位图
BOOL MirrorDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bDirection,int nImageBits)
{
// 指向源图像的指针
LPSTR lpSrc;
// 指向要复制区域的指针
LPSTR lpDst;
// 指向复制图像的指针
LPSTR lpBits;
HLOCAL hBits;
// 循环变量
LONG i;
LONG j;
int nBits;//每像素占的位数
// 图像每行的字节数
LONG lLineBytes;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth *nImageBits);
// 暂时分配内存,以保存一行图像
hBits = LocalAlloc(LHND, lLineBytes);
if (hBits == NULL)
{
// 分配内存失败
return FALSE;
}
// 锁定内存
lpBits = (char * )LocalLock(hBits);
int nStep=nImageBits/8;
long lCenter=lWidth/2*nStep;
// 判断镜像方式
if (bDirection)
{
// 水平镜像
// 针对图像每行进行操作
for(i = 0; i < lHeight; i++)
{
// 针对每行图像左半部分进行操作
for(j = 0; j < lCenter; j+=nStep)
{
for(nBits=0;nBits<nStep;nBits++)
{
lpSrc = (char *)lpDIBBits + lLineBytes * i +lCenter- j+nBits;
lpDst = (char *)lpDIBBits + lLineBytes * i +lCenter+ j+nBits;
*lpBits = *lpDst;
*lpDst = *lpSrc;
*lpSrc = *lpBits;
}
}
}
}
else
{
// 垂直镜像
// 针对上半图像进行操作
for(i = 0; i < lHeight / 2; i++)
{
// 指向倒数第i行象素起点的指针
lpSrc = (char *)lpDIBBits + lLineBytes * i;
// 指向第i行象素起点的指针
lpDst = (char *)lpDIBBits + lLineBytes * (lHeight - i - 1);
// 备份一行,宽度为lWidth
memcpy(lpBits, lpDst, lLineBytes);
// 将倒数第i行象素复制到第i行
memcpy(lpDst, lpSrc, lLineBytes);
// 将第i行象素复制到倒数第i行
memcpy(lpSrc, lpBits, lLineBytes);
}
}
// 释放内存
LocalUnlock(hBits);
LocalFree(hBits);
// 返回
return TRUE;
}
5.保存位图到文件
BOOL SaveBufToBmpFile( BYTE* buf, LPBITMAPINFOHEADER lpBih, LPCSTR strFileName )
{
FILE* bmpFile;
bmpFile = fopen( strFileName, "wb" );
if( bmpFile == NULL )
{
return FALSE;
}
BITMAPFILEHEADER bfh;
memset( &bfh, 0, sizeof( bfh ) );
bfh.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lpBih->biSizeImage;
bfh.bfType = 0x4d42;
bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );
fwrite( &bfh, sizeof(bfh), 1, bmpFile );
fwrite( lpBih, sizeof(BITMAPINFOHEADER), 1, bmpFile );
fwrite( buf, lpBih->biSizeImage, 1, bmpFile );
fclose( bmpFile );
return TRUE;
}
BOOL SaveCBitmapToFile(HBITMAP hBitmap, LPCTSTR strFileName)
{
//设备描述表
HDC hDC;
//当前分辨率下每象素所占字节数
int iBits;
//位图中每象素所占字节数
WORD wBitCount;
//定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0;
//位图属性结构
BITMAP Bitmap;
//位图文件头结构
BITMAPFILEHEADER bmfHdr;
//位图信息头结构
BITMAPINFOHEADER bi;
//指向位图信息头结构
LPBITMAPINFOHEADER lpbi;
//定义文件,分配内存句柄,调色板句柄
HANDLE fh, hDib, hPal,hOldPal=NULL;
//计算位图文件每个像素所占字节数
hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1) wBitCount = 1;
else if (iBits <= 4) wBitCount = 4;
else if (iBits <= 8) wBitCount = 8;
else wBitCount = 24;
GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);
//恢复调色板
if (hOldPal)
{
::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
//创建位图文件
fh = CreateFile(strFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh == INVALID_HANDLE_VALUE) return FALSE;
// 设置位图文件头
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;
// 写入位图文件头
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}
6.加载RGB24位图
BYTE* LoadBmpFromFile(LPCTSTR strFileName,BITMAPINFOHEADER& bih)
{
/*
CFile file;
if(!file.Open(strFileName,CFile::shareDenyRead ))
{
DWORD dwError=GetLastError();
return NULL;
}
BITMAPFILEHEADER bmfheader;
if(file.Read((LPSTR)&bmfheader,sizeof(bmfheader))!=sizeof(bmfheader))
return NULL;
if (bmfheader.bfType!=((WORD)('M'<<8)|'B')) return FALSE;
DWORD nLen=file.GetLength()- sizeof(BITMAPFILEHEADER);
HGLOBAL hDib=::GlobalAlloc(GMEM_FIXED,nLen);
if (hDib==NULL) return NULL;
if (file.ReadHuge((LPSTR)hDib, nLen)!=nLen)
{
::GlobalFree(hDib);
return NULL;
}
BITMAPINFOHEADER *BmIHeader=(LPBITMAPINFOHEADER)hDib;
LPBITMAPINFO BmInfo=(LPBITMAPINFO)hDib;
int nColors=BmIHeader->biClrUsed?BmIHeader->biClrUsed:1<<BmIHeader->biBitCount;
LPVOID lpDibBits;
if(BmInfo->bmiHeader.biBitCount>8)
lpDibBits=(LPVOID)((LPDWORD)(BmInfo->bmiColors+ BmInfo->bmiHeader.biClrUsed)+
((BmInfo->bmiHeader.biCompression==BI_BITFIELDS)?3:0));
else
lpDibBits=(LPVOID)(BmInfo->bmiColors+nColors);
memcpy(&bih,BmIHeader,sizeof(BITMAPINFOHEADER));
// bih.biSizeImage=WIDTHBYTES(bih.biWidth*bih.biBitCount)*bih.biHeight;
bih.biSizeImage=((bih.biWidth*(bih.biBitCount/8)+3)&~3)*bih.biHeight;
// bih.biSizeImage=bih.biWidth*bih.biHeight*3;
BYTE* pDataBuf=new BYTE[bih.biSizeImage];
memcpy(pDataBuf,lpDibBits,bih.biSizeImage);
::GlobalFree(hDib);
file.Close();
return pDataBuf;
*/
HANDLE bmpFile;
bmpFile = CreateFile( strFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( bmpFile==INVALID_HANDLE_VALUE )
return NULL;
DWORD dwRead;
BITMAPFILEHEADER bfh;
ReadFile( bmpFile, &bfh, sizeof(BITMAPFILEHEADER), &dwRead, NULL );
if( bfh.bfType != 0x4d42 )
{
CloseHandle(bmpFile);
return NULL;
}
ReadFile( bmpFile, &bih, sizeof(BITMAPINFOHEADER), &dwRead, NULL );
if( bih.biBitCount != 24 )
{
CloseHandle( bmpFile );
return NULL;
}
UINT bmpSize = ((bih.biWidth*(bih.biBitCount/8)+3)&~3)*bih.biHeight;
BYTE* imageBuf = new BYTE[bmpSize];
ReadFile( bmpFile, imageBuf, bmpSize, &dwRead, NULL );
bih.biSizeImage=bmpSize;
CloseHandle(bmpFile);
return imageBuf;
}
BOOL LoadBmpFromFile(LPCTSTR strFileName, CBitmap &bmp)
{
CFile file;
if(!file.Open(strFileName,CFile::shareDenyRead ))
{
DWORD dwError=GetLastError();
return FALSE;
}
BITMAPFILEHEADER bmfheader;
if(file.Read((LPSTR)&bmfheader,sizeof(bmfheader))!=sizeof(bmfheader))
return FALSE;
if (bmfheader.bfType!=((WORD)('M'<<8)|'B')) return FALSE;
DWORD nLen=file.GetLength()- sizeof(BITMAPFILEHEADER);
HGLOBAL hDib=::GlobalAlloc(GMEM_FIXED,nLen);
if (hDib==NULL) return FALSE;
if (file.ReadHuge((LPSTR)hDib, nLen)!=nLen)
{
::GlobalFree(hDib);
return FALSE;
}
BITMAPINFOHEADER *BmIHeader=(LPBITMAPINFOHEADER)hDib;
LPBITMAPINFO BmInfo=(LPBITMAPINFO)hDib;
int nColors=BmIHeader->biClrUsed?BmIHeader->biClrUsed:1<<BmIHeader->biBitCount;
LPVOID lpDibBits;
if(BmInfo->bmiHeader.biBitCount>8)
lpDibBits=(LPVOID)((LPDWORD)(BmInfo->bmiColors+ BmInfo->bmiHeader.biClrUsed)+
((BmInfo->bmiHeader.biCompression==BI_BITFIELDS)?3:0));
else
lpDibBits=(LPVOID)(BmInfo->bmiColors+nColors);
CClientDC dc(NULL);
HBITMAP hBmp =::CreateDIBitmap(dc.m_hDC,
BmIHeader,
CBM_INIT,
lpDibBits,
BmInfo,
DIB_RGB_COLORS);
bmp.Attach( hBmp );
::GlobalFree(hDib);
file.Close();
return TRUE;
}
7.从位图数据得到CBitmap
BOOL GetCBitmap(BITMAPINFOHEADER* pBih, BYTE* pDataBuf,CBitmap &bmp)
{
BITMAPINFO bi;
memset( &bi, 0, sizeof(bi) );
memcpy( &(bi.bmiHeader), pBih, sizeof(BITMAPINFOHEADER) );
CClientDC dc(NULL);
HBITMAP hBmp =::CreateDIBitmap(dc.m_hDC,
pBih,
CBM_INIT,
pDataBuf,
&bi,
DIB_RGB_COLORS);
bmp.Attach( hBmp );
return TRUE;
}
8.从CImageList得到提取一个HBITMAP
HBITMAP GetBitmapFromImageList(CImageList& imageList,int nWidth,int nHeight,int nIndex)
{
//从ImageList得出相应的bmp
HDC hDC=::GetDC(NULL);
CDC dc;
dc.CreateCompatibleDC(NULL);
HBITMAP hBmp=CreateCompatibleBitmap(hDC,nWidth,nHeight);
HBITMAP obmp = (HBITMAP) SelectObject(dc.m_hDC, hBmp);
imageList.Draw(&dc,nIndex,CPoint(0,0),ILD_NORMAL);
hBmp=(HBITMAP) SelectObject(dc.m_hDC, obmp);
dc.DeleteDC();
return hBmp;
}
9.从HBitmap得到对应的位图数据
BYTE* GetBmpInfoFromHBitmap(HBITMAP hBitmap,BITMAPINFOHEADER& bih)
{
//设备描述表
HDC hDC;
//当前分辨率下每象素所占字节数
int iBits;
//位图中每象素所占字节数
WORD wBitCount;
//定义调色板大小, 位图中像素字节大小
DWORD dwPaletteSize=0, dwBmBitsSize=0;
//位图属性结构
BITMAP Bitmap;
//位图信息头结构
BITMAPINFOHEADER bi;
//指向位图信息头结构
LPBITMAPINFOHEADER lpbi;
//定义文件,分配内存句柄,调色板句柄
HANDLE hDib, hPal,hOldPal=NULL;
//计算位图文件每个像素所占字节数
hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1) wBitCount = 1;
else if (iBits <= 4) wBitCount = 4;
else if (iBits <= 8) wBitCount = 8;
else wBitCount = 24;
GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
bi.biSizeImage=dwBmBitsSize;
//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);
memcpy(&bih,&bi,sizeof(BITMAPINFOHEADER));
BYTE* pDataBuf=new BYTE[dwBmBitsSize];
memcpy(pDataBuf,(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,dwBmBitsSize);
//恢复调色板
if (hOldPal)
{
::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
//清除资源
GlobalUnlock(hDib);
GlobalFree(hDib);
return pDataBuf;
}
BOOL BGRFromRGB(BYTE *buf, UINT widthPix, UINT height)
{
if (buf==NULL)
return FALSE;
UINT col, row;
for (row=0;row<height;row++) {
for (col=0;col<widthPix;col++) {
LPBYTE pRed, pGrn, pBlu;
pRed = buf + row * widthPix * 3 + col * 3;
pGrn = buf + row * widthPix * 3 + col * 3 + 1;
pBlu = buf + row * widthPix * 3 + col * 3 + 2;
// 交换红色和蓝色
BYTE tmp;
tmp = *pRed;
*pRed = *pBlu;
*pBlu = tmp;
}
}
return TRUE;
}
2.从一个RGB24数据缓冲得到一个小的矩形RGB24缓冲
void GetPartImage( BYTE* image, int imageWidth, int imageHeight, BYTE* part, int left,int top, int right ,int bottom )
{
int w = right - left;
int h = bottom - top;
UINT nSize=((imageWidth*(24/8)+3)&~3);
for( int i=0; i<h; i++ )
{
for( int j=0; j<w; j++ )
{
part[j*3+i*w*3+0] = image[(left+j)*3+(top+i)*nSize+0];
part[j*3+i*w*3+1] = image[(left+j)*3+(top+i)*nSize+1];
part[j*3+i*w*3+2] = image[(left+j)*3+(top+i)*nSize+2];//imageWidth*3
}
}
}
3.对RGB24重新采样(最近邻算法)
BOOL ResampleBmp(BITMAPINFOHEADER& bih, BYTE* inBuf,int newx,int newy,BYTE* outBuf)
{
if (newx==0 || newy==0) return FALSE;
if (bih.biWidth==newx && bih.biHeight==newy){
if(outBuf)
{
memcpy(outBuf,inBuf,bih.biSizeImage);
}
return TRUE;
}
float xScale, yScale, fX, fY;
xScale = (float)bih.biWidth / (float)newx;
yScale = (float)bih.biHeight / (float)newy;
//DWORD对齐的扫描行的字节宽度
int dwEffWidth1 = ((((bih.biBitCount * bih.biWidth) + 31) / 32) * 4);
bih.biWidth=newx;
bih.biHeight=newy;
int dwEffWidth2 = ((((bih.biBitCount * bih.biWidth) + 31) / 32) * 4);
for(long y=0; y<newy; y++)
{
fY = y * yScale;
for(long x=0; x<newx; x++)
{
fX = x * xScale;
//得到源位图的每个象素点的RGB
BYTE* iSrc = inBuf + (int)fY*dwEffWidth1 + (int)fX*3;
RGBQUAD rgb;
rgb.rgbBlue = *iSrc++;
rgb.rgbGreen= *iSrc++;
rgb.rgbRed = *iSrc;
//设置目标位图的每个象素点的RGB
BYTE* iDst = outBuf + y*dwEffWidth2 + x*3;
*iDst++ = rgb.rgbBlue;
*iDst++ = rgb.rgbGreen;
*iDst = rgb.rgbRed;
}
}
bih.biSizeImage=dwEffWidth2*bih.biHeight;
return TRUE;
}
4.水平或垂直镜像位图
BOOL MirrorDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bDirection,int nImageBits)
{
// 指向源图像的指针
LPSTR lpSrc;
// 指向要复制区域的指针
LPSTR lpDst;
// 指向复制图像的指针
LPSTR lpBits;
HLOCAL hBits;
// 循环变量
LONG i;
LONG j;
int nBits;//每像素占的位数
// 图像每行的字节数
LONG lLineBytes;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth *nImageBits);
// 暂时分配内存,以保存一行图像
hBits = LocalAlloc(LHND, lLineBytes);
if (hBits == NULL)
{
// 分配内存失败
return FALSE;
}
// 锁定内存
lpBits = (char * )LocalLock(hBits);
int nStep=nImageBits/8;
long lCenter=lWidth/2*nStep;
// 判断镜像方式
if (bDirection)
{
// 水平镜像
// 针对图像每行进行操作
for(i = 0; i < lHeight; i++)
{
// 针对每行图像左半部分进行操作
for(j = 0; j < lCenter; j+=nStep)
{
for(nBits=0;nBits<nStep;nBits++)
{
lpSrc = (char *)lpDIBBits + lLineBytes * i +lCenter- j+nBits;
lpDst = (char *)lpDIBBits + lLineBytes * i +lCenter+ j+nBits;
*lpBits = *lpDst;
*lpDst = *lpSrc;
*lpSrc = *lpBits;
}
}
}
}
else
{
// 垂直镜像
// 针对上半图像进行操作
for(i = 0; i < lHeight / 2; i++)
{
// 指向倒数第i行象素起点的指针
lpSrc = (char *)lpDIBBits + lLineBytes * i;
// 指向第i行象素起点的指针
lpDst = (char *)lpDIBBits + lLineBytes * (lHeight - i - 1);
// 备份一行,宽度为lWidth
memcpy(lpBits, lpDst, lLineBytes);
// 将倒数第i行象素复制到第i行
memcpy(lpDst, lpSrc, lLineBytes);
// 将第i行象素复制到倒数第i行
memcpy(lpSrc, lpBits, lLineBytes);
}
}
// 释放内存
LocalUnlock(hBits);
LocalFree(hBits);
// 返回
return TRUE;
}
5.保存位图到文件
BOOL SaveBufToBmpFile( BYTE* buf, LPBITMAPINFOHEADER lpBih, LPCSTR strFileName )
{
FILE* bmpFile;
bmpFile = fopen( strFileName, "wb" );
if( bmpFile == NULL )
{
return FALSE;
}
BITMAPFILEHEADER bfh;
memset( &bfh, 0, sizeof( bfh ) );
bfh.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lpBih->biSizeImage;
bfh.bfType = 0x4d42;
bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );
fwrite( &bfh, sizeof(bfh), 1, bmpFile );
fwrite( lpBih, sizeof(BITMAPINFOHEADER), 1, bmpFile );
fwrite( buf, lpBih->biSizeImage, 1, bmpFile );
fclose( bmpFile );
return TRUE;
}
BOOL SaveCBitmapToFile(HBITMAP hBitmap, LPCTSTR strFileName)
{
//设备描述表
HDC hDC;
//当前分辨率下每象素所占字节数
int iBits;
//位图中每象素所占字节数
WORD wBitCount;
//定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0;
//位图属性结构
BITMAP Bitmap;
//位图文件头结构
BITMAPFILEHEADER bmfHdr;
//位图信息头结构
BITMAPINFOHEADER bi;
//指向位图信息头结构
LPBITMAPINFOHEADER lpbi;
//定义文件,分配内存句柄,调色板句柄
HANDLE fh, hDib, hPal,hOldPal=NULL;
//计算位图文件每个像素所占字节数
hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1) wBitCount = 1;
else if (iBits <= 4) wBitCount = 4;
else if (iBits <= 8) wBitCount = 8;
else wBitCount = 24;
GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);
//恢复调色板
if (hOldPal)
{
::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
//创建位图文件
fh = CreateFile(strFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh == INVALID_HANDLE_VALUE) return FALSE;
// 设置位图文件头
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;
// 写入位图文件头
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}
6.加载RGB24位图
BYTE* LoadBmpFromFile(LPCTSTR strFileName,BITMAPINFOHEADER& bih)
{
/*
CFile file;
if(!file.Open(strFileName,CFile::shareDenyRead ))
{
DWORD dwError=GetLastError();
return NULL;
}
BITMAPFILEHEADER bmfheader;
if(file.Read((LPSTR)&bmfheader,sizeof(bmfheader))!=sizeof(bmfheader))
return NULL;
if (bmfheader.bfType!=((WORD)('M'<<8)|'B')) return FALSE;
DWORD nLen=file.GetLength()- sizeof(BITMAPFILEHEADER);
HGLOBAL hDib=::GlobalAlloc(GMEM_FIXED,nLen);
if (hDib==NULL) return NULL;
if (file.ReadHuge((LPSTR)hDib, nLen)!=nLen)
{
::GlobalFree(hDib);
return NULL;
}
BITMAPINFOHEADER *BmIHeader=(LPBITMAPINFOHEADER)hDib;
LPBITMAPINFO BmInfo=(LPBITMAPINFO)hDib;
int nColors=BmIHeader->biClrUsed?BmIHeader->biClrUsed:1<<BmIHeader->biBitCount;
LPVOID lpDibBits;
if(BmInfo->bmiHeader.biBitCount>8)
lpDibBits=(LPVOID)((LPDWORD)(BmInfo->bmiColors+ BmInfo->bmiHeader.biClrUsed)+
((BmInfo->bmiHeader.biCompression==BI_BITFIELDS)?3:0));
else
lpDibBits=(LPVOID)(BmInfo->bmiColors+nColors);
memcpy(&bih,BmIHeader,sizeof(BITMAPINFOHEADER));
// bih.biSizeImage=WIDTHBYTES(bih.biWidth*bih.biBitCount)*bih.biHeight;
bih.biSizeImage=((bih.biWidth*(bih.biBitCount/8)+3)&~3)*bih.biHeight;
// bih.biSizeImage=bih.biWidth*bih.biHeight*3;
BYTE* pDataBuf=new BYTE[bih.biSizeImage];
memcpy(pDataBuf,lpDibBits,bih.biSizeImage);
::GlobalFree(hDib);
file.Close();
return pDataBuf;
*/
HANDLE bmpFile;
bmpFile = CreateFile( strFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( bmpFile==INVALID_HANDLE_VALUE )
return NULL;
DWORD dwRead;
BITMAPFILEHEADER bfh;
ReadFile( bmpFile, &bfh, sizeof(BITMAPFILEHEADER), &dwRead, NULL );
if( bfh.bfType != 0x4d42 )
{
CloseHandle(bmpFile);
return NULL;
}
ReadFile( bmpFile, &bih, sizeof(BITMAPINFOHEADER), &dwRead, NULL );
if( bih.biBitCount != 24 )
{
CloseHandle( bmpFile );
return NULL;
}
UINT bmpSize = ((bih.biWidth*(bih.biBitCount/8)+3)&~3)*bih.biHeight;
BYTE* imageBuf = new BYTE[bmpSize];
ReadFile( bmpFile, imageBuf, bmpSize, &dwRead, NULL );
bih.biSizeImage=bmpSize;
CloseHandle(bmpFile);
return imageBuf;
}
BOOL LoadBmpFromFile(LPCTSTR strFileName, CBitmap &bmp)
{
CFile file;
if(!file.Open(strFileName,CFile::shareDenyRead ))
{
DWORD dwError=GetLastError();
return FALSE;
}
BITMAPFILEHEADER bmfheader;
if(file.Read((LPSTR)&bmfheader,sizeof(bmfheader))!=sizeof(bmfheader))
return FALSE;
if (bmfheader.bfType!=((WORD)('M'<<8)|'B')) return FALSE;
DWORD nLen=file.GetLength()- sizeof(BITMAPFILEHEADER);
HGLOBAL hDib=::GlobalAlloc(GMEM_FIXED,nLen);
if (hDib==NULL) return FALSE;
if (file.ReadHuge((LPSTR)hDib, nLen)!=nLen)
{
::GlobalFree(hDib);
return FALSE;
}
BITMAPINFOHEADER *BmIHeader=(LPBITMAPINFOHEADER)hDib;
LPBITMAPINFO BmInfo=(LPBITMAPINFO)hDib;
int nColors=BmIHeader->biClrUsed?BmIHeader->biClrUsed:1<<BmIHeader->biBitCount;
LPVOID lpDibBits;
if(BmInfo->bmiHeader.biBitCount>8)
lpDibBits=(LPVOID)((LPDWORD)(BmInfo->bmiColors+ BmInfo->bmiHeader.biClrUsed)+
((BmInfo->bmiHeader.biCompression==BI_BITFIELDS)?3:0));
else
lpDibBits=(LPVOID)(BmInfo->bmiColors+nColors);
CClientDC dc(NULL);
HBITMAP hBmp =::CreateDIBitmap(dc.m_hDC,
BmIHeader,
CBM_INIT,
lpDibBits,
BmInfo,
DIB_RGB_COLORS);
bmp.Attach( hBmp );
::GlobalFree(hDib);
file.Close();
return TRUE;
}
7.从位图数据得到CBitmap
BOOL GetCBitmap(BITMAPINFOHEADER* pBih, BYTE* pDataBuf,CBitmap &bmp)
{
BITMAPINFO bi;
memset( &bi, 0, sizeof(bi) );
memcpy( &(bi.bmiHeader), pBih, sizeof(BITMAPINFOHEADER) );
CClientDC dc(NULL);
HBITMAP hBmp =::CreateDIBitmap(dc.m_hDC,
pBih,
CBM_INIT,
pDataBuf,
&bi,
DIB_RGB_COLORS);
bmp.Attach( hBmp );
return TRUE;
}
8.从CImageList得到提取一个HBITMAP
HBITMAP GetBitmapFromImageList(CImageList& imageList,int nWidth,int nHeight,int nIndex)
{
//从ImageList得出相应的bmp
HDC hDC=::GetDC(NULL);
CDC dc;
dc.CreateCompatibleDC(NULL);
HBITMAP hBmp=CreateCompatibleBitmap(hDC,nWidth,nHeight);
HBITMAP obmp = (HBITMAP) SelectObject(dc.m_hDC, hBmp);
imageList.Draw(&dc,nIndex,CPoint(0,0),ILD_NORMAL);
hBmp=(HBITMAP) SelectObject(dc.m_hDC, obmp);
dc.DeleteDC();
return hBmp;
}
9.从HBitmap得到对应的位图数据
BYTE* GetBmpInfoFromHBitmap(HBITMAP hBitmap,BITMAPINFOHEADER& bih)
{
//设备描述表
HDC hDC;
//当前分辨率下每象素所占字节数
int iBits;
//位图中每象素所占字节数
WORD wBitCount;
//定义调色板大小, 位图中像素字节大小
DWORD dwPaletteSize=0, dwBmBitsSize=0;
//位图属性结构
BITMAP Bitmap;
//位图信息头结构
BITMAPINFOHEADER bi;
//指向位图信息头结构
LPBITMAPINFOHEADER lpbi;
//定义文件,分配内存句柄,调色板句柄
HANDLE hDib, hPal,hOldPal=NULL;
//计算位图文件每个像素所占字节数
hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1) wBitCount = 1;
else if (iBits <= 4) wBitCount = 4;
else if (iBits <= 8) wBitCount = 8;
else wBitCount = 24;
GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
bi.biSizeImage=dwBmBitsSize;
//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);
memcpy(&bih,&bi,sizeof(BITMAPINFOHEADER));
BYTE* pDataBuf=new BYTE[dwBmBitsSize];
memcpy(pDataBuf,(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,dwBmBitsSize);
//恢复调色板
if (hOldPal)
{
::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
//清除资源
GlobalUnlock(hDib);
GlobalFree(hDib);
return pDataBuf;
}
相关文章推荐
- 【图像处理之常用算法一】——彩色图像的灰度化
- 图像处理算法(二)---图像常用颜色空间
- 图像处理常用算法GPU实现三:基于模板匹配的边缘检测
- 图像处理常用算法
- 图像处理常用算法GPU实现五:图像对比度增强
- 图像处理常用算法GPU实现二:基于微分的边缘检测
- 图像处理常用算法(C/C++)
- 常用用图像处理算法(一)
- 图像处理(验证码识别)程序中常用算法
- 图像处理常用算法(基础)
- 常用用图像处理算法(二)
- 图像处理之 opencv 学习---opencv 中的常用算法
- 【图像处理】数字图像处理中常用图像分割算法(理论初识)
- 图形与图像处理的常用的水印算法
- 图像处理常用算法GPU实现四:基于中值滤波的二值图像平滑
- 常用图像处理算法(三)
- 图像处理常用算法GPU实现四:基于中值滤波的二值图像平滑
- 图像处理常用算法总结
- 8种常用图像处理算法
- 8种常用图像处理算法