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

📄 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()
{
	return ((m_pBits != NULL) &&
			(m_pBitmapInfo != NULL));
}

WORD CDIBitmap::NumberOfColors()
{
	ASSERT(m_pBits != NULL);
	ASSERT(m_pBitmapInfo != NULL);
	
	return m_wNumColors;
}
	
DWORD CDIBitmap::DIBDataSize()
{
	// ASSERT's will be made in calling routines.

	return BitmapInfoSize() + BitsSize();
}

WORD CDIBitmap::BitmapInfoSize()
{
	ASSERT(m_pBits != NULL);
	ASSERT(m_pBitmapInfo != NULL);
	
	return m_wBMISize;
}

DWORD CDIBitmap::BitsSize()
{
	ASSERT(m_pBits != NULL);
	ASSERT(m_pBitmapInfo != NULL);
	
	return m_dwBitsSize;
}

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

BOOL CDIBitmap::GetPalette(CPalette* pPal)
{
	ASSERT (pPal != NULL);
	ASSERT (m_pBits != NULL);
	ASSERT (m_pBitmapInfo != NULL);
	
	WORD numRGBQUADS = NumberOfColors();
	
	if (numRGBQUADS == 0)
	{
		TRACE0("No palette data available.\n");
		return FALSE;
	}

	LOGPALETTE* pLP = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
			numRGBQUADS*sizeof(PALETTEENTRY));
	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("Palette creation failed!");
		return FALSE;
	}
	
	// We don't need the LOGPALETTE structure anymore
	// since we have the completed CPalette object.
	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) )
	{
		//m_wBMISize = sizeof(BITMAPINFO);
		//pbmInfo = (BITMAPINFO*)malloc(m_wBMISize);
		//m_wNumColors = 0;
		return 0;
	}
	else
	{
		// Compute number of RGBQUAD structures 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;
		}
		
		// Read in the RGB quad data
		//m_wBMISize = sizeof(BITMAPINFO) + numRGBQUADS*sizeof(RGBQUAD);
		//pbmInfo = (BITMAPINFO*)malloc( m_wBMISize );
		//fileDIB.Read(pbmInfo->bmiColors, numRGBQUADS * sizeof(RGBQUAD));
		//m_wNumColors = numRGBQUADS;
		return numRGBQUADS;
        
 	} // end if -- load RGB quads from DIB
}

BOOL CDIBitmap::LoadFromDIB(const char* lpszFileName)
{
	CFile fileDIB;
	CFileException e;

	// Open the file	
	if ( !fileDIB.Open(lpszFileName, CFile::modeRead, &e) )
	{
		TRACE0 ("File could not be opened!\n");
		return FALSE;
	}
    
    //**** Destroy DIB here!?!
    DestroyDIB();
    
	// Store Beginning Of File (BOF) position
	DWORD dwBOF = fileDIB.GetPosition();
    
	// Read in the file header
    BITMAPFILEHEADER fileHeader;
	fileDIB.Read(&fileHeader, sizeof(BITMAPFILEHEADER));
	
	// Make sure its a bitmap file.
	if (fileHeader.bfType != 0x4D42) // 0x4D42 == "BM"
	{
		TRACE0 ("File is not a bitmap!\n");
		fileDIB.Close();
		return FALSE;
	}

	// Read in the info header.
	BITMAPINFOHEADER infoHeader;
	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 ("Presentation Manager bitmaps not supported.\n");
		
		fileDIB.Close();
		return FALSE;
	}
	
	m_wNumColors = BMIColorCount(&infoHeader);
	m_wBMISize = sizeof(BITMAPINFO) + m_wNumColors*sizeof(RGBQUAD);
	BITMAPINFO* pbmInfo = (BITMAPINFO*)malloc( m_wBMISize );
	if (m_wNumColors != 0)
	{
		fileDIB.Read(pbmInfo->bmiColors, m_wNumColors * sizeof(RGBQUAD));
	}
 	
 	// Finish initializing pbmInfo structure
 	memcpy(pbmInfo, &infoHeader, sizeof(BITMAPINFOHEADER));

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

	fileDIB.Close();

//#ifdef _DEBUG	
	//Dump(afxDump);
//#endif

	return TRUE;
}

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

BOOL CDIBitmap::LoadFromHandle(HGLOBAL &hgDIB, DWORD dwSize)
{
	// Make sure handle is valid.
	if (hgDIB == NULL)
	{
		TRACE0("NULL handle was passed to LoadFromHandle().\n");
		return FALSE;
	}

	// Lock memory and retrieve pointer.
	BYTE FAR* lpDIB = (BYTE FAR*)::GlobalLock(hgDIB);
	
	// Get BITMAPINFO structure from block of global memory
	BITMAPINFO bmiData;
	_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");
		
		::GlobalUnlock(hgDIB);
		return FALSE;
	}

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

	// Remove and reallocate any remenants of an old DIB.
	DestroyDIB();

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

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

	::GlobalUnlock(hgDIB);

	m_pBitmapInfo = pbmInfo;
	m_pBits = pbmBits;

//#ifdef _DEBUG	
//	Dump(afxDump);
//#endif

	return TRUE;
}

BOOL CDIBitmap::SaveToHandle(HGLOBAL &hgDIB)
{
	ASSERT(m_pBitmapInfo != NULL);
	ASSERT(m_pBits != NULL);

	if (hgDIB != NULL)
		::GlobalFree(hgDIB); // perhaps GlobalRealloc()?
	
	hgDIB = ::GlobalAlloc( GHND, DIBDataSize() );
	if (hgDIB == NULL)
	{
		TRACE0("GlobalAlloc failed!\n");
		return FALSE;
	}
		
	BYTE FAR* lpDIB = (BYTE FAR*)::GlobalLock(hgDIB);
	
	_fmemcpy( lpDIB, m_pBitmapInfo, BitmapInfoSize() );
	_fmemcpy( lpDIB+BitmapInfoSize(), m_pBits, (int)BitsSize() );
	
	if (::GlobalUnlock(hgDIB) != NULL)
		ASSERT(FALSE);
	
	// memory is freed elsewhere
	// in our case, during the ODBC clean up.
	
	return TRUE;
}
	
BOOL CDIBitmap::DrawOnDC (CDC* pDC, int x, int y)
{
	BOOL Result; 

	// Make sure the CDC pointer is valid
	if (!pDC)
	{
		TRACE0("NULL CDC pointer passed to DrawOnDC().\n");
		return FALSE;
	}
	
	// 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
	{
		TRACE0("DrawOnDC: GetPalette returns FALSE.\n");
	}
	
	// Block transfer the bitmap to the screen
	if (m_pBitmapInfo != NULL)
	{
		int Width = (int)m_pBitmapInfo->bmiHeader.biWidth;
		int Height = (int)m_pBitmapInfo->bmiHeader.biHeight;
		Result = ::StretchDIBits(pDC->GetSafeHdc(),
				x, y, Width, Height, 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();
}

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 + -