#include "stdafx.h"
#include "cdib.h"
#include "windowsx.h"
#include "math.h"
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
CDib::CDib()
{
size=0;
m_pRGB = NULL;
m_pData = NULL;
m_pBitmapInfo = NULL;
m_pBitmapInfoHeader = NULL;
m_valid = false;
pDib = NULL;
m_nWidth = 0;
m_nHeight = 0;
}
CDib::CDib(const CDib&dib)
{ //拷贝构造函数
m_nWidth = dib.m_nWidth;
m_nHeight = dib.m_nHeight;
m_nLineBytes = dib.m_nLineBytes;
size = dib.size;
pDib = (BYTE*)GlobalAllocPtr(GMEM_MOVEABLE, size);
m_pBitmapInfoHeader = ( BITMAPINFOHEADER* ) pDib;
GetBitmapInfoHeader( *m_pBitmapInfoHeader );
m_pData = pDib + sizeof( BITMAPINFOHEADER );
memcpy(m_pData,dib.m_pData,size - sizeof( BITMAPINFOHEADER ));
}
CDib::CDib(int nWidth, int nHeight)
{//
ASSERT( nWidth > 0 );
ASSERT( nHeight > 0 );
m_nWidth = nWidth;
m_nHeight = nHeight;
m_nLineBytes = (m_nWidth * 24 + 31 ) /32*4;
size = m_nLineBytes * m_nHeight + sizeof( BITMAPINFOHEADER );
pDib = (BYTE*)GlobalAllocPtr(GMEM_MOVEABLE, size);
m_pBitmapInfoHeader = ( BITMAPINFOHEADER* ) pDib;
GetBitmapInfoHeader( *m_pBitmapInfoHeader );
m_pData = pDib + sizeof( BITMAPINFOHEADER );
memset( m_pData, 0x00, size - sizeof( BITMAPINFOHEADER ) );
}
CDib::~CDib()
{
GlobalFreePtr(pDib);
}
void CDib::LoadFile(const char* dibFileName)
{
strcpy(m_fileName,dibFileName);
CFile dibFile(m_fileName, CFile::modeRead);
dibFile.Read((void*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER));
if (bitmapFileHeader.bfType == 0x4d42)
{
DWORD fileLength = dibFile.GetLength();
size = fileLength -sizeof(BITMAPFILEHEADER);
pDib =(BYTE*)GlobalAllocPtr(GMEM_MOVEABLE, size); //分配位图空间
dibFile.Read((void*)pDib, size);
dibFile.Close();
m_pBitmapInfo = (BITMAPINFO*) pDib;
m_pBitmapInfoHeader = (BITMAPINFOHEADER*) pDib;
m_pRGB = (RGBQUAD*)(pDib +
m_pBitmapInfoHeader->biSize);
int m_numberOfColors = GetNumberOfColors();
if (m_pBitmapInfoHeader->biClrUsed == 0)
m_pBitmapInfoHeader->biClrUsed =
m_numberOfColors;
DWORD colorTableSize = m_numberOfColors *
sizeof(RGBQUAD);
m_pData = pDib + m_pBitmapInfoHeader->biSize
+ colorTableSize;
if (m_pRGB == (RGBQUAD*)m_pData) // No color table
m_pRGB = NULL;
m_pBitmapInfoHeader->biSizeImage = GetSize();
GetDibWidthBytes();
m_nWidth = m_pBitmapInfoHeader->biWidth;
m_nHeight = m_pBitmapInfoHeader->biHeight;
m_valid = TRUE;
}
else
{
m_valid = FALSE;
AfxMessageBox("This isn't a bitmap file!");
}
}
BOOL CDib::IsValid()
{
return m_valid;
}
char* CDib::GetFileName()
{
return m_fileName;
}
UINT CDib::GetWidth()
{
return (UINT) m_pBitmapInfoHeader->biWidth;
}
UINT CDib::GetHeight()
{
return (UINT) m_pBitmapInfoHeader->biHeight;
}
DWORD CDib::GetSize()
{
if (m_pBitmapInfoHeader->biSizeImage != 0)
return m_pBitmapInfoHeader->biSizeImage;
else
{
DWORD height = (DWORD) GetHeight();
DWORD width = (DWORD) GetWidth();
return height * width;
}
}
UINT CDib::GetNumberOfColors()
{
int numberOfColors;
if ((m_pBitmapInfoHeader->biClrUsed == 0) &&
(m_pBitmapInfoHeader->biBitCount < 9))
{
switch (m_pBitmapInfoHeader->biBitCount)
{
case 1: numberOfColors = 2; break;
case 4: numberOfColors = 16; break;
case 8: numberOfColors = 256;
}
}
else
numberOfColors = (int) m_pBitmapInfoHeader->biClrUsed;
return numberOfColors;
}
BYTE* CDib::GetData()
{
return m_pData;
}
RGBQUAD* CDib::GetRGB()
{
return m_pRGB;
}
BITMAPINFO* CDib::GetInfo()
{
return m_pBitmapInfo;
}
WORD CDib::PaletteSize(LPBYTE lpDIB)
{
return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
}
WORD CDib::DIBNumColors(LPBYTE lpDIB)
{
WORD wBitCount; // DIB bit count
wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
switch (wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
void CDib::SaveFile(const CString filename)
{
strcpy(m_fileName,filename);
CFile dibFile(m_fileName, CFile::modeCreate|CFile::modeWrite);
dibFile.Write((void*)&bitmapFileHeader,sizeof(BITMAPFILEHEADER));
dibFile.Write((void*)pDib, size);
dibFile.Close();
}
bool CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight)
{
// If we have not data we can't draw.
if( pDib == NULL )
return false;
// Check for the default values of -1
// in the width and height arguments. If
// we find -1 in either, we'll set them
// to the value that's in the BITMAPINFOHEADER.
if( nWidth == -1 )
nWidth = m_pBitmapInfoHeader->biWidth;
if( nHeight == -1 )
nHeight = m_pBitmapInfoHeader->biHeight;
// Use StretchDIBits to draw the Dib.
StretchDIBits( pDC->m_hDC, nX, nY,
nWidth, nHeight,
0, 0,
m_pBitmapInfoHeader->biWidth, m_pBitmapInfoHeader->biHeight,
m_pData,
( BITMAPINFO* ) m_pBitmapInfoHeader,
DIB_RGB_COLORS, SRCCOPY );
return TRUE;
}
DWORD CDib::GetDibWidthBytes()
{
m_nBitCount=m_pBitmapInfoHeader->biBitCount;
LONG nWidth=m_pBitmapInfoHeader->biWidth;
m_nLineBytes = (DWORD)m_pBitmapInfoHeader->biWidth; //8-bits
if(m_nBitCount == 1) m_nLineBytes = (nWidth + 7) / 8;
else if(m_nBitCount == 4) m_nLineBytes = (nWidth + 1) / 2;
else if(m_nBitCount == 24) m_nLineBytes = 3 * nWidth ;
while((m_nLineBytes & 3) != 0)
m_nLineBytes++;
return m_nLineBytes;
}
//////////////////////////////////////////////////////////////////////////
//This method is only 24-bitmap
//Transfer
bool CDib::BltFast(CPoint ptDest, CPoint ptSrc, CSize size,CDib *pSrcdib , bool bTransParent)
{
if ( ptDest.x < 0 )
{
ptSrc.x -= ptDest.x;
size.cx += ptDest.x;
ptDest.x = 0;
}
if ( ptDest.y < 0 )
{
ptSrc.y -= ptDest.y;
size.cy += ptDest.y;
ptDest.y = 0;
}
if ( ptDest.x + size.cx > m_nWidth )
size.cx = m_nWidth - ptDest.x;
if ( ptDest.y + size.cy > m_nHeight )
size.cy = m_nHeight - ptDest.y;
//BottomTop
ptDest.y = m_nHeight - ptDest.y - size.cy;
ptSrc.y = pSrcdib->m_nHeight - ptSrc.y - size.cy;
//
// ptDest.y = m_nHeight - ptDest.y - 1;
// ptSrc.y = pSrcdib->m_nHeight - ptSrc.y - 1;
//
BYTE* pSrcBits = pSrcdib->m_pData;
pSrcBits += pSrcdib->m_nLineBytes * ptSrc.y + 3 * ptSrc.x; // Data address of Src DIB
BYTE* pDestBits = m_pData;
pDestBits += m_nLineBytes * ptDest.y + 3 * ptDest.x; // Data address of Dest DIB
//TRACE("%d\n",ptOriginSrc.y);
ASSERT( ptSrc.x >= 0 );
ASSERT( ptSrc.y >= 0 );
ASSERT( ptDest.x >= 0 );
ASSERT( ptDest.y >= 0 );
if ( bTransParent )
{// if use the transparent color
BYTE* pHSrc;
BYTE* pHDest;
DIB_COLOR tmp;
TRACE("%d,%d\n",size.cy,size.cx);
for (int i = 0; i < size.cy; i++) //Height
{
pHSrc = pSrcBits;
pHDest = pDestBits;
for (int j = 0; j < size.cx; j++) //Width
{
if ( ( tmp = pSrcdib->GetColor( pHSrc ) ) != COLOR_BLACK)
SetColor(pHDest, tmp );
pHSrc += PixelBytes; //Move the pointer
pHDest += PixelBytes;
}
pSrcBits += pSrcdib->m_nLineBytes; //Chanage the line
pDestBits += m_nLineBytes;
}
}
else
{// Copy a Dib Data to the other Dib Data
int nSize = 3 * size.cx;
for ( int i = 0; i < size.cy; i++ )
{
memcpy( pDestBits, pSrcBits, nSize ); // 直接拷贝扫描行即可
pSrcBits += pSrcdib->m_nLineBytes;
pDestBits += m_nLineBytes;
}
}
return true;
}
////////////////////////////////////