📄 dib.cpp
字号:
// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Dib.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_SERIAL(CDib,,CObject,1);
CDib::CDib()
{
m_hDib=NULL;
m_pPalette=NULL;
m_pBitmap=NULL;
}
CDib::~CDib()
{
Destroy();
if(m_pBitmap!=NULL)
{
delete m_pBitmap;
m_pBitmap=NULL;
}
if(m_pPalette!=NULL)
{
delete m_pPalette;
m_pPalette=NULL;
}
}
//create default empty DIB use system palette
BOOL CDib::Create(DWORD dwWidth, DWORD dwHeight)
{
HDIB hDib=CreateDefaultDIB(dwWidth,dwHeight);
if(!hDib)
return FALSE;
Destroy();
m_hDib=hDib;
return UpdateInternal();
}
//create default empty DIB
BOOL CDib::Create(DWORD dwWidth, DWORD dwHeight, WORD wBitCount)
{
HDIB hDib=CreateDIB(dwWidth,dwHeight,wBitCount);
if(!hDib)
return FALSE;
Destroy();
m_hDib=hDib;
return UpdateInternal();
}
//create default DIB from DIB data block
//根据内存指针,创建图像内存块句柄
BOOL CDib::Create(LPBYTE lpDIB)
{
if(lpDIB==NULL)
return FALSE;
//计算内存块大小
DWORD dwSize=DIBLockSize(lpDIB);
//分配内存
HDIB hDib=GlobalAlloc(GHND,dwSize);
//check that DIB handle is valid
if(!hDib)
return FALSE;
//内存锁定
LPBYTE lpbi=(LPBYTE)GlobalLock(hDib);
if(!lpbi)
return FALSE;
//内存复制(内存块一样,但类型不一样)
CopyMemory(lpbi,lpDIB,dwSize);
GlobalUnlock(hDib);
//如果m_hDib已指向某个内存块,销毁
Destroy();
//指定成员变量的内存块(注意重新分配了内存)
m_hDib=hDib;
return UpdateInternal();
}
//create DIB from DIB data block
BOOL CDib::Create(LPBYTE lpDIB, WORD wBitCount)
{
if(lpDIB==NULL)
return FALSE;
if(!Create(lpDIB))
return FALSE;
WORD wBits=((LPBITMAPINFOHEADER)lpDIB)->biBitCount ;
if(!wBitCount==wBits)
return FALSE;
HDIB hNewDib=ConvertDIBFormat(m_hDib,wBitCount,NULL);
if(!hNewDib)
return FALSE;
Destroy();
m_hDib=hNewDib;
return UpdateInternal();
}
//create default DIB from DIBSECTION data block
BOOL CDib::Create(HBITMAP hBitmap)
{
if (!hBitmap)
return FALSE;
HDIB hDib=DIBSectionToDIB(hBitmap);
if(!hDib)
return FALSE;
Destroy();
m_hDib=hDib;
return UpdateInternal();
}
//create DIB from DDB data block
BOOL CDib::Create(HBITMAP hBitmap, WORD wBitCount)
{
if (!hBitmap)
return FALSE;
HDIB hDib=DIBSectionToDIB(hBitmap);
if(!hDib)
return FALSE;
DIBSECTION ds;
HDIB hNewDib;
GetObject(hBitmap,sizeof(DIBSECTION),&ds);
if(wBitCount==ds.dsBmih .biBitCount )
hNewDib=hDib;
else
{
hNewDib=ConvertDIBFormat(hDib,wBitCount,NULL);
//cleanup hDib
GlobalFree(hDib);
}
if(!hNewDib)
return FALSE;
Destroy();
m_hDib=hNewDib;
return UpdateInternal();
}
//create DIB from DDB and given palette
BOOL CDib::Create(HBITMAP hBitmap, HPALETTE hPalette)
{
if (!hBitmap)
return FALSE;
if(!hPalette)
return FALSE;
HDIB hDib=BitmapToDIB(hBitmap,hPalette);
if(!hDib)
return FALSE;
Destroy();
m_hDib=hDib;
return UpdateInternal();
}
//create DIB from DDB and given palette
BOOL CDib::Create(HBITMAP hBitmap, HPALETTE hPalette, WORD wBitCount)
{
if (!hBitmap)
return FALSE;
if(!hPalette)
return FALSE;
HDIB hDib=BitmapToDIB(hBitmap,hPalette,wBitCount);
if(!hDib)
return FALSE;
Destroy();
m_hDib=hDib;
return UpdateInternal();
}
//create DIB from given CRect
BOOL CDib::Create(CRect rcScreen)
{
HDIB hDib=CopyScreenToDIB(rcScreen);
if(!hDib)
return FALSE;
Destroy();
m_hDib=hDib;
return UpdateInternal();
}
//create DIB from given window
BOOL CDib::Create(HWND hWnd, WORD fPrintArea)
{
HDIB hDib=CopyWindowToDIB(hWnd,fPrintArea);
if(!hDib)
return FALSE;
Destroy();
m_hDib=hDib;
return UpdateInternal();
}
//create DIB from given window and area
BOOL CDib::Create(HWND hWnd, CRect rcClientArea)
{
HDIB hDib=CopyClientRectToDIB(hWnd,rcClientArea);
if(!hDib)
return FALSE;
Destroy();
m_hDib=hDib;
return UpdateInternal();
}
// connect the resource number with the DIB
BOOL CDib::Attach(HDIB hDib)
{
if(!hDib)
return FALSE;
Destroy();
m_hDib=hDib;
return UpdateInternal();
}
//create DIB from given resource Number
BOOL CDib::Load(UINT uIDS, LPCTSTR lpszDibType)
{
LPCSTR lpszDibRes=MAKEINTRESOURCE(uIDS);
return Load(lpszDibRes,lpszDibType);
}
//Create DIB from given resource name
BOOL CDib::Load(LPCTSTR lpszDibRes, LPCTSTR lpszDibType)
{
HINSTANCE hInst=AfxGetInstanceHandle();
HRSRC hRes=::FindResource (hInst,lpszDibRes,lpszDibType);
HGLOBAL hData=::LoadResource (hInst,hRes);
//if resource ok?
if(hRes==NULL||hData==NULL)
return FALSE;
//get resource buffer
LPBYTE lpBuf=(LPBYTE)::LockResource (hData);
//is DIB?
if(((LPBITMAPFILEHEADER)lpBuf)->bfType !=DIB_HEADER_MARKER)
return FALSE;
//use this buffer to create CDib
LPBYTE lpDIB=lpBuf+sizeof(BITMAPFILEHEADER);
return Create(lpDIB);
}
//create DIB from given file name
BOOL CDib::Load(LPCTSTR lpszDibFile)
{
try
{
CFile file(lpszDibFile,CFile::modeRead|CFile::shareDenyNone);
if(!Read(&file))
return FALSE;
}
catch(CException e)
{
return FALSE;
}
return TRUE;
}
BOOL CDib::Save(LPCTSTR lpszDibFile)
{
try
{
CFile file(lpszDibFile,CFile::modeCreate|CFile::modeWrite);
if(!Write(&file))
return FALSE;
}
catch(CException e)
{
return FALSE;
}
return TRUE;
}
//Read a DIB file
BOOL CDib::Read(CFile *pFile)
{
//改变鼠标形状
SetCursor(LoadCursor(NULL,IDC_WAIT));
//位图信息头
LPBITMAPINFOHEADER lpbi;
LPBYTE lpBI;
DWORD dwSize;
HDIB hDIB;
//位图文件头
BITMAPFILEHEADER bmfHdr;
try
{
//read DIB file header
//读位图文件头
int nSize=sizeof(BITMAPFILEHEADER);
pFile->Read ((LPBYTE)&bmfHdr,nSize);
//IS DIB file?
//判断是否BMP图像
if(bmfHdr.bfType !=DIB_HEADER_MARKER ) //"BM"
{
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
//纠正错误的文件长度信息
DWORD dwLength=pFile->GetLength ();
if(bmfHdr.bfSize !=dwLength)
bmfHdr.bfSize =dwLength;
//read DIB INFO
//计算剩余的文件大小(除位图文件头外)
dwSize=bmfHdr.bfSize -sizeof(BITMAPFILEHEADER);
//sizeof(BITMAPINFOHEADER);
//分配内存空间,返回内存句柄
hDIB=GlobalAlloc(GHND,dwSize);
//锁定内存句柄
lpBI=(LPBYTE)GlobalLock(hDIB);
//读剩余的数据
DWORD dwCount=pFile->ReadHuge (lpBI,dwSize);
//read ok?
//判断是否正常读取(和预计的大小是否相同)
if(dwCount!=dwSize)
{
GlobalUnlock(hDIB);
GlobalFree(hDIB);
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
//解析最前面的位图信息头
lpbi=(LPBITMAPINFOHEADER)lpBI;
//check to see if it's a window DIB
//判断位图信息头是否和预计的相同
if(lpbi->biSize !=sizeof(BITMAPINFOHEADER))
{
GlobalUnlock(hDIB);
GlobalFree(hDIB);
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
//FILL COLOR NUM ITEM
//检查图像颜色数目字段(可能没有填写)
int nNumColors=(UINT) lpbi->biClrUsed ;
if(nNumColors==0)
{
//no color table for 24-bits default size otherwise
//根据每像素的位数,计算颜色数目
if(lpbi->biBitCount !=24)
nNumColors=1<<lpbi->biBitCount ;
}
//fill in some default values if they are zero
//填上可能没有填充的内容
if(lpbi->biClrUsed ==0)
lpbi->biClrUsed =nNumColors;
if(lpbi->biSizeImage ==0)
//计算图像字节大小,注意4个字节补齐
lpbi->biSizeImage =
((((lpbi->biWidth *(DWORD)lpbi->biBitCount )
+31)&~31)>>3)*lpbi->biHeight ;
}
//异常处理
catch(CException e)
{
GlobalUnlock(hDIB);
GlobalFree(hDIB);
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
//create CDib with DIB buffer
BOOL bSuccess;
//创建图像内存块句柄
bSuccess=Create(lpBI);
GlobalFree(lpBI);
//恢复鼠标形状
SetCursor(LoadCursor(NULL,IDC_ARROW));
//恢复文件头指针
pFile->SeekToBegin ();
return bSuccess;
}
BOOL CDib::Write(CFile *pFile)
{
SetCursor(LoadCursor(NULL,IDC_WAIT));
BITMAPFILEHEADER bmfHdr;//header for bitmap file
LPBITMAPINFOHEADER lpbi;//pointer to DIB info structure
DWORD dwDIBSize;
//get the pointer to the DIB memory
lpbi=(LPBITMAPINFOHEADER)GlobalLock(m_hDib);
if(!lpbi)
{
GlobalUnlock(m_hDib);
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
//check to see if it's a window DIB
if(lpbi->biSize !=sizeof(BITMAPINFOHEADER))
{
GlobalUnlock(m_hDib);
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
//Fill in the fields of the file header
//Fill in the file type (first 2bytes must be "BM" for
//a Bitmap
bmfHdr.bfType =DIB_HEADER_MARKER;//"BM"
//calculating the size of the DIB is a bit trickly(if we want to
// do it right).The easiest way to do this is to call GlobalSize()
// on our global handle, but since the size of our global memory
//may have been padded a few bytes, we may end uup writing out a
//few too many bytes to the file(which may vause problems with
//some apps,like HC 3.0
// so Instead let's calculate the size manually
//To do this ,find size of Header Plus size of Color table,Since
//the first DWORD in both BITMAPINFOHEADER and
//BITMAPCOREHEADER contains the size of the structure, let's use
//this
//partial calculation
dwDIBSize=*(LPDWORD)lpbi+PaletteSize((LPBYTE)lpbi);
//Now calculate the size of the image
//It's an RLE butmap,we can't calculate size, so trust the
//biSizeImage field
if((lpbi->biCompression ==BI_RLE8)||
(lpbi->biCompression ==BI_RLE4))
dwDIBSize+=lpbi->biSizeImage ;
else
{
DWORD dwBmBitsSize;//Size of Bitmap Bits only
//It's not RLE,so size is width (DWORD aligned)*Height
dwBmBitsSize=WIDTHBYTES((lpbi->biWidth )*
((DWORD)lpbi->biBitCount ))*lpbi->biHeight ;
dwDIBSize+=dwBmBitsSize;
//Now since we have calculated the correct size,why don't
// fill in the biSizeImage field
lpbi->biSizeImage =dwBmBitsSize;
}
//calculate the file size by adding the DIB size to
//size of (BITMAPFILEHEADER)
bmfHdr.bfSize =dwDIBSize+sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1= 0;
bmfHdr.bfReserved2 =0;
//Now calculate the offset the actual bitmap bits will be in
// the file-- It's tje bitmap file header plus the DIB header
// plus the size of the color table
bmfHdr.bfOffBits =(DWORD)sizeof(BITMAPFILEHEADER)+
lpbi->biSize +PaletteSize((LPBYTE)lpbi);
//write the file header
try
{
pFile->Write (&bmfHdr,
sizeof(BITMAPFILEHEADER));
//write the DIB header and the bits--use local version of
//mywrite, so we can write more than 32767 bytes of data
pFile->WriteHuge(lpbi,dwDIBSize);
}
catch(CException e)
{
GlobalUnlock(m_hDib);
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
GlobalUnlock(m_hDib);
SetCursor(LoadCursor(NULL,IDC_ARROW));
return TRUE;
}
//destroy DIB and release memory
void CDib::Destroy()
{
if(m_hDib!=NULL)
{
DestroyDIB(m_hDib);
m_hDib=NULL;
}
}
//unconnect tje DIB and CDib object
HDIB CDib::Detach()
{
if(m_hDib==NULL)
return NULL;
HDIB hDib=m_hDib;
m_hDib=NULL;
if(m_pBitmap!=NULL)
{
delete m_pBitmap;
m_pBitmap=NULL;
}
if(m_pPalette!=NULL)
{
delete m_pPalette;
m_pPalette=NULL;
}
return hDib;
}
void CDib::Serialize(CArchive &ar)
{
CObject::Serialize (ar);
ar.Flush ();
if(ar.IsStoring ())
{
Write(ar.GetFile ());
}
else
{
Read(ar.GetFile ());
}
}
BOOL CDib::Display(CDC *pDC, int xDest, int yDest, int nWidthDest, int nHeightDest, int xSrc, int ySrc, DWORD dwRop)
{
CDC MemDC;
MemDC.CreateCompatibleDC (pDC);
CBitmap*pOldBmp=MemDC.SelectObject (m_pBitmap);
CPalette* pOldPal=pDC->SelectPalette (m_pPalette,TRUE);
pDC->RealizePalette ();
BOOL bSuccess=pDC->BitBlt (xDest,yDest,
nWidthDest,nHeightDest,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -