www.pudn.com > SobelKirsch.rar > Dib.cpp
/////////////////////////////////////////////////////////////////////////////////
//
// Dib.cpp: implementation of the CDib class.
//
////////////////////////////////////////////////////////////////////////////////
// 版权所有(2002)
// Copyright(2002)
// 编写者: 向世明
// Author: Xiang Shiming
#include "stdafx.h"
#include "dib.h"
IMPLEMENT_DYNAMIC(CDib, CObject)
CDib::CDib()
{
Init();
}
CDib::CDib(const char* pszDibFileName)
{
Init();
LoadFile(pszDibFileName);
}
CDib::~CDib()
{
ClearMemory();
}
void CDib::ClearMemory()
{
if(m_hDIB != NULL)
::GlobalFree(m_hDIB);
m_hDIB = 0;
m_pDibData = NULL;
m_pszFileName = NULL;
m_pBitmapInfoHeader = NULL;
m_pBitmapInfo = NULL;
m_pRGBQuad = NULL;
m_pBitmapFileHeader = NULL;
}
#ifdef _DEBUG
void CDib::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
}
void CDib::AssertValid() const
{
CObject::AssertValid();
ASSERT(m_pszFileName != NULL);
ASSERT(m_hDIB != 0);
}
#endif
void CDib::Init()
{
m_pRGBQuad = NULL; //RGBQUAD 表项
m_pDibData = NULL; //位图像素数据
m_nWidth = 0; //宽度
m_nHeight = 0; //高度
m_nBitCount = 0; //每个像素占有的位数
m_nTotalColors = 0; //颜色总数
m_pBitmapFileHeader = NULL;
m_pBitmapInfoHeader = NULL;
m_pBitmapInfo = NULL;
m_hDIB = 0;
m_pszFileName = NULL;
}
void CDib::LoadFile(const char* pszDibFileName)
{
ASSERT(pszDibFileName);
//如果存在就释放内存
if(m_pBitmapInfo) ::GlobalFree(m_hDIB);
//再次初始化, 用于多次动态重用
Init();
m_pszFileName = (char*)pszDibFileName;
BITMAPFILEHEADER bitmapFileHeader;
CFile dibFile(pszDibFileName, CFile::modeRead);
try
{
//读入位图文件头信息
UINT nBFHsize = dibFile.Read((void*)&bitmapFileHeader, sizeof(BITMAPFILEHEADER));
if(nBFHsize != sizeof(BITMAPFILEHEADER))
{
m_bValid = FALSE;
return;
}
}
catch(CFileException* e)
{
e->Delete();
}
//如果为位图就进行下一步的处理
if (bitmapFileHeader.bfType == 0x4d42)
{
AfxGetApp()->BeginWaitCursor();
//文件长度
DWORD dwFileLength = dibFile.GetLength();
//位图信息及位图数据的大小(字节)
DWORD dwSize = dwFileLength - sizeof(BITMAPFILEHEADER);
//为Dib分配全局内存
m_hDIB = (HGLOBAL) ::GlobalAlloc(GMEM_MOVEABLE, dwSize);
if (m_hDIB == 0) m_bValid = FALSE;
//指向Dib实际像素数据的指针,
BYTE* pbyDib = (BYTE*)::GlobalLock(m_hDIB);
if (pbyDib == NULL) m_bValid = FALSE;
try
{
//读入内存
DWORD dwReadSize = dibFile.Read((void*)pbyDib, dwSize);
dibFile.Close();
if(dwReadSize != dwSize)
{
m_bValid = FALSE;
::GlobalUnlock(m_hDIB);
::GlobalFree(m_hDIB);
Init();
return;
}
}
catch(CFileException* e)
{
e->Delete();
}
//获取位图文件头指针和位图文件数据信息指针
m_pBitmapInfo = (BITMAPINFO*) pbyDib;
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;
//如果没有颜色索引表, 则该值为NULL
if (m_pRGBQuad == (RGBQUAD*)m_pDibData) m_pRGBQuad = NULL;
//位图的大小(面积像素单位)
m_pBitmapInfoHeader->biSizeImage = GetSize();
::GlobalUnlock(m_hDIB);
AfxGetApp()->EndWaitCursor();
m_bValid = TRUE;
}
else
{
AfxMessageBox("This is not a bitmap file!");
m_bValid = FALSE;
}
}
LONG CDib::GetWidth() const
{
return m_nWidth;
}
LONG CDib::GetHeight() const
{
return m_nHeight;
}
//获取数据缓冲区的大小
DWORD CDib::GetSize()
{
if (m_pBitmapInfoHeader->biSizeImage != 0)
return (m_pBitmapInfoHeader->biSizeImage);
else
return (DWORD)GetDibWidthBytes(m_nWidth, 24) * (DWORD)m_nHeight;
}
BYTE CDib::GetBitCount() const
{
return m_nBitCount;
}
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;
}
char* CDib::GetFileName() const
{
return m_pszFileName;
}
BYTE* CDib::GetDibData() const
{
return m_pDibData;
}
RGBQUAD* CDib::GetRGBQuad() const
{
return m_pRGBQuad;
}
BITMAPINFO* CDib::GetBmpInfo() const
{
return m_pBitmapInfo;
}
BOOL CDib::IsValid() const
{
return m_bValid;
}
//每行的字节宽度
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;
}
//将所有格式的数据转换成DDB--24位数据, 存放于lpbyDdb24
//返回获取数据的总数.
DWORD CDib::GetDdbData24(LPBYTE lpbyDdb24)
{
ASSERT(lpbyDdb24);
//计算DIB位图中一行的字节量
DWORD dwDibWidthBytes = GetDibWidthBytes(m_nWidth, m_nBitCount);
//转换成24位DDB后每行的大小, 注意每行的字节数只需要是偶数即可
DWORD dwDdbWidthBytes = ((m_nWidth * 24 + 15) / 16) * 2;
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 24位位图数据的行头
DWORD dwDdbBaseIndex = 0;
for(LONG i = 0;i < m_nHeight;i++)
{
//指向DIB行数据的指针
BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex;
//指向 DDB 24位位图的数据的指针
BYTE* pbyDdbRaw = lpbyDdb24 + 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; //红色
}
}//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 24位位图数据的行头
DWORD dwDdbBaseIndex = 0;
for(LONG i = 0;i < m_nHeight;i++)
{
//指向DIB行数据的指针
BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex;
//指向 DDB 24位位图的数据的指针
BYTE* pbyDdbRaw = lpbyDdb24 + 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++) = m_pRGBQuad[byBitLow].rgbBlue; //蓝色
*(pbyDdbRaw++) = m_pRGBQuad[byBitLow].rgbGreen; //绿色
*(pbyDdbRaw++) = m_pRGBQuad[byBitLow].rgbRed; //红色
}//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 24位位图数据的行头
DWORD dwDdbBaseIndex = 0;
for(LONG i = 0;i < m_nHeight;i++)
{
//指向DIB行数据的指针
BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex;
//指向 DDB 24位位图的数据的指针
BYTE* pbyDdbRaw = lpbyDdb24 + 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; //红色
}//end j
dwDibBaseIndex -= dwDibWidthBytes;
dwDdbBaseIndex += dwDdbWidthBytes;
}//end i
return (dwDdbWidthBytes * m_nHeight);
}// end if(m_nBitCount == 8)
else if(m_nBitCount == 24)
{
DWORD dwLength = m_nWidth * 3;
//指向DIB行数据的指针
BYTE* pbyDibRaw = m_pDibData + (m_nHeight - 1) * dwDibWidthBytes;;
//指向 DDB 24位位图的数据的指针
BYTE* pbyDdbRaw = lpbyDdb24;
//蓝色--绿色--红色
for(LONG i = 0;i < m_nHeight;i++)
{
::CopyMemory(pbyDdbRaw, pbyDibRaw, dwLength);
pbyDibRaw -= dwDibWidthBytes; //from
pbyDdbRaw += dwDdbWidthBytes; //to
}//end i
return (dwDdbWidthBytes * m_nHeight);
}// end if(m_nBitCount == 24)
return (m_nWidth * m_nHeight);
}
//将所有格式的数据转换成DDB--32位数据, 存放于lpbyDdb32
//返回获取数据的总数.
//32位DDB数据按字节顺序:蓝色--绿色--红色--保留字节--
DWORD CDib::GetDdbData32(LPBYTE lpbyDdb32)
{
ASSERT(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);
}
//the return value is the number of scan lines copied.
int CDib::Draw(HDC hdc, int XDest, int YDest, int nDestWidth, int nDestHeight, int XSrc, int YSrc, int nSrcWidth, int nSrcHeight, UINT iUsage, DWORD dwRop)
{
if (m_pRGBQuad) // Has a color table
{
HPALETTE hPalette = CreateBitmapPalette();
HPALETTE hOldPalette = ::SelectPalette(hdc, hPalette, FALSE);
::RealizePalette(hdc);
int nScanLines = StretchDIBits(hdc,
XDest, YDest, nDestWidth, nDestHeight,
XSrc, YSrc, nSrcWidth, nSrcHeight,
m_pDibData, m_pBitmapInfo, iUsage, dwRop);
::SelectPalette(hdc, hOldPalette, FALSE);
::DeleteObject(hPalette);
return nScanLines;
}
else
return StretchDIBits(hdc,
XDest, YDest, nDestWidth, nDestHeight,
XSrc, YSrc, nSrcWidth, nSrcHeight,
m_pDibData, m_pBitmapInfo, iUsage, dwRop);
}
HPALETTE CDib::CreateBitmapPalette()
{
if((m_pRGBQuad == NULL) || !IsValid())return NULL;
struct
{
WORD palVersion;
WORD palNumEntries;
PALETTEENTRY palPalEntry[256];
} palette = { 0x300, 256 };
LPRGBQUAD pRGBTable = m_pRGBQuad;
for(UINT i = 0; i < m_nTotalColors; ++i)
{
palette.palPalEntry[i].peRed = pRGBTable[i].rgbRed;
palette.palPalEntry[i].peGreen = pRGBTable[i].rgbGreen;
palette.palPalEntry[i].peBlue = pRGBTable[i].rgbBlue;
palette.palPalEntry[i].peFlags = 0;
}
HPALETTE hPalette = ::CreatePalette((LPLOGPALETTE)&palette);
return hPalette;
}