www.pudn.com > final_6.rar > Dib.cpp
// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CG.h"
#include "Dib.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDib::CDib()
{
m_pRGBQuad = NULL; //RGBQUAD 表项
m_pDibData = NULL; //位图像素数据
m_nWidth = 0; //宽度
m_nHeight = 0; //高度
m_nBitCount = 0; //每个像素占有的位数
m_nTotalColors = 0; //颜色总数
m_pBitmapInfoHeader = NULL;
m_hDIB = 0;
}
CDib::~CDib()
{
DeleteDIB();
m_pRGBQuad = NULL; //RGBQUAD 表项
m_pDibData = NULL; //位图像素数据
m_nWidth = 0; //宽度
m_nHeight = 0; //高度
m_nBitCount = 0; //每个像素占有的位数
m_nTotalColors = 0; //颜色总数
m_pBitmapInfoHeader = NULL;
m_hDIB = 0;
}
void CDib::DeleteDIB()
{
if (m_hDIB != NULL)
{
::GlobalFree((HGLOBAL) m_hDIB);
m_hDIB=NULL;
}
if (m_palDIB != NULL)
{
// delete m_palDIB;
}
}
BOOL CDib::Load(LPCTSTR lpszFileName)
{
HDIB hDIB;
CFile file;
CFileException fe;
if (!file.Open(lpszFileName, CFile::modeRead|CFile::shareDenyWrite, &fe))
{
AfxMessageBox(fe.m_cause);
return FALSE;
}
TRY
{
hDIB = ::ReadDIBFile(file);
}
CATCH (CFileException, eLoad)
{
file.Abort();
return FALSE;
}
END_CATCH
DeleteDIB(); //清除旧位图
m_hDIB=hDIB;
//获取位图文件头指针
BYTE* pbyDib = (BYTE*)::GlobalLock(m_hDIB);
m_pBitmapInfoHeader = (BITMAPINFOHEADER*) pbyDib;
//宽度和高度
m_nWidth = m_pBitmapInfoHeader->biWidth;
m_nHeight = m_pBitmapInfoHeader->biHeight;
//每像素的颜色位数
m_nBitCount = (BYTE)m_pBitmapInfoHeader->biBitCount;
//颜色数
m_nTotalColors = GetColorNumber();
if (m_pBitmapInfoHeader->biClrUsed == 0)
m_pBitmapInfoHeader->biClrUsed = m_nTotalColors;
//指向位图颜色索引表项的指针, 如果没有颜色表项, 则该值为NULL
m_pRGBQuad = (RGBQUAD*)(pbyDib + m_pBitmapInfoHeader->biSize);
//颜色索引表的大小(字节)
DWORD dwColorTableSize = m_nTotalColors * sizeof(RGBQUAD);
//指向位图数据的指针
m_pDibData = pbyDib + m_pBitmapInfoHeader->biSize + dwColorTableSize;
m_palDIB = new CPalette;
if (::CreateDIBPalette(m_hDIB, m_palDIB) == NULL)
{
// DIB有可能没有调色板
delete m_palDIB;
m_palDIB = NULL;
}
return TRUE;
}
BOOL CDib::LoadFromResource(UINT nID)
{
//从资源中载入DIB
HINSTANCE hResInst = AfxGetResourceHandle();
HRSRC hFindRes;
HDIB hDIB;
LPSTR pDIB;
LPSTR pRes;
HGLOBAL hRes;
//搜寻指定的资源
hFindRes = ::FindResource(hResInst, MAKEINTRESOURCE(nID), RT_BITMAP);
if (hFindRes == NULL) return FALSE;
hRes = ::LoadResource(hResInst, hFindRes); //载入位图资源
DWORD dwSize=::SizeofResource(hResInst,hFindRes);
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize);
if (hDIB == NULL) return FALSE;
pDIB = (LPSTR)::GlobalLock((HGLOBAL)hDIB);
pRes = (LPSTR) ::LockResource(hRes);
memcpy(pDIB, pRes, dwSize); //把hRes中的内容复制hDIB中
::GlobalUnlock((HGLOBAL) hDIB);
DeleteDIB();
m_hDIB=hDIB;
//获取位图文件头指针
BYTE* pbyDib = (BYTE*)::GlobalLock(m_hDIB);
m_pBitmapInfoHeader = (BITMAPINFOHEADER*) pbyDib;
//宽度和高度
m_nWidth = m_pBitmapInfoHeader->biWidth;
m_nHeight = m_pBitmapInfoHeader->biHeight;
//每像素的颜色位数
m_nBitCount = (BYTE)m_pBitmapInfoHeader->biBitCount;
//颜色数
m_nTotalColors = GetColorNumber();
if (m_pBitmapInfoHeader->biClrUsed == 0)
m_pBitmapInfoHeader->biClrUsed = m_nTotalColors;
//指向位图颜色索引表项的指针, 如果没有颜色表项, 则该值为NULL
m_pRGBQuad = (RGBQUAD*)(pbyDib + m_pBitmapInfoHeader->biSize);
//颜色索引表的大小(字节)
DWORD dwColorTableSize = m_nTotalColors * sizeof(RGBQUAD);
//指向位图数据的指针
DWORD s= m_pBitmapInfoHeader->biSize;
m_pDibData = pbyDib + s+ dwColorTableSize;
m_palDIB = new CPalette;
if (::CreateDIBPalette(m_hDIB, m_palDIB) == NULL)
{
// DIB有可能没有调色板
delete m_palDIB;
m_palDIB = NULL;
}
return TRUE;
}
int CDib::Width()
{
if(m_hDIB==NULL) return 0;
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
int cxDIB = (int) ::DIBWidth(lpDIB);
::GlobalUnlock((HGLOBAL) m_hDIB);
return cxDIB;
}
int CDib::Height()
{
if(m_hDIB==NULL) return 0;
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
int cyDIB = (int) ::DIBHeight(lpDIB); // Size of DIB - y
::GlobalUnlock((HGLOBAL) m_hDIB);
return cyDIB;
}
BOOL CDib::Draw(CDC *pDC, int x, int y, int cx, int cy)
{
//显示DIB,该函数具有缩放功能
//参数x和y说明了目的矩形的左上角坐标,cx和cy说明了目的矩形的尺寸
//cx和cy若有一个为0则该函数按DIB的实际大小绘制,cx和cy的缺省值是0
int dx=Width();
int dy=Height();
if(m_hDIB==NULL) return FALSE;
CRect rDIB,rDest;
rDest.left=x;
rDest.top=x;
if(cx==0||cy==0)
{
cx=dx;
cy=dy;
}
rDest.right=rDest.left+cx;
rDest.bottom=rDest.top+cy;
rDIB.left=rDIB.top=0;
rDIB.right=Width();
rDIB.bottom=Height();
return ::PaintDIB(pDC->GetSafeHdc(),&rDest,m_hDIB,&rDIB,m_palDIB);
}
//将所有格式的数据转换成DDB--32位数据, 存放于lpbyDdb32
//返回获取数据的总数.
//32位DDB数据按字节顺序:蓝色--绿色--红色--保留字节--
DWORD CDib::GetDdbData32(LPBYTE lpbyDdb32)
{
VERIFY(lpbyDdb32);
//计算DIB位图中一行的字节量
DWORD dwDibWidthBytes = GetDibWidthBytes(m_nWidth, m_nBitCount);
//转换成32位DDB后每行的大小, 注意每位4字节
DWORD dwDdbWidthBytes = m_nWidth * 4;
if(m_nBitCount == 1)
{
//每行实际字节数, 8个像素对应一个字节.
long nLineBytes = (m_nWidth + 7) / 8;
BYTE abyBitMask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
//DIB位图数据的行头
DWORD dwDibBaseIndex = (m_nHeight - 1) * dwDibWidthBytes;
//DDB 32位位图数据的行头
DWORD dwDdbBaseIndex = 0;
for(long i = 0;i < m_nHeight;i++)
{
//指向DIB行数据的指针
BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex;
//指向 DDB 32位位图的数据的指针
BYTE* pbyDdbRaw = lpbyDdb32 + dwDdbBaseIndex;
for(long j = 0;j < nLineBytes;j++)
{
//8个像素数据的索引值
BYTE byBit8 = *(pbyDibRaw++);
for(int n = 0; n < 8;n++)
{
BYTE byBitSingle = (byBit8 & abyBitMask[n]) >> (7 - n);
*(pbyDdbRaw++) = m_pRGBQuad[byBitSingle].rgbBlue; //蓝色
*(pbyDdbRaw++) = m_pRGBQuad[byBitSingle].rgbGreen; //绿色
*(pbyDdbRaw++) = m_pRGBQuad[byBitSingle].rgbRed; //红色
pbyDdbRaw++; //保留**
}
}//end j
dwDibBaseIndex -= dwDibWidthBytes;
dwDdbBaseIndex += dwDdbWidthBytes;
}//end i
return (dwDdbWidthBytes * m_nHeight);
}// end if(m_nBitCount == 1)
else if(m_nBitCount == 4)
{
//每行实际字节数
long nLineBytes = (m_nWidth + 1) / 2;
//DIB位图数据的行头
DWORD dwDibBaseIndex = (m_nHeight - 1) * dwDibWidthBytes;
//DDB 32位位图数据的行头
DWORD dwDdbBaseIndex = 0;
for(long i = 0;i < m_nHeight;i++)
{
//指向DIB行数据的指针
BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex;
//指向 DDB 32位位图的数据的指针
BYTE* pbyDdbRaw = lpbyDdb32 + dwDdbBaseIndex;
for(long j = 0;j < nLineBytes;j++)
{
//两个像素数据的索引值, 通过高四位和低四位
BYTE byBit8 = *(pbyDibRaw++);
BYTE byBitHigh = (byBit8 & 0xF0) >> 4;
BYTE byBitLow = (byBit8 & 0x0F);
*(pbyDdbRaw++) = m_pRGBQuad[byBitHigh].rgbBlue; //蓝色
*(pbyDdbRaw++) = m_pRGBQuad[byBitHigh].rgbGreen; //绿色
*(pbyDdbRaw++) = m_pRGBQuad[byBitHigh].rgbRed; //红色
pbyDdbRaw++;
*(pbyDdbRaw++) = m_pRGBQuad[byBitLow].rgbBlue; //蓝色
*(pbyDdbRaw++) = m_pRGBQuad[byBitLow].rgbGreen; //绿色
*(pbyDdbRaw++) = m_pRGBQuad[byBitLow].rgbRed; //红色
pbyDdbRaw++;
}//end j
dwDibBaseIndex -= dwDibWidthBytes;
dwDdbBaseIndex += dwDdbWidthBytes;
}//end i
return (dwDdbWidthBytes * m_nHeight);
}// end if(m_nBitCount == 4)
else if(m_nBitCount == 8)
{
//DIB位图数据的行头
DWORD dwDibBaseIndex = (m_nHeight - 1) * dwDibWidthBytes;
//DDB 32位位图数据的行头
DWORD dwDdbBaseIndex = 0;
for(long i = 0;i < m_nHeight;i++)
{
//指向DIB行数据的指针
BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex;
//指向 DDB 32位位图的数据的指针
BYTE* pbyDdbRaw = lpbyDdb32 + dwDdbBaseIndex;
for(long j = 0;j < m_nWidth;j++)
{
//一个像素数据的索引值
BYTE byIndex = *(pbyDibRaw++);
*(pbyDdbRaw++) = m_pRGBQuad[byIndex].rgbBlue; //蓝色
*(pbyDdbRaw++) = m_pRGBQuad[byIndex].rgbGreen; //绿色
*(pbyDdbRaw++) = m_pRGBQuad[byIndex].rgbRed; //红色
pbyDdbRaw++;
}//end j
dwDibBaseIndex -= dwDibWidthBytes;
dwDdbBaseIndex += dwDdbWidthBytes;
}//end i
return (dwDdbWidthBytes * m_nHeight);
}// end if(m_nBitCount == 8)
else if(m_nBitCount == 24)
{
//DIB位图数据的行头
DWORD dwDibBaseIndex = (m_nHeight - 1) * dwDibWidthBytes;
//DDB 32位位图数据的行头
DWORD dwDdbBaseIndex = 0;
for(long i = 0;i < m_nHeight;i++)
{
//指向DIB行数据的指针
BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex;
//指向 DDB 32位位图的数据的指针
BYTE* pbyDdbRaw = lpbyDdb32 + dwDdbBaseIndex;
for(long j = 0;j < m_nWidth;j++)
{
*(pbyDdbRaw++) = *(pbyDibRaw++); //蓝色
*(pbyDdbRaw++) = *(pbyDibRaw++); //绿色
*(pbyDdbRaw++) = *(pbyDibRaw++); //红色
pbyDdbRaw++;
}//end j
dwDibBaseIndex -= dwDibWidthBytes;
dwDdbBaseIndex += dwDdbWidthBytes;
}//end i
return (dwDdbWidthBytes * m_nHeight);
}// end if(m_nBitCount == 24)
return (m_nWidth * m_nHeight);
}
//每行的字节宽度
DWORD CDib::GetDibWidthBytes(int nWidth, BYTE byBitCount)
{
DWORD dwWidthBytes = (DWORD)nWidth; //8-bits
if(byBitCount == 1) dwWidthBytes = (nWidth + 7) / 8;
else if(byBitCount == 4) dwWidthBytes = (nWidth + 1) / 2;
else if(byBitCount == 24) dwWidthBytes = 3 * nWidth ;
while((dwWidthBytes & 3) != 0)dwWidthBytes++;
return dwWidthBytes;
}
UINT CDib::GetColorNumber() const
{
UINT nColors = 0;
if ((m_pBitmapInfoHeader->biClrUsed == 0) &&
(m_pBitmapInfoHeader->biBitCount < 9))
{
switch (m_pBitmapInfoHeader->biBitCount)
{
case 1: nColors = 2; break;
case 4: nColors = 16; break;
case 8: nColors = 256;break;
}
}
else
nColors = (UINT) m_pBitmapInfoHeader->biClrUsed;
return nColors;
}