www.gusucode.com > VC++使用BMP位图换肤实现液晶电子钟-源码程序 > VC++使用BMP位图换肤实现液晶电子钟-源码程序/code/Dib.cpp

    // Dib.cpp: implementation of the CDib class.
// Download by http://www.NewXing.com
//////////////////////////////////////////////////////////////////////

#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)
    {
		
		
		//文件长度
        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);
		m_bValid = TRUE;
    }    
    else
    {
        AfxMessageBox("This is not a bitmap file!");
		m_bValid = FALSE;
    }
}

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;
}

//获取数据缓冲区的大小       
DWORD CDib::GetSize()
{
    if (m_pBitmapInfoHeader->biSizeImage != 0)
        return (m_pBitmapInfoHeader->biSizeImage);
	else 
		return (DWORD)GetDibWidthBytes(m_nWidth, 24) * (DWORD)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;

}

BOOL CDib::IsValid() const
{
	return m_bValid;
}

//将所有格式的数据转换成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);
}

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;

}

//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);

}

BYTE CDib::GetBitCount() const
{
	return m_nBitCount;
}

BITMAPINFO* CDib::GetBmpInfo() const
{
    return m_pBitmapInfo;
}

BYTE* CDib::GetDibData() const
{
    return m_pDibData;
}

RGBQUAD* CDib::GetRGBQuad() const
{
    return m_pRGBQuad;
}