📄 dib.cpp
字号:
// DIB.cpp: implementation of the CDIB class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Test.h"
#include "DIB.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDIB::CDIB()
{
m_hDIB=NULL;
m_sizeDIB=CSize(0,0);
m_pPal=NULL;
}
CDIB::~CDIB()
{
if(m_hDIB!=NULL)//删除存储图像的区域
::GlobalFree((HGLOBAL)m_hDIB);
if(m_pPal!=NULL)
delete m_pPal;
}
CDIB::CDIB(LPCTSTR lpPathName)
{
m_hDIB=CreateDIB(lpPathName);
if(m_hDIB==NULL)
{
MessageBox(NULL,"构造DIB类失败!",NULL,MB_OK);
m_sizeDIB=CSize(0,0);
m_pPal=NULL;
}
else
{
LPSTR _lpDIB=(LPSTR)::GlobalLock((HGLOBAL)m_hDIB);
m_sizeDIB=GetDIBSize(_lpDIB);
::GlobalUnlock((HGLOBAL)m_hDIB);
m_pPal=new CPalette;
//if(!CreateDIBPalette(m_hDIB,m_pPal))
//{
// delete m_pPal; m_pPal=NULL;
//}
CreateDIBPalette(m_hDIB,m_pPal);
delete m_pPal; m_pPal=NULL;
}
}
HDIB CDIB::ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
HDIB hDIB;
LPSTR pDIB;
dwBitsSize=file.GetLength();
if(file.Read((LPSTR)&bmfHeader,sizeof(bmfHeader))!=sizeof(bmfHeader))
{return NULL;}
if(bmfHeader.bfType!=DIB_HEADER_MARKER)
{return NULL;}
hDIB=(HDIB)::GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,dwBitsSize-sizeof(BITMAPFILEHEADER));
if(hDIB==0)
return NULL;
pDIB=(LPSTR)::GlobalLock((HGLOBAL)hDIB);
if(file.ReadHuge(pDIB,dwBitsSize-sizeof(BITMAPFILEHEADER))!=dwBitsSize-sizeof(BITMAPFILEHEADER))
{
::GlobalUnlock((HGLOBAL)hDIB);
::GlobalFree((HGLOBAL)hDIB);
return NULL;
}
::GlobalUnlock((HGLOBAL)hDIB);
return hDIB;
}
HDIB CDIB::CreateDIB(LPCTSTR lpPathName)
{
HDIB _hDIB;
CFile file;
CFileException fe;
if(!file.Open(lpPathName,CFile::modeRead|CFile::shareDenyWrite,&fe))
{
// ReportSaveLoadException(lpPathName,&fe,FALSE,AFX_IDP_FAILED_TO_OPEN_DOC);
//_hDIB=NULL;
return NULL;
}
TRY{
_hDIB=ReadDIBFile(file);
}
CATCH(CFileException,eLoad)
{
file.Abort();
_hDIB=NULL;
// return ;
}
END_CATCH
return _hDIB;
}
CSize CDIB::GetDIBSize(LPSTR lpDIB)
{
LPBITMAPINFOHEADER lpbmi;
LPBITMAPCOREHEADER lpbmc;
lpbmi=(LPBITMAPINFOHEADER)lpDIB;
lpbmc=(LPBITMAPCOREHEADER)lpDIB;
if(IS_WIN30_DIB(lpDIB))
{
return CSize((int)lpbmi->biWidth,(int)lpbmi->biHeight);
}
else
{
return CSize((int)lpbmc->bcWidth,(int)lpbmc->bcHeight);
}
}
WORD CDIB::NumColors(LPSTR lpbi)
{
WORD wBitCount;
WORD wNumCol;
if(IS_WIN30_DIB(lpbi))
{
DWORD dwClrUsed;
dwClrUsed=((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
if(dwClrUsed!=0)
return (WORD)dwClrUsed;
}
if(IS_WIN30_DIB(lpbi))
wBitCount=((LPBITMAPINFOHEADER)lpbi)->biBitCount;
else
wBitCount=((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
switch(wBitCount)
{
case 1:
wNumCol=2;
break;
case 4:
wNumCol=16;
break;
case 8:
wNumCol=256;
break;
default:
wNumCol=0;
}
return wNumCol;
}
BOOL CDIB::CreateDIBPalette(HDIB hDIB, CPalette *cPal)
{
LPLOGPALETTE lpPal;//指针,指向逻辑调色板
HANDLE hLogPal;//调色板句柄
int i;
WORD wNumColors;
LPSTR lpbi;//DIB指针
LPBITMAPINFO lpbmi;//BITMAPINFO结构指针,书中好像没有介绍这个结构,可以直接把DIB对象的指针赋给它
LPBITMAPCOREINFO lpbmc;
BOOL bResult=FALSE;
if(hDIB==NULL)
return FALSE;
lpbi=(LPSTR)::GlobalLock((HGLOBAL)hDIB);
lpbmi=(LPBITMAPINFO)lpbi;
lpbmc=(LPBITMAPCOREINFO)lpbi;
wNumColors=NumColors(lpbi);
if(wNumColors!=0){
hLogPal=::GlobalAlloc(GHND,sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*wNumColors);
if(hLogPal==0)
{
::GlobalUnlock((HGLOBAL)hDIB);
return FALSE;
}
lpPal=(LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal);
lpPal->palVersion=PALVERSION;
lpPal->palNumEntries=(WORD)wNumColors;
if(IS_WIN30_DIB(lpbi)){
for(i=0;i<(int)wNumColors;i++){
lpPal->palPalEntry[i].peRed=lpbmi->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen=lpbmi->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue=lpbmi->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peFlags=0;
}
}
else{
for(i=0;i<(int)wNumColors;i++){
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;
}
}//end else
bResult=cPal->CreatePalette(lpPal);
::GlobalUnlock((HGLOBAL)hLogPal);
::GlobalFree((HGLOBAL)hLogPal);
}
::GlobalUnlock((HGLOBAL)hDIB);
return bResult;
}
HDIB CDIB::GetHDIB() const
{
return m_hDIB;
}
BOOL CDIB::PaintDIB(HDC hDC, LPRECT lpDCRect)
{
CRect rcDIB;
rcDIB.left=0; rcDIB.top=0; rcDIB.right=m_sizeDIB.cx; rcDIB.bottom=m_sizeDIB.cy;
BOOL bSuccess=FALSE;
LPSTR lpDIBHdr; //信息头
LPSTR lpDIBBits; //图像起始位置
HPALETTE hPal=NULL;//DIB调色板句柄
HPALETTE hOldPal=NULL;
if(m_hDIB==NULL)
return FALSE;
lpDIBHdr=(LPSTR)::GlobalLock((HGLOBAL)m_hDIB);
lpDIBBits=FindDIBBits(lpDIBHdr);
if(m_pPal!=NULL)
{
hPal=(HPALETTE)m_pPal->m_hObject;
hOldPal=::SelectPalette(hDC,hPal,TRUE);//全局函数,将当前环境hDC赋予新的调色板,并返回以前的调色板
}
::SetStretchBltMode(hDC,COLORONCOLOR);
if((RECTWIDTH(lpDCRect)==m_sizeDIB.cx)&&(RECTHEIGHT(lpDCRect)==m_sizeDIB.cy))//目标区域和源区域相同,调用全局函数SetDIBitsToDevice
bSuccess=::SetDIBitsToDevice(hDC,lpDCRect->left,lpDCRect->top,RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),rcDIB.left,rcDIB.top,0,m_sizeDIB.cy,lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS);
else //目标区域与源区域不同时,进行缩放,调用全局函数StretchDIBits
bSuccess=::StretchDIBits(hDC,lpDCRect->left,lpDCRect->top,RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),rcDIB.left,rcDIB.top,m_sizeDIB.cx,m_sizeDIB.cy,lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS,SRCCOPY);
::GlobalUnlock((HGLOBAL)m_hDIB);
if(hOldPal!=NULL)
::SelectPalette(hDC,hOldPal,TRUE);
return bSuccess;
}
//计算DIB对象的象素的起始位置,并返回其指针
LPSTR CDIB::FindDIBBits(LPSTR lpbi)
{
return (lpbi+*(LPWORD)lpbi+PaletteSize(lpbi));//*(LPWORD)lpbi为信息头的一个元素,即biSize,表示本信息头的长度
}
WORD CDIB::PaletteSize(LPSTR lpbi)
{
if(IS_WIN30_DIB(lpbi)){
return (WORD)(NumColors(lpbi)*sizeof(RGBQUAD));
}
else{
return (WORD)(NumColors(lpbi)*sizeof(RGBTRIPLE));
}
}
CSize CDIB::GetDIBSize()
{
return m_sizeDIB;
}
//根据pDIB及其中的一个子区域构造一个子图像类
CDIB::CDIB(CDIB* pDIB, int _left, int _top, int _right, int _bottom)
{
int _width,_height,i,j,m,n;
_width=_right-_left;
_height=_bottom-_top;
int _widthBytes=WIDTHBYTES(8*_width);
int srcWidth=pDIB->GetDIBSize().cx;
int srcHeight=pDIB->GetDIBSize().cy;
int srcwidthBytes=WIDTHBYTES(8*srcWidth);
LPSTR lpbi,destLpbi;
unsigned char* destImage, * srcImage;
LPBITMAPINFOHEADER lpbmi,destLpbmi;
HDIB _hDIB;
if(!((_left>=0)&&(_right<=srcWidth)&&(_top>=0)&&(_bottom<=srcHeight)))
{
MessageBox(NULL,"子图像的边界定义出错!",NULL,MB_OK);
SetEmpty();
return;
}
_hDIB=pDIB->GetHDIB();
lpbi=(LPSTR)::GlobalLock((HGLOBAL)_hDIB);
if(NumColors(lpbi)!=256)//仅支持对256色位图提取子位图
{
MessageBox(NULL,"仅支持256位图!",NULL,MB_OK);
::GlobalUnlock((HGLOBAL)_hDIB);
SetEmpty();
return;
}
if(!IS_WIN30_DIB(lpbi))
{
MessageBox(NULL,"仅支持WIN30位图!",NULL,MB_OK);
::GlobalUnlock((HGLOBAL)_hDIB);
SetEmpty();
return;
}
WORD _paletteSize=pDIB->PaletteSize(lpbi);
// m_hDIB=(HDIB)::GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(BITMAPINFOHEADER)+_paletteSize+_widthBytes*_height);
m_hDIB=(HDIB)::GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,*(LPWORD)lpbi+_paletteSize+_widthBytes*_height);
if(m_hDIB==NULL)
{
::GlobalUnlock((HGLOBAL)_hDIB);
SetEmpty();
return;
}
destLpbi=(LPSTR)::GlobalLock((HGLOBAL)m_hDIB);
::memcpy(destLpbi,lpbi,sizeof(BITMAPINFOHEADER)+_paletteSize);
destLpbmi=(LPBITMAPINFOHEADER)destLpbi;
lpbmi=(LPBITMAPINFOHEADER)lpbi;
destLpbmi->biBitCount=8;
destLpbmi->biClrUsed=256;
destLpbmi->biHeight=_height;
destLpbmi->biWidth=_width;
destLpbmi->biSizeImage=_widthBytes*_height;
destImage=(unsigned char*)FindDIBBits(destLpbi);
srcImage=(unsigned char*)FindDIBBits(lpbi);
for(j=_top,n=_height-1;j<_bottom;j++,n--)
for(i=_left,m=0;i<_right;i++,m++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -