📄 dibitmap.cpp
字号:
#include "stdafx.h"
#include "DIBitmap.h"
CBmpPalette::CBmpPalette( CDIBitmap* pBmp )
{
ASSERT( pBmp );
int cPaletteEntries = pBmp->GetPalEntries();
int cPalette = sizeof(LOGPALETTE) +
sizeof(PALETTEENTRY) * cPaletteEntries;
// Since the LOGPALETTE structure is open-ended, you
// must dynamically allocate it, rather than using one
// off the stack.
LOGPALETTE* pPal = (LOGPALETTE*)new BYTE[cPalette];
RGBQUAD* pColorTab = pBmp->GetColorTablePtr();
pPal->palVersion = 0x300;
pPal->palNumEntries = cPaletteEntries;
// Roll through the color table, and add each color to
// the logical palette.
for( int ndx = 0; ndx < cPaletteEntries; ndx++ )
{
pPal->palPalEntry[ndx].peRed = pColorTab[ndx].rgbRed;
pPal->palPalEntry[ndx].peGreen = pColorTab[ndx].rgbGreen;
pPal->palPalEntry[ndx].peBlue = pColorTab[ndx].rgbBlue;
pPal->palPalEntry[ndx].peFlags = NULL;
}
VERIFY( CreatePalette( pPal ) );
delete [] (BYTE*)pPal;
}
#define PADWIDTH(x) (((x)*8 + 31) & (~31))/8
CDIBitmap :: CDIBitmap()
: m_pInfo(0)
, m_pPixels(0)
, m_pPal(0)
, m_bIsPadded(FALSE)
{
}
CDIBitmap :: ~CDIBitmap() {
delete [] (BYTE*)m_pInfo;
delete [] m_pPixels;
delete m_pPal;
}
void CDIBitmap :: DestroyBitmap() {
delete [] (BYTE*)m_pInfo;
delete [] m_pPixels;
delete m_pPal;
m_pInfo = 0;
m_pPixels = 0;
m_pPal = 0;
}
BOOL CDIBitmap :: CreateFromBitmap( CDC * pDC, CBitmap * pSrcBitmap ) {
ASSERT_VALID(pSrcBitmap);
ASSERT_VALID(pDC);
try {
BITMAP bmHdr;
// Get the pSrcBitmap info
pSrcBitmap->GetObject(sizeof(BITMAP), &bmHdr);
// Reallocate space for the image data
if( m_pPixels ) {
delete [] m_pPixels;
m_pPixels = 0;
}
DWORD dwWidth;
if (bmHdr.bmBitsPixel > 8)
dwWidth = PADWIDTH(bmHdr.bmWidth * 3);
else
dwWidth = PADWIDTH(bmHdr.bmWidth);
m_pPixels = new BYTE[dwWidth*bmHdr.bmHeight];
if( !m_pPixels )
throw TEXT("could not allocate data storage\n");
// Set the appropriate number of colors base on BITMAP structure info
WORD wColors;
switch( bmHdr.bmBitsPixel ) {
case 1 :
wColors = 2;
break;
case 4 :
wColors = 16;
break;
case 8 :
wColors = 256;
break;
default :
wColors = 0;
break;
}
// Re-allocate and populate BITMAPINFO structure
if( m_pInfo ) {
delete [] (BYTE*)m_pInfo;
m_pInfo = 0;
}
m_pInfo = (BITMAPINFO*)new BYTE[sizeof(BITMAPINFOHEADER) + wColors*sizeof(RGBQUAD)];
if( !m_pInfo )
throw TEXT("could not allocate BITMAPINFO struct\n");
// Populate BITMAPINFO header info
m_pInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_pInfo->bmiHeader.biWidth = bmHdr.bmWidth;
m_pInfo->bmiHeader.biHeight = bmHdr.bmHeight;
m_pInfo->bmiHeader.biPlanes = bmHdr.bmPlanes;
if( bmHdr.bmBitsPixel > 8 )
m_pInfo->bmiHeader.biBitCount = 24;
else
m_pInfo->bmiHeader.biBitCount = bmHdr.bmBitsPixel;
m_pInfo->bmiHeader.biCompression = BI_RGB;
m_pInfo->bmiHeader.biSizeImage = ((((bmHdr.bmWidth * bmHdr.bmBitsPixel) + 31) & ~31) >> 3) * bmHdr.bmHeight;
m_pInfo->bmiHeader.biXPelsPerMeter = 0;
m_pInfo->bmiHeader.biYPelsPerMeter = 0;
m_pInfo->bmiHeader.biClrUsed = 0;
m_pInfo->bmiHeader.biClrImportant = 0;
// Now actually get the bits
int test = ::GetDIBits(pDC->GetSafeHdc(), (HBITMAP)pSrcBitmap->GetSafeHandle(),
0, (WORD)bmHdr.bmHeight, m_pPixels, m_pInfo, DIB_RGB_COLORS);
// check that we scanned in the correct number of bitmap lines
if( test != (int)bmHdr.bmHeight )
throw TEXT("call to GetDIBits did not return full number of requested scan lines\n");
CreatePalette();
m_bIsPadded = FALSE;
#ifdef _DEBUG
} catch( TCHAR * psz ) {
TRACE1("CDIBitmap::CreateFromBitmap(): %s\n", psz);
#else
} catch( TCHAR * ) {
#endif
if( m_pPixels ) {
delete [] m_pPixels;
m_pPixels = 0;
}
if( m_pInfo ) {
delete [] (BYTE*) m_pInfo;
m_pInfo = 0;
}
return FALSE;
}
return TRUE;
}
BOOL CDIBitmap :: LoadResource(LPCTSTR pszID) {
HBITMAP hBmp = (HBITMAP)::LoadImage(
AfxGetInstanceHandle(),
pszID, IMAGE_BITMAP,
0,0, LR_CREATEDIBSECTION
);
if( hBmp == 0 )
return FALSE;
CBitmap bmp;
bmp.Attach(hBmp);
CClientDC cdc( CWnd::GetDesktopWindow() );
BOOL bRet = CreateFromBitmap( &cdc, &bmp );
bmp.DeleteObject();
CreatePalette();
return bRet;
}
BOOL CDIBitmap :: Load( CFile* pFile ) {
ASSERT( pFile );
BOOL fReturn = TRUE;
try {
delete [] (BYTE*)m_pInfo;
delete [] m_pPixels;
m_pInfo = 0;
m_pPixels = 0;
DWORD dwStart = pFile->GetPosition();
//
// Check to make sure we have a bitmap. The first two bytes must
// be 'B' and 'M'.
BITMAPFILEHEADER fileHeader;
pFile->Read(&fileHeader, sizeof(fileHeader));
if( fileHeader.bfType != 0x4D42 )
throw TEXT("Error:Unexpected file type, not a DIB\n");
BITMAPINFOHEADER infoHeader;
pFile->Read( &infoHeader, sizeof(infoHeader) );
if( infoHeader.biSize != sizeof(infoHeader) )
throw TEXT("Error:OS2 PM BMP Format not supported\n");
// Store the sizes of the DIB structures
int cPaletteEntries = GetPalEntries( infoHeader );
int cColorTable = 256 * sizeof(RGBQUAD);
int cInfo = sizeof(BITMAPINFOHEADER) + cColorTable;
int cPixels = fileHeader.bfSize - fileHeader.bfOffBits;
//
// Allocate space for a new bitmap info header, and copy
// the info header that was loaded from the file. Read the
// the file and store the results in the color table.
m_pInfo = (BITMAPINFO*)new BYTE[cInfo];
memcpy( m_pInfo, &infoHeader, sizeof(BITMAPINFOHEADER) );
pFile->Read( ((BYTE*)m_pInfo) + sizeof(BITMAPINFOHEADER),
cColorTable );
//
// Allocate space for the pixel area, and load the pixel
// info from the file.
m_pPixels = new BYTE[cPixels];
pFile->Seek(dwStart + fileHeader.bfOffBits, CFile::begin);
pFile->Read( m_pPixels, cPixels );
CreatePalette();
m_bIsPadded = TRUE;
#ifdef _DEBUG
} catch( TCHAR * psz ) {
TRACE( psz );
#else
} catch( TCHAR * ) {
#endif
fReturn = FALSE;
}
return fReturn;
}
BOOL CDIBitmap :: Load( const CString & strFilename ) {
CFile file;
if( file.Open( strFilename, CFile::modeRead ) )
return Load( &file );
return FALSE;
}
BOOL CDIBitmap :: Save( const CString & strFileName ) {
ASSERT(! strFileName.IsEmpty());
CFile File;
if( !File.Open(strFileName, CFile::modeCreate|CFile::modeWrite) ) {
TRACE1("CDIBitmap::Save(): Failed to open file %s for writing.\n", LPCSTR(strFileName));
return FALSE;
}
return Save( &File );
}
// Does not open or close pFile. Assumes
// caller will do it.
BOOL CDIBitmap :: Save( CFile * pFile ) {
ASSERT_VALID( pFile );
ASSERT( m_pInfo );
ASSERT( m_pPixels );
BITMAPFILEHEADER bmfHdr;
DWORD dwPadWidth = PADWIDTH(GetWidth());
// Make sure bitmap data is in padded format
PadBits();
bmfHdr.bfType = 0x4D42;
// initialize to BitmapInfo size
DWORD dwImageSize= m_pInfo->bmiHeader.biSize;
// Add in palette size
WORD wColors = GetColorCount();
WORD wPaletteSize = (WORD)(wColors*sizeof(RGBQUAD));
dwImageSize += wPaletteSize;
// Add in size of actual bit array
dwImageSize += PADWIDTH((GetWidth()) * DWORD(m_pInfo->bmiHeader.biBitCount)/8) * GetHeight();
m_pInfo->bmiHeader.biSizeImage = 0;
bmfHdr.bfSize = dwImageSize + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + m_pInfo->bmiHeader.biSize + wPaletteSize;
pFile->Write(&bmfHdr, sizeof(BITMAPFILEHEADER));
pFile->Write(m_pInfo, sizeof(BITMAPINFO) + (wColors-1)*sizeof(RGBQUAD));
pFile->WriteHuge(m_pPixels,
DWORD((dwPadWidth*(DWORD)m_pInfo->bmiHeader.biBitCount*GetHeight())/8) );
return TRUE;
}
BOOL CDIBitmap :: CreatePalette() {
if( m_pPal )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -