📄 dibapi.cpp
字号:
//************************************************************************************************************************
// 文件名:dibapi.cpp
//
//DIB(Independent Bitmap)API函数库:
//
//paintDIB() -绘制DIB对象
//CreateDIBPAlette() -创建DIB对象调色板
//FindDIBBits() -返回DIB图像像素起始位置
//DIBWidth() -返回DIB的宽度
//DIBHEIGHT() -返回DIB的高度
//PaletteSize() -返回DIB调色板的大小
//DIBNumColors() -计算DIB调色板颜色数目
//CopyHandle() -拷贝内存块
//
//SaveDIB() 将DIB保存到指定的文件中
//ReadDIBFile() 重指定文件中读取的DIB对象
//
//**************************************************************************************************************************
//#include"stdafx.h"
#include"dibapi.h"
#include"io.h"
#include"errno.h"
#include"math.h"
#include"direct.h"
/*
*Dib 文件头标志(字符串"BM",写DIB时用到该常数)
*/
#define DIB_HEADER_MARKER ((WORD)('M'<<8)|'B')
/****************************************************************************************************************************
*
*function:
* PaintDIB() -绘制DIB图像
*
*parameter:
* HDC hDC -输出设备DC
* LPRECT lpDCRECT -绘制矩形区域
* HDIB hDIB -指向DIB对象的指针
* LPRECT lpDIBRect -要输出的DIB区域
* CPalette* pPal -指向DIB对象调色板的指针
*
*return:
* BOLL -绘制成功返回TRUE,否则返回FALSE.
*
*comments:
*该函数注意用来绘制DIB对象。其中调用了StretchDIBits()或者
*SetDIBToDevice()来绘制DIB对象。输出的设备由参数hDC指定;
*绘制的矩形区域有参数lpDCRect指定;输出DIB的区域由参数
*lpDIBRect.
*
***************************************************************************************************************************/
BOOL WINAPI PaintDIB(HDC hDC,
LPRECT lpDCRect,
HDIB hDIB,
LPRECT lpDIBRect,
CPalette* pPal)
{
LPSTR lpDIBHdr; //BITMAPINFOHEADER 指针
LPSTR lpDIBBits; //DIB像素指针
BOOL bSuccess=FALSE; //成功的标志
HPALETTE hPal=NULL; //DIB调色板
HPALETTE hOldPal=NULL; //以前的调色板
//判断DIB对象是否为空
if(hDIB==NULL)
{
//return
return FALSE;
}
//Lock DIB
lpDIBHdr=(LPSTR)::GlobalLock((HGLOBAL)hDIB);
//find the section start of DIB image's pixel
lpDIBBits=::FindDIBBits(lpDIBHdr);
//Get DIB palette and chose it
if(pPal!=NULL)
{
hPal=(HPALETTE)pPal->m_hObject;
//Chose the palette
hOldPal=::SelectPalette(hDC,hPal,TRUE);
}
//Set the palette
::SetStretchBltMode(hDC,COLORONCOLOR);
//判断是调用StretchDIBits()还是SetDIBitsToDevice()来绘制DIB对象
if((RECTWIDTH(lpDCRect)==RECTWIDTH(lpDIBRect))&&(RECTHEIGHT(lpDCRect)==RECTHEIGHT(lpDIBRect)))
{
//原始大小,不用拉伸
bSuccess=::SetDIBitsToDevice(hDC, //hDC
lpDCRect->left, //DestX
lpDCRect->top, //DestY
RECTWIDTH(lpDCRect), //nDestWidth
RECTHEIGHT(lpDCRect), //nDestHeight
lpDIBRect->left, //SrcX
(int)DIBHeight(lpDIBHdr)-
lpDIBRect->top-
RECTHEIGHT(lpDIBRect), //SrcY
0, //nStartScane
(WORD)DIBHeight(lpDIBHdr), //nNumScans
lpDIBBits, //lpBits
(LPBITMAPINFO)lpDIBHdr, //lpBitInfo
DIB_RGB_COLORS); //wUsage
}
else
{
//非原始大小,拉伸。
bSuccess=::StretchDIBits(hDC, //hDC
lpDCRect->left, //DestX
lpCDRect->top, //DestY
RECTWIDTH(lpDCRect), //nDestWidth
RECTHEIGHT(lpDCRect), //nDestHeight
lpDIBRect->left, //SrcX
lfDIBRect->top, //SrcY
RECTWIDTH(lpDIBRect), //wSrcWidth
RECTHEIGHT(lpDIBRect), //wSrcHeight
lpDIBBits, //lpBits
(LPBITMAPINFO)lpDIBHdr, //lpBitsInfo
DIB_RGB_COLORS, //wUsage
SRCCOPY); //dwROP
}
//解除锁定
::GlobalUnlock((HGLOBAL)hDIB);
//恢复以前的调色板
if(hOldPal!=NULL)
{
::SelectPalette(hDC,hOldPal,TRUE);
}
//return
return bSuccess;
}
/*******************************************************************************************************************
*
*function:
* CreateDIBPalette() -创建DIB图像的调色板
*
*parameter:
* HDIB hDIB -指向DIB对象的句柄
* CPalette* pPal -指向DIB对象调色板的指针
*
*return:
* BOLL -创建成功返回TRUE,否则返回FALSE
*
*comments:
* 该函数按照DIB创建一个逻辑调色板,从DIB中读取颜色表并保存在调色板中,
*最后按照逻辑调色板创建一个新的调色板,并返回该调色板的句柄。这样可以
*用最后的颜色来显示DIB图像。
*
**********************************************************************************************************************/
BOOL WINAPI CreateDIBPalette(HDIB hDIB,CPalette* pPal)
{
//指向逻辑调色板的指针
LPLOGPALETTE lpPal;
//逻辑调色板的句柄
HANDLE hLogPal;
//调色板的句柄
HPALETTE hPal=NULL;
//循环变量
int i;
//颜色表中的数目
WORD wNumColors;
//指向DIB的指针
LPSTR lpbi;
//指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFO lpbmi;
//指向BITMAPCOREINFO结构的指针
LPBITMAPCOREINFO lpbmc;
//表明是否是Win3.0 DIB的标记
BOOL bWinStyleDIB;
//创建结果
BOOL bResult=FALSE;
//判断DIB是否为空
if(hDIB=NULL)
{
//返回FALSE
return FALSE;
}
//锁定DIB
lpbi=(LPSTR)::GlobalLock((HGLOBAL)hDIB);
//获取指向BITMAPINFO结构的指针(Win3.0)
lpbmi=(LPBITMAPINFO)lpbi;
//获取指向BITMAPCOREINFO结构的指针
lpbmc=(LPBITMAPCOREINFO)lpbi;
//获取DIB颜色表中的颜色数目
wNumColors=::DIBNumColors(lpmi);
if(wNumColors!=0)
{
//分配为逻辑调色板的内存
hLogPal=::GlobalAlloc(GHND,sizeof(LOGPATETTE)+
sizeof(PALETTEENTRY)
*wNumColors);
//如果内存不足,退出
if(hLogPal==0)
{
//解除锁定
::GlobalUnlock((HGLOBAL)hDIB);
//返回FALSE
return FALSE;
}
lpPal=(LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal);//由句柄转向指针
// 设置版本号
lpPal->palVersion=PALVERSION;
//设置颜色的数目
lpPal->palNumEntries=(WORD)wNumColors;
//判断是否是Win3.0的DIB
bWinStyleDIB=IS_WIN30_DIB(lpbi);
//读取调色板
for(i=0;i<(int)wNumColors;i++)
{
if(bWinStyleDIB)
{
//读取红色的分量
lpPal->palPalEntry[i].peRed=lpbmi->bmiColors[i].rgbRed;
//读取绿色的分量
lpPal->palPalEntry[i].peGreen=lpbmi->bmiColors[i].rgbGreen;
//读取蓝色的分量
lpPal->palPalEntry[i].peBlue=lpbmi->bmiColors[i].grbBlue;
//保留位
lpPal->palPalEntry[i].peFlags=0;
}
else
{
//读取红色的分量
lpPal->palPalEntry[i].peRed=lpbmc.bmciColors[i].rgbtRed;
//读取绿色的分量
lpPal->palPalEntry[i].peGreen=lpbmc.bmciColors[i].rgbtGreen;
//读取蓝色的分量
lpPal->palPalEntry[i].peBlue=lpbmc.bmciColors[i].rgbtBlue;
//保留位
lpPal->palPalEntry[i].peFlags=0;
}
}
//按照逻辑调色板创建调色板,并返回指针
bResult=pPal->CreatePalette(lpPal);
//解除锁定
::GlobalUnlock((HGLOBAL)hLogPal);
//释放调色板
::GlobalFree((HGLOBAL)hLogPal);
}
//解除锁定
::GlobalUnlock((HGLOBAL)hDIB);
//返回结果
return bResult;
}
/**************************************************************************************************************
*
*function:
* FindDIBBits() -找到DIB图像像素起始地址
*
*parameter:
* LPSTR lpbi -指向DIB对象的指针
*
*return:
* LPSTR -指向DIB图像像素的起始地址
*
*comments:
* 该函数计算DIB中图像像素的起始位置,并返回指向他的起始地址
*
************************************************************************************************************/
LPSTR WINAPI FindDIBBits(LPSTR lpbi)
{
return (lpbi+*(LPDWORD)lpbi+::PatetteSize(lpsi));
}
/***************************************************************************************************************
*function:
* DIBWidth()
*
*parameter:
* LPSTR lpbi
*
*return:
* DWORD
*
*comments:
* 该函数返回DIB中图像的宽度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER中的biWidth;
*对于其他返回BITMAPCOREHEADER中的bcWidth值。
*
************************************************************************************************************/
DWORD WINAPI DIBWidth(LPSTR lpbi)
{
//指向BITMAPINFO结构的指针(Windows 3.0)
LPBITMAPINFOHEADER lpbmi;
//指向BITMAPCOREINFO结构的指针
LPBITMAPCOREHEADER lpbmc;
//获取指针
lpbmi=(LPBITMAPINFOHEADER)lpbi;
lpbmc=(LPBITMAPCOREHEADER)lpbi;
//返回DIB中图像的宽度
if(IS_WIN30_DIB(lpbi))
{
//对于Windows 3.0 DIB 返回lpbmi->biWidth
return lpbmi->biWidth;
}
else
{
//对于其他格式的DIB,返回lpbmc->bcWidth
return lpbmc->bcWidth;
}
}
/***********************************************************************************************
*function:
* DIBHeight()
*
*parameter:
* LPSTR lpbi
*
*return:
* DWORD
*
*comments:
* 该函数返回DIB中的高度。对于Window 3.0 DIB ,返回BITMAPINFOHEADER
*中的biHeight值;对于其他返回BITMAPCOREHEADER中的bcHeight值。
*
*************************************************************************************************/
DWORD WINAPI DIBHeight(LPSTR lpbi)
{
//指向BITMAPINFO结构的指针(Windows 3.0)
LPBITMAPINFOHEADER lpbmi;
//指向BITMAPCOREINFO结构的指针
LPBITMAPCOREHEADER lpbmc;
//获取指针
lpbmi=(LPBITMAPINFOHEADER)lpbi;
lpbmc=(LPBITMAPCOREHEADER)lpbi;
//返回DIB中图像的宽度
if(IS_WIN30_DIB(lpbi))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -