📄 dibapi.cpp
字号:
//对于Windows 3.0 DIB 返回lpbmi->biHeight
return lpbmi->biHeight;
}
else
{
//对于其他格式的DIB,返回lpbmc->bcHeight
return lpbmc->bcHeight;
}
}
/************************************************************************************************************
*function:
* PaletteSize()
*
*parameter:
* LPSTR lpbi -指向DIB 图像的指针
*
*return:
* WORD -DIB 图像中调色板的大小
*
*comments:
* 该函数返回DIB中的调色板的大小。对于Windows 3.0 DIB ,返回颜色数目*
*RGBQUAD的大小;对于其他返回颜色数目*RGBTRIPLE的大小。
*
************************************************************************************************************/
WORD WINAPI PaletteSize(LPSTR lpbi)
{
//计算DIB中调色板的大小
if(IS_WIN30_DIB(lpbi))
{
//返回 颜色数目*RGBQUAD的大小
return (WORD)(::DIBNumColors(lpbi)*sizeof(RGBQUAD));
}
else
{
//返回 颜色数目*RGBTRIPLE的大小
return (WORD)(::DIBNumColors(lpbi)*sizeof(RGBTRIPLE));
}
}
/**************************************************************************************************************
*function:
* DIBNumColors()
*
*parameter:
* LPSTR lpbi -指向DIB对象的指针
*
*return:
* WORD -返回调色板中颜色的种数
*
*comments:
* 该函数返回DIB 中调色板的颜色的种数。对于单色位图,返回2;
*对于16色位图,返回16;对于256色位图,返回256;对于真彩色位图(24位),没有调色板的,返回0.
*
*************************************************************************************************************/
WORD WINAPI DIBNumColors(LPSTR lpbi)
{
DWORD wBitCount;
/*
对于Windows 3.0 DIB,实际颜色的数目可以比位数的数目要小
对于这种情况,则返回一个近似数。
*/
//判断是否是WIN3.0 DIB
if(IS_WIN30_DIB(lpbi))
{
DWORD dwClrUsed;
//读取dwClrUsed值
dwClrUsed=((BITMAPINFOHEADER)lpbi)->biClrUsed;
if(dwClrUsed !=0)
{
//如果dwClrUsed (实际用到的颜色数)不为0,直接返回改值
return (WORD)dwClrUsed;
}
}
//读取像素的位数
if(IS_WIN30_DIB(lpbi))
{
//读取biBitCount值
wBitCount=((LPBITMAPINFOHEADER)lpbi)->biBitCount;
}
else
{
//读取bcBitCount值
wBitCount=((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
}
//按照像素的位数计算颜色数目
switch(wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
/************************************************************************************************************
*
*funtion:
* CopyHandle()
*
*parameter:
* HGLOBAL h -要复制的内存区域
*
*return:
* HGOBAL -复制后的新内存区域
*
*comments:
* 该参数复制指定的内存区域。返回复制后的新内存区域,出错时返回0.
*
****************************************************************************************************************/
HGLOBAL WINAPI CopyHandle(HGLOABAL h)
{
if(h==NULL)
return NULL;
// 获取指定内存区域的大小
DWORD dwLen=::GlobalSize((HGLOBAL)h);
//分配新内存空间
HGLOBAL hCopy=::GlobalAlloc(GHND,dwLen);
//判断分配是否成功
if(hCopy!=NULL)
{
//Lock
void *lpCopy=::GlobalLock((HGLOBAL) hCopy);
void *lp =::GlobalLock((HGLOBAL) h);
//Copy
memcpy(lpCopy,lp,dwLen);
//解除锁定
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
}
return hCopy;
}
/**************************************************************************************************************
*function:
* SaveDIB()
*
*parameter:
* HDIB hDib
* CFile& file
*
*return:
* BOOL
*
*comments:
* 该函数指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。
*
*****************************************************************************************************************/
BOOL WINAPI SaveDIB(HDIB hDib,CFile& file)
{
//Bitmap 文件头
BITMAPFILEHEADER bmfHdr;
//指向BIPMAPINFOHEADER的指针
LPBITMAINFOHEADER lpBI;
//DIB 的大小
DWORD dwDIBSize;
if(hDib==NULL)
{
return FALSE;
}
//读取BITMAPINFO结构,并锁定
lpBI=(LPBITMAPINFOHEADER)::GlobalLock((HGLOBAL)hDib);
if(lpBI==NULL)
{
return FALSE;
}
if(!IS_WIN30_DIB(lpBI))
{
::GlobalUnlock((HGLOBAL)hDib);
return FALSE;
}
//填充文件头
//文件类型“BM”
bmfHdr.bfType=DIB_HEADER_MARKER;
/*计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并不是DIB 的真正的大小,
*它总是多几个字节。这样就需要计算一下DIB 的真实大小。
*
*文件头大小+颜色表大小
*(BITMAPINFOHEADER和BIPMAPCOREHEADER结构的第一个DWORD都是改结构的大小)*/
dwDIBSize=*(LPDWORD)lpBI+::PaletteSize(LPSTR)lpBI);
//计算图像的大小
if((lpBI->biCompression==BI_RLE8)||(lpBI->biCompression==BI_RLE4))
{
//对于RLE位图,没法计算大小,只能信任biSizeImage内的值
dwDIBSize+=lpBI->biSizeImage;
}
else
{
DWORD dwBmBitsSize;
//大小为Width*Height
dwBmBitsSize=WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount))*lpBI->biHeight;
//计算DIB真正的大小
dwDIBSize+=dwBmBitsSize;
//更新biSizeImage(很多BMP文件头中的biSizeImage的值是错误的)
lpBI->biSizeImage=dwBmBitsSize;
}
//计算文件大小,DIB(大小)+BIPMAPFILEHEADER结构的大小
bmfHdr.bfSize=dwDIBSize+sizeof(BITMAPFILEHEADER);
//两个保留字
bmfHdr.bfReserved1=0;
bmfHdr.bfReserved2=0;
//计算偏移量bfOffBits
bmfHdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+lpBI->biSize
+PaletteSize((LPSTR)lpBI);
//尝试写文件
TRY
{
//些写件头
file.Write((LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER));
//写DIB头和像素
file.WriteHuge(lpBI,dwDIBSize);
}
CATCH(CFileException, e)
{
::GlobalUnlock((HGLOBAL)hDib);
THROW_LAST();
}
END_CATCH
::GlobalUnlock((HGLOBAL)hDib);
return TRUE;
}
/**************************************************************************************************************
*
*function:
* ReadDIBFile()
*
*parameter:
* CFile& file
*
*return:
* HDIB
*
*comment:
* 该函数将指定的文件的DIB对象读到指定的区域中,除BIPMAPFILEHEADER
*外的内容都将被读入内存。
*
************************************************************************************************************/
HDIB WINAPI ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHdr;
DWORD dwBitsSize;
HDIB hDIB;
LPSTR pDIB;
//获取DIB(文件)长度
dwBitsSize=file.GetLength();
//尝试读取DIB文件头
if(file.Read((LPSTR)&bmfHdr,sizeof(bmfHdr))!=sizeof(BITMAPFILEHEADER))
{
//大小不对,返回NULL
return NULL;
}
//判断是否是DIB的对象,检查头俩个字节是不是“BM”
if(bmfHdr.bfType!=DIB_HEADER_MARKER)
{
//非DIB对象,返回NULL
return NULL;
}
//为DIB分配内存
hDIB=(HDIB)::GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,dwBitsSize);
if(hDIB==0)
{
//内存分配失败,返回NULL
return NULL;
}
pDIB=(LPSTR)::GlobalLock((HGLOBAL)hDIB);
if(file.ReadHuge(pDIB,dwBitsSize-sizeof(BIPMAPFILEHEADER))!=dwBitsSize-sizeof(BITMAPFILEHEADER))
{
//对象不对
::GlobalUnlock((HGLOBAL)hDIB);
::GolbalFree((HGLOBAL)hDIB);
return NULL;
}
::GlobalUnlock((HGLOBAL)hDIB);
return hDIB;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -