📄 dib.cpp
字号:
return nBitCount;
}
/*************************************************************************
*
* 函数名称:
* CopyHandle()
*
* 参数:
* HGLOBAL h - 要复制的内存区域
*
* 返回值:
* HGLOBAL - 复制后的新内存区域
*
* 说明:
* 拷贝内存块
*
************************************************************************/
HGLOBAL CDIB::CopyHandle (HGLOBAL h)
{
if (h == NULL)
return NULL;
// 获取指定内存区域大小
DWORD dwLen = ::GlobalSize((HGLOBAL) h);
// 分配新内存空间
HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);
// 判断分配是否成功
if (hCopy != NULL)
{
// 锁定
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
void* lp = ::GlobalLock((HGLOBAL) h);
// 复制
memcpy(lpCopy, lp, dwLen);
// 解除锁定
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
}
return hCopy;
}
/*************************************************************************
*
* 函数名称:
* SaveDIB()
*
* 参数:
* HDIB hDib - 要保存的DIB
* CFile& file - 保存文件CFile
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE或者CFileException
*
* 说明:
* 将DIB保存到指定文件中
*
*************************************************************************/
BOOL CDIB::SaveDIB(HDIB hDib, CFile& file)
{
// Bitmap文件头
BITMAPFILEHEADER bmfHdr;
// 指向BITMAPINFOHEADER的指针
LPBITMAPINFOHEADER lpBI;
if (hDib == NULL)
{
// 如果DIB为空,返回FALSE
return FALSE;
}
// 读取BITMAPINFO结构,并锁定
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL)
{
// 为空,返回FALSE
return FALSE;
}
// 判断是否是WIN3.0 DIB
if (!IS_WIN30_DIB(lpBI))
{
// 不支持其它类型的DIB保存
// 解除锁定
::GlobalUnlock((HGLOBAL) hDib);
// 返回FALSE
return FALSE;
}
// 填充文件头
// 文件类型"BM"
bmfHdr.bfType = DIB_HEADER_MARKER;
// 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并
// 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。
// 文件头大小+颜色表大小
// (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小)
DWORD dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPBYTE)lpBI);
// 计算图像大小
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
{
// 对于RLE位图,没法计算大小,只能信任biSizeImage内的值
dwDIBSize += lpBI->biSizeImage;
}
else
{
// 大小为Width * Height
DWORD dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
// 计算出DIB真正的大小
dwDIBSize += dwBmBitsSize;
// 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的)
lpBI->biSizeImage = dwBmBitsSize;
}
// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
// 两个保留字
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + PaletteSize((LPBYTE)lpBI);
// 尝试写文件
TRY
{
// 写文件头
file.Write((LPBYTE)&bmfHdr, sizeof(BITMAPFILEHEADER));
// 写DIB头和象素
file.Write(lpBI, dwDIBSize);
}
CATCH (CFileException, e)
{
// 解除锁定
::GlobalUnlock((HGLOBAL) hDib);
// 抛出异常
THROW_LAST();
}
END_CATCH
// 解除锁定
::GlobalUnlock((HGLOBAL) hDib);
// 返回TRUE
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* ReadDIBFile()
*
* 参数:
* CFile& file - 要读取的文件文件CFile
*
* 返回值:
* HDIB - 成功返回DIB的句柄,否则返回NULL。
*
* 说明:
* 重指定文件中读取DIB对象
*
*************************************************************************/
HDIB CDIB::ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
HDIB hDIB;
LPBYTE lpDIB;
// 获取DIB(文件)长度(字节)
DWORD dwBitsSize = file.GetLength();
// 尝试读取DIB文件头
if (file.Read((LPBYTE)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
{
// 大小不对,返回NULL。
return NULL;
}
// 判断是否是DIB对象,检查头两个字节是否是"BM"
if (bmfHeader.bfType != DIB_HEADER_MARKER)
{
// 非DIB对象,返回NULL。
return NULL;
}
// 为DIB分配内存
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
if (hDIB == 0)
{
// 内存分配失败,返回NULL。
return NULL;
}
// 锁定
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 读象素
if (file.Read(lpDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
dwBitsSize - sizeof(BITMAPFILEHEADER) )
{
// 大小不对。
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 释放内存
::GlobalFree((HGLOBAL) hDIB);
// 返回NULL。
return NULL;
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回DIB句柄
return hDIB;
}
/*************************************************************************
*
* 函数名称:
* SetRgnColor()
*
* 参数:
* HDIB hDIB - 要读取的文件
* CRect rect - 设置的矩形区
* COLORREF col - 填充的颜色
*
* 返回值:
* 无返回值
*
* 说明:
* 该函数用指定的颜色填充指定的区域
*
*************************************************************************/
void CDIB::SetRgnColor(HDIB hDIB, CRect rect, COLORREF col)
{
// 循环变量
LONG i;
LONG j;
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = FindDIBBits(lpDIB);
// DIB的宽度
LONG lWidth = DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 对区域进行颜色填充
for (i = lHeight - rect.bottom; i < lHeight - rect.top; i++)
{
for (j = rect.left * 3; j < rect.right * 3; j++)
{
*(unsigned char *)(lpDIBBits + lLineBytes * i + j) = GetBValue(col);
j++;
*(unsigned char *)(lpDIBBits + lLineBytes * i + j) = GetGValue(col);
j++;
*(unsigned char *)(lpDIBBits + lLineBytes * i + j) = GetRValue(col);
}
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
}
/*************************************************************************
*
* 函数名称:
* SetCircleColor()
*
* 参数:
* HDIB hDIB - 要读取的文件
* CRect rect - 设置的矩形区
* COLORREF col - 填充的颜色
*
* 返回值:
* 无返回值
*
* 说明:
* 该函数用指定的颜色填充指定的圆形区域
*
*************************************************************************/
void CDIB::SetCircleColor(HDIB hDIB, CRect rect, COLORREF col)
{
// 循环变量
LONG i;
LONG j;
// 指向DIB的指针
LPBYTE lpDIB;
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB图像象素起始位置
lpDIBBits = FindDIBBits(lpDIB);
// DIB的宽度
LONG lWidth = DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = DIBHeight(lpDIB);
// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 中间变量
int cx, cy, dr;
// 对圆形区域进行颜色填充
for (i = lHeight - rect.bottom; i < lHeight - rect.top; i++)
{
for (j = rect.left; j < rect.right; j ++)
{
cx = abs(j - rect.left - 8);
cy = abs(i - lHeight + rect.bottom - 8);
dr = cx * cx + cy * cy;
if (dr > 64 || i < 0 || i > lHeight || j < 0 || j > lWidth)
continue;
*(unsigned char *)(lpDIBBits + lLineBytes * i + j * 3) = GetBValue(col);
*(unsigned char *)(lpDIBBits + lLineBytes * i + j * 3 + 1) = GetGValue(col);
*(unsigned char *)(lpDIBBits + lLineBytes * i + j * 3 + 2) = GetRValue(col);
}
}
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
}
HDIB CDIB:: XTo256(HDIB hDIB)
{
if(hDIB==NULL) return NULL;
//DIB 信息头指针
LPBITMAPINFOHEADER pOldBIH,pNewBIH;
//DIB指针
LPBYTE lpbi_Old,lpbi_New;;
//像素指针
LPBYTE lpDIBBits_Old,lpDIBBits_New;
//调色板指针
RGBQUAD *pOldPalette,*pNewPalette;
//辅助变量
DWORD dwLen=0;//
LONG x,y;
//锁定旧内存,指针设定
lpbi_Old=(LPBYTE)::GlobalLock((HGLOBAL)hDIB);
pOldBIH=(LPBITMAPINFOHEADER)lpbi_Old;
pOldPalette=(RGBQUAD*)(lpbi_Old+sizeof(BITMAPINFOHEADER));
lpDIBBits_Old=(LPBYTE)pOldBIH+sizeof(BITMAPINFOHEADER)+PaletteSize(lpbi_Old);
//获取原图像字节行宽度和转换后的8位256色灰度图像的字节宽度
LONG nOldWidthBytes,nNewWidthBytes;
nOldWidthBytes=WIDTHBYTES((pOldBIH->biWidth *pOldBIH->biBitCount)) ;
nNewWidthBytes=WIDTHBYTES(pOldBIH->biWidth *8);
//计算总分配内存
dwLen=sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)+(pOldBIH->biHeight)*nNewWidthBytes;
//分配内存
HDIB hNewDIB=(HDIB)::GlobalAlloc(GHND,dwLen);
//分配不成功,返回
if(hNewDIB==NULL)
{
AfxMessageBox("分配内存不成功!");
return NULL;
}
//锁定新内存,并设定指针
lpbi_New=(LPBYTE)::GlobalLock((HGLOBAL)hNewDIB);
pNewBIH=(LPBITMAPINFOHEADER)lpbi_New;
pNewPalette=(RGBQUAD*)(lpbi_New+sizeof(BITMAPINFOHEADER));
lpDIBBits_New=lpbi_New+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD);
//位图信息头赋值
*pNewBIH=*pOldBIH;
pNewBIH->biBitCount =8;
pNewBIH->biClrUsed =0;
pNewBIH->biSizeImage =nNewWidthBytes*pOldBIH->biHeight;
//调色板项赋值
for(int i=0;i<256;i++)
{
pNewPalette[i].rgbRed=i;
pNewPalette[i].rgbGreen=i;
pNewPalette[i].rgbBlue=i;
pNewPalette[i].rgbReserved=0;
}
//像素拷贝
RGBQUAD RGB;
unsigned char Gray;
switch(pOldBIH->biBitCount){
case 1:
AfxMessageBox("位深度:1");
for( y=0;y<pOldBIH->biHeight;y++)
{
for( x=0;x<pOldBIH->biWidth;x++)//处理一行
{
RGB=pOldPalette[(lpDIBBits_Old[y*nOldWidthBytes+x/8]>>(x%8))&1];
Gray=GRAY(RGB);
lpDIBBits_New[x+y*nNewWidthBytes]=Gray;
}
}
break;
case 4:
AfxMessageBox("位深度:4");
for( y=0;y<pOldBIH->biHeight;y++)
{
for( x=0;x<pOldBIH->biWidth;x++)//处理一行
{
RGB=pOldPalette[
(lpDIBBits_Old[y*nOldWidthBytes+x/2]>>(x%2))&15];
Gray=GRAY(RGB);
lpDIBBits_New[x+y*nNewWidthBytes]=Gray;
}
}
break;
case 8:
AfxMessageBox("位深度:8");
for(y=0;y<pOldBIH->biHeight;y++)
{
for( x=0;x<pOldBIH->biWidth;x++)//处理一行
{
RGB=pOldPalette[lpDIBBits_Old[x+y*nOldWidthBytes]];
Gray=GRAY(RGB);
lpDIBBits_New[x+y*nNewWidthBytes]=Gray;
}
}
break;
case 16:
AfxMessageBox("位深度:16");
for( y=0;y<pOldBIH->biHeight;y++)
{
for( x=0;x<pOldBIH->biWidth;x++)//处理一行
{
RGB.rgbRed =(lpDIBBits_Old[y*nOldWidthBytes+2*x+1]>>3)&31*8; //RED
RGB.rgbGreen =((lpDIBBits_Old[y*nOldWidthBytes+2*x]>>5)&7)| //GREEn_low
((lpDIBBits_Old[y*nOldWidthBytes+2*x+1]<<3)&28)*4; //GREEN_high
RGB.rgbBlue =lpDIBBits_Old[y*nOldWidthBytes+2*x]&31*8; //BLUE
Gray=GRAY(RGB);
lpDIBBits_New[x+y*nNewWidthBytes]=Gray;
}
}
break;
case 24:
AfxMessageBox("位深度:24");
for( y=0;y<pOldBIH->biHeight;y++)
{
for( x=0;x<pOldBIH->biWidth;x++)//处理一行
{
RGB.rgbRed =lpDIBBits_Old[y*nOldWidthBytes+3*x+2]; //RED
RGB.rgbGreen =lpDIBBits_Old[y*nOldWidthBytes+3*x+1];//GREEN
RGB.rgbBlue =lpDIBBits_Old[y*nOldWidthBytes+3*x]; //BLUE
Gray=GRAY(RGB);
lpDIBBits_New[x+y*nNewWidthBytes]=Gray;
}
}
break;
case 32:
AfxMessageBox("32");
for(y=0;y<pOldBIH->biHeight ;y++)
{
for(x=0;x<pOldBIH->biWidth ;x++)
{
RGB.rgbRed =lpDIBBits_Old[y*nOldWidthBytes+4*x]; //RED
RGB.rgbGreen =lpDIBBits_Old[y*nOldWidthBytes+4*x+1]; //GREEN
RGB.rgbBlue =lpDIBBits_Old[y*nOldWidthBytes+4*x+2]; //BLUE
Gray=GRAY(RGB);
lpDIBBits_New[x+y*nNewWidthBytes]=Gray;
}
}
break;
default:
AfxMessageBox("other");
break;
}
::GlobalUnlock((HGLOBAL)hDIB);
return hNewDIB;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -