⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dibitmap.cpp

📁 API经典入门
💻 CPP
字号:
// Filename: DIBitmap.cpp

#include "stdafx.h"
#include "DIBitmap.h"

IMPLEMENT_DYNAMIC( CDIBitmap, CObject )

////////////////////////////////////////////////
// Constructors & Destructors

CDIBitmap::CDIBitmap()
{
	m_pBitmapInfo = NULL;
	m_pBits = NULL;
	m_wNumColors = 0;
	m_wBMISize = 0;
	m_dwBitsSize = 0;	
}

//CDIBitmap(CBitmap* pBM);
//CDIBitmap(BITMAP bm);

CDIBitmap::~CDIBitmap()
{
	DestroyDIB();
}

void CDIBitmap::DestroyDIB()
{
	free(m_pBits);
	free(m_pBitmapInfo);
	m_pBits = NULL;
	m_pBitmapInfo = NULL;
	m_wNumColors = 0;
	m_wBMISize = 0;
	m_dwBitsSize = 0;
}

////////////////////////////////////////////////
// Selectors

BOOL CDIBitmap::DIBIsLoaded() const
{
	return ((m_pBits != NULL) &&
			(m_pBitmapInfo != NULL) &&
			(m_dwBitsSize > 0) &&
			(m_wBMISize > 0));
}

WORD CDIBitmap::NumberOfColors() const
{
	ASSERT( DIBIsLoaded() );
	
	return m_wNumColors;
}
	
DWORD CDIBitmap::DIBDataSize() const
{
	// ASSERT's will be made in calling routines.

	return BitmapInfoSize() + BitsSize();
}

WORD CDIBitmap::BitmapInfoSize() const
{
	ASSERT( DIBIsLoaded() );
	
	return m_wBMISize;
}

DWORD CDIBitmap::BitsSize() const
{
	ASSERT( DIBIsLoaded() );
	
	return m_dwBitsSize;
}

////////////////////////////////////////////////
// Operations

BOOL CDIBitmap::GetPalette(CPalette* pPal)
{
	ASSERT_VALID (pPal);
	ASSERT( DIBIsLoaded() );
	
	WORD numRGBQUADS = NumberOfColors();
	
	// If there are no colors, there is no palette!
	if (numRGBQUADS == 0)
	{
		return FALSE;
	}

	// Construct a CPalette-compatible temporary destination
	// for the color info.
	LOGPALETTE* pLP = 
			(LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
			numRGBQUADS*sizeof(PALETTEENTRY));
	if (pLP == NULL)
	{
		// malloc failed to allocate memory for pLP
		TRACE0("GetPalette: Out of memory!\n");
		return FALSE;
	}		
	
	// Fill the LOGPALETTE structure with the color data.
	pLP->palVersion = 0x300; // Windows version 3.0 (or better)
	pLP->palNumEntries = numRGBQUADS;
	for (DWORD i = 0; i < numRGBQUADS; i++)
	{
		pLP->palPalEntry[i].peRed = m_pBitmapInfo->bmiColors[i].rgbRed;
		pLP->palPalEntry[i].peGreen = m_pBitmapInfo->bmiColors[i].rgbGreen;
		pLP->palPalEntry[i].peBlue = m_pBitmapInfo->bmiColors[i].rgbBlue;
		pLP->palPalEntry[i].peFlags = 0;
	}
	
	// Detatch and reallocate any LOGPALETTE structure that may
	// already be associated with the CPalette object.  
	// Note: CreatePalette() will fail w/ an assertion if the
	// CPalette object already has a palette.
	pPal->DeleteObject();
	
	// Create the new palette based on the LOGPALETTE structure
	// built above.
	if (!pPal->CreatePalette(pLP))
	{
		TRACE0("GetPalette: Palette creation failed!\n");
		free(pLP);
		return FALSE;
	}
	
	// Reallocate LOGPALETTE structure memory, since
	// all its info has been copied to the palette.
	free(pLP);
	
	return TRUE;
}

WORD BMIColorCount(BITMAPINFOHEADER* pInfoHeader)
{
	WORD numRGBQUADS;

	// if 24 bits per pixel and no colors are used, then 
	// there is no color table information.
	if ( (pInfoHeader->biBitCount == 24) && 
		(pInfoHeader->biClrUsed == 0) )
	{
		numRGBQUADS = 0;
	}
	else
	{
		// Compute number of colors held in the DIB file.
		if (pInfoHeader->biClrUsed == 0)
		{
			// find 2 to the power of biBitCount
			numRGBQUADS = 2 << (pInfoHeader->biBitCount-1);
		}
		else
		{
			numRGBQUADS = (WORD)pInfoHeader->biClrUsed;
		}
		
        
 	} // end if -- load RGB quads from DIB

	return numRGBQUADS;
}

BOOL CDIBitmap::LoadFromDIB(const char* lpszFileName)
{
	CFile fileDIB;		// File handle
	CFileException e;
	DWORD dwBOF;		// Beginning Of File position holder
    
	// Intermediate variables for bitmap information.
    BITMAPFILEHEADER fileHeader;
	BITMAPINFOHEADER infoHeader;
	WORD wNumColors;
	BITMAPINFO* pbmInfo = NULL;
	WORD wBMISize;
	BYTE* pbmBits = NULL;
	DWORD dwBitsSize;
	
	// Open the file	
	if ( !fileDIB.Open(lpszFileName, CFile::modeRead, &e) )
	{
		TRACE0 ("File could not be opened!\n");
		return FALSE;
	}
    
	// Store Beginning Of File (BOF) position
	dwBOF = fileDIB.GetPosition();
    
	// Read in the file header
	fileDIB.Read(&fileHeader, sizeof(BITMAPFILEHEADER));
	
	TRY
	{
	// Make sure its a bitmap file.
	if (fileHeader.bfType != 0x4D42) // 0x4D42 == "BM"
	{
		TRACE0 ("File is not a bitmap!\n");
		AfxThrowNotSupportedException();
	}

	// Read in the info header.
	fileDIB.Read(&infoHeader, sizeof(BITMAPINFOHEADER));
	
	// Make sure its in Windows format.
	if ( infoHeader.biSize != sizeof(BITMAPINFOHEADER) )
	{
		// Most likely the file is a presentation manager bitmap
		// file.  This file is structured using the BITCOREHEADER
		// type.  Consult your manuals for more information.
		TRACE0 ("File is not a Windows Bitmap File!\n");
		TRACE0 ("PM bitmaps not currently supported.\n");
		
		AfxThrowNotSupportedException();
	}
	
	// Analyze and retrieve the color table.
	wNumColors =  BMIColorCount(&infoHeader);
	wBMISize = sizeof(BITMAPINFO) + wNumColors*sizeof(RGBQUAD);
	pbmInfo = (BITMAPINFO*)malloc( wBMISize );
	if (wNumColors != 0)
	{
		fileDIB.Read(pbmInfo->bmiColors, wNumColors * sizeof(RGBQUAD));
	}
 	
 	// Finish initializing pbmInfo structure
 	memcpy(pbmInfo, &infoHeader, sizeof(BITMAPINFOHEADER));

	// Calculate memory needed for the image bits.
	dwBitsSize = (DWORD)(fileHeader.bfSize - fileHeader.bfOffBits);
	
	//TRACE1("Number of bits in the bitmap: %u\n", m_dwBitsSize);
	if (dwBitsSize > 64000)
	{
		TRACE0("Memory allocation too big for malloc!\n");
		AfxThrowMemoryException();
	}
	
	// Allocate enough memory for the bits.
	pbmBits = (BYTE*)malloc((int)dwBitsSize);
	
	if (pbmBits == NULL)
	{
		TRACE0("Not enough memory for bits!\n");
		AfxThrowMemoryException();
	}
	
	// Now we can read in the actual bitmap bits!
	fileDIB.Seek( dwBOF + fileHeader.bfOffBits, CFile::begin );
	fileDIB.Read( pbmBits, (int)dwBitsSize );

	fileDIB.Close();

    // Destroy (and free) old DIB info
    DestroyDIB();
    
	// Commit the changes.
	m_pBitmapInfo = pbmInfo;
	m_pBits = pbmBits;
	m_wNumColors = wNumColors;
	m_wBMISize = wBMISize;	
	m_dwBitsSize = dwBitsSize;
	
	return TRUE;
    
    
	} // end TRY
	CATCH(CException, e)
	{
	// If a fatal error occurs, clean things up.
	
	fileDIB.Close();
	
	if (pbmBits != NULL)
		free(pbmBits);
		
	if (pbmInfo != NULL)
		free(pbmInfo);
	}
	END_CATCH

	return FALSE;
}

BOOL CDIBitmap::SaveToDIB(const char* lpszFileName)
{
	return FALSE;
}

BOOL CDIBitmap::LoadFromHandle(HGLOBAL &hgDIB, DWORD dwSize)
{
	// Far pointer to the global memory object.
	BYTE FAR* lpDIB = NULL;

	// Intermediate variables for bitmap information.
	WORD wNumColors;
	BITMAPINFO bmiData;
	BITMAPINFO* pbmInfo = NULL;
	WORD wBMISize;
	BYTE* pbmBits = NULL;	
	DWORD dwBitsSize;
		
	// Make sure handle is valid.
	if ( (hgDIB == NULL) || (dwSize == 0) )
	{
		TRACE0("NULL handle was passed to LoadFromHandle().\n");
		return FALSE;
	}

	// Lock memory and retrieve the pointer.
	lpDIB = (BYTE FAR*)::GlobalLock(hgDIB);

	if (lpDIB == NULL)
	{
		TRACE0("LoadFromHandle: GlobalLock failed.\n");
		return FALSE;
	}
	
	// Get BITMAPINFO structure from block of global memory
	_fmemcpy( &bmiData.bmiHeader, lpDIB, sizeof(BITMAPINFOHEADER) );

	// Make sure its in Windows format.
	if ( bmiData.bmiHeader.biSize != sizeof(BITMAPINFOHEADER) )
	{
		// Most likely the mem block is a presentation manager 
		// bitmap.  This is structured using the BITCOREHEADER
		// type.  Consult your manuals for more information.
		TRACE0 ("Memory block is not a Windows Bitmap!\n");
		TRACE0 ("Presentation Manager bitmaps not supported.\n");

		goto FatalError;
	}

//TRACE1("InfoHeader: Bitmap Size: %ld \n", bmiData.bmiHeader.biSize);
//TRACE1("InfoHeader: Bitmap Width: %ld \n", bmiData.bmiHeader.biWidth);
//TRACE1("InfoHeader: Bitmap Height: %ld \n", bmiData.bmiHeader.biHeight);
//TRACE1("InfoHeader: Bitmap Planes: %u \n", bmiData.bmiHeader.biPlanes);
//TRACE1("InfoHeader: Bitmap Bit Count: %ld \n", bmiData.bmiHeader.biBitCount);
//TRACE1("InfoHeader: Bitmap Clr Used: %u \n", bmiData.bmiHeader.biClrUsed);
//TRACE1("InfoHeader: Bitmap Impt Clrs: %u \n", bmiData.bmiHeader.biClrImportant);

	wNumColors = BMIColorCount(&bmiData.bmiHeader);
	wBMISize = sizeof(BITMAPINFO) + wNumColors*sizeof(RGBQUAD);
	pbmInfo = (BITMAPINFO*)malloc( wBMISize );
	if (wNumColors != 0)
	{
		_fmemcpy( pbmInfo->bmiColors, 
				lpDIB + sizeof(BITMAPINFOHEADER), 
				wNumColors * sizeof(RGBQUAD) );
	}
 	
 	// Finish initializing pbmInfo structure
 	memcpy(pbmInfo, &bmiData.bmiHeader, sizeof(BITMAPINFOHEADER));

	// Now we can read in the actual bitmap bits!
	dwBitsSize = (DWORD)(dwSize - wBMISize);
	
	//TRACE1("Number of bytes of bitmap data: %u\n", m_dwBitsSize);
	if (dwBitsSize > 64000)
	{
		TRACE0("Memory allocation too big for malloc!\n");
		goto FatalError;
	}
	
	pbmBits = (BYTE*)malloc((int)dwBitsSize);
	
	if (pbmBits == NULL)
	{
		TRACE0("Not enough memory for bits!\n");
		goto FatalError;
	}
	
	_fmemcpy( pbmBits, lpDIB + wBMISize, (int)dwBitsSize ); 

	::GlobalUnlock(hgDIB);

	// Destroy (and free) old DIB info
	DestroyDIB();

	// Commit the changes.
	m_pBitmapInfo = pbmInfo;
	m_pBits = pbmBits;
	m_wNumColors = wNumColors;
	m_wBMISize = wBMISize;	
	m_dwBitsSize = dwBitsSize;
	
	return TRUE;
	
FatalError:
	// If a fatal error occurs, clean things up.
	// (Yes, I don't like goto's either, but
	// sometimes it actually increases understanding
	// as in this case).
	
	::GlobalUnlock(hgDIB);

	if (pbmBits != NULL)
		free(pbmBits);
		
	if (pbmInfo != NULL)
		free(pbmInfo);
		
	return FALSE;
}

BOOL CDIBitmap::SaveToHandle(HGLOBAL &hgDIB)
{
	ASSERT( DIBIsLoaded() );

	// Free the memory (if any) currently
	// associated with hgDIB.
	if (hgDIB != NULL)
		::GlobalFree(hgDIB);

	// Allocate enough global memory to accomodate
	// the size of our DIB.
	hgDIB = ::GlobalAlloc( GHND, DIBDataSize() );
	if (hgDIB == NULL)
	{
		TRACE0("SaveToHandle: GlobalAlloc failed!\n");
		return FALSE;
	}
		                   
	// Retrieve a pointer to the global block of memory.
	BYTE FAR* lpDIB = (BYTE FAR*)::GlobalLock(hgDIB);
	
	if (lpDIB == NULL)
	{
		TRACE0("SaveToHandle: GlobalLock failed.\n");
		return FALSE;
	}
	
	// Copy the DIB data into the global block of memory.
	_fmemcpy( lpDIB, m_pBitmapInfo, BitmapInfoSize() );
	_fmemcpy( lpDIB+BitmapInfoSize(), m_pBits, (int)BitsSize() );
	
	// Release the memory -- lpDIB is no longer valid.
	::GlobalUnlock(hgDIB);
	
	// global memory is freed elsewhere
	// in our case, during the ODBC clean up.
	
	return TRUE;
}
	
BOOL CDIBitmap::DrawOnDC (CDC* pDC, int x, int y)
{
	// Make sure bitmap data exists
	ASSERT( DIBIsLoaded() );

	// Call StretchOnDC() with the current 
	// width and height.
	return StretchOnDC(pDC, x, y, 
			(int)m_pBitmapInfo->bmiHeader.biWidth,
			(int)m_pBitmapInfo->bmiHeader.biHeight);
}

BOOL CDIBitmap::StretchOnDC (CDC* pDC, int x, int y,
					int newWidth, int newHeight)
{
	BOOL Result; 

	// Make sure the CDC pointer is usable
	ASSERT_VALID(pDC);
	
	// Make sure bitmap data exists
	ASSERT( DIBIsLoaded() );
	
	// Select and Realize the palette
	CPalette CurPalette;
	CPalette* pOldPalette = NULL;
	if (GetPalette(&CurPalette))
	{
		if (pOldPalette = pDC->SelectPalette(&CurPalette, FALSE))
			pDC->RealizePalette();
		else
			TRACE0("DrawOnDC: Error in Selecting Palette.\n");
	}
	else
	{
		// No palette available.
		TRACE0("DrawOnDC: GetPalette returns FALSE.\n");
	}
	
	// Block transfer the bitmap to the screen
	int Width  = (int)m_pBitmapInfo->bmiHeader.biWidth;
	int Height = (int)m_pBitmapInfo->bmiHeader.biHeight;
	Result = ::StretchDIBits(pDC->GetSafeHdc(),
				x, y, newWidth, newHeight, 0, 0, 
				Width, Height, m_pBits, m_pBitmapInfo, 
				DIB_RGB_COLORS, SRCCOPY);
	
	// return dc to original state
	if (pOldPalette)
		pDC->SelectPalette(pOldPalette, FALSE);

	return Result;
}

#ifdef _DEBUG

void CDIBitmap::AssertValid() const
{
	CObject::AssertValid();
	
	ASSERT( DIBIsLoaded() );
}

void CDIBitmap::Dump( CDumpContext& dc ) const
{
	CObject::Dump(dc);

	if (m_pBitmapInfo == NULL)
	{
		dc << "m_pBitmapInfo == NULL\n\n";
	}
	else
	{
		dc << "\nBITMAPINFOHEADER DATA:\n"
			<< "Size: " << m_pBitmapInfo->bmiHeader.biSize
			<< "\nWidth: " << m_pBitmapInfo->bmiHeader.biWidth
			<< "\nHeight: " << m_pBitmapInfo->bmiHeader.biHeight
			<< "\nPlanes: " << m_pBitmapInfo->bmiHeader.biPlanes
			<< "\nBit Count: " << m_pBitmapInfo->bmiHeader.biBitCount;
		dc << "\nCompression: " << m_pBitmapInfo->bmiHeader.biCompression
			<< "\nImage Size: " << m_pBitmapInfo->bmiHeader.biSizeImage
			<< "\nXPels/Meter: " << m_pBitmapInfo->bmiHeader.biXPelsPerMeter
			<< "\nYPels/Meter: " << m_pBitmapInfo->bmiHeader.biYPelsPerMeter
			<< "\nColors Used: " << m_pBitmapInfo->bmiHeader.biClrUsed
			<< "\nImport. Clrs: " << m_pBitmapInfo->bmiHeader.biClrImportant
			<< "\n\n";
	}
}

#endif


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -