#include "Bitmap.h"
Bitmap::Bitmap() : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0)
{

}
Bitmap::Bitmap(HDC hDC, LPTSTR szFileName) : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0)
{
	Create(hDC, szFileName); 
}
Bitmap::Bitmap(HDC hDC, UINT uiResID, HINSTANCE hInstance) : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0)
{
	Create(hDC, uiResID, hInstance); 
}
Bitmap::Bitmap(HDC hDC, int iWidth, int iHeight, COLORREF crColor) : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0)
{
	Create(hDC, iWidth, iHeight, crColor); 
}
Bitmap::~Bitmap()
{
	Free(); 
}
void Bitmap::Free()
{
	// Delete the bitmap graphics object
	if(m_hBitmap != NULL)
	{
		DeleteObject(m_hBitmap);
		m_hBitmap = NULL;
	}
}
BOOL Bitmap::Create(HDC hDC, LPTSTR szFileName)
{
	char szTemp[64] = {0};

	Free();// Free any previous bitmap info

	HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,	// Open the bitmap file
								OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if(hFile == INVALID_HANDLE_VALUE)
	{
		sprintf(szTemp, "Could not open %s!\nCould not locate the file.", szFileName);
		MessageBox(NULL, szTemp, "Error in loading BMPs", MB_OK);
		return FALSE;
	}//end: if (hFile == INVALID_HANDLE_VALUE)
	
	//Read the bitmap file header
	BITMAPFILEHEADER  bmpfHeader;
	DWORD             dwBytesRead;
	
	BOOL bOK = ReadFile(hFile, &bmpfHeader, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL);

	if((!bOK) || (dwBytesRead != sizeof(BITMAPFILEHEADER)) || (bmpfHeader.bfType != 0x4D42))
	{ CloseHandle(hFile); return FALSE; }

	BITMAPINFO* pBitmapInfo = (new BITMAPINFO);

	if(pBitmapInfo != NULL)
	{
		// Read the bitmap info header
		bOK = ReadFile(hFile, pBitmapInfo, sizeof(BITMAPINFOHEADER), &dwBytesRead, NULL);
		if ((!bOK) || (dwBytesRead != sizeof(BITMAPINFOHEADER))) { CloseHandle(hFile); Free(); return FALSE;  }
		// Store the width and height of the bitmap
		m_iWidth	= (int)pBitmapInfo->bmiHeader.biWidth;
		m_iHeight	= (int)pBitmapInfo->bmiHeader.biHeight;
		
		// Get a handle to the bitmap and copy the image bits
		PBYTE pBitmapBits;
		m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS, (PVOID*)&pBitmapBits, NULL, 0);
		
		if ((m_hBitmap != NULL) && (pBitmapBits != NULL))
		{
			SetFilePointer(hFile, bmpfHeader.bfOffBits, NULL, FILE_BEGIN);
			bOK = ReadFile(hFile, pBitmapBits, pBitmapInfo->bmiHeader.biSizeImage, &dwBytesRead, NULL);
			if (bOK) return TRUE;
		}
	}
	// Something went wrong, so cleanup everything
	Free(); return FALSE;
}
BOOL Bitmap::Create(HDC hDC, UINT uiResID, HINSTANCE hInstance)
{
	Free();// Free any previous DIB info
	
	// Find the bitmap resource
	HRSRC hResInfo = FindResource(hInstance, MAKEINTRESOURCE(uiResID), RT_BITMAP);
	
	if (hResInfo == NULL) return FALSE;
	
	// Load the bitmap resource
	HGLOBAL hMemBitmap = LoadResource(hInstance, hResInfo);
	if (hMemBitmap == NULL) return FALSE;
	
	// Lock the resource and access the entire bitmap image
	PBYTE pBitmapImage = (BYTE*)LockResource(hMemBitmap);
	if (pBitmapImage == NULL) { FreeResource(hMemBitmap); return FALSE; }
	
	// Store the width and height of the bitmap
	BITMAPINFO* pBitmapInfo = (BITMAPINFO*)pBitmapImage;
	m_iWidth	= (int)pBitmapInfo->bmiHeader.biWidth;
	m_iHeight	= (int)pBitmapInfo->bmiHeader.biHeight;
	
	// Get a handle to the bitmap and copy the image bits
	PBYTE pBitmapBits;
	m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS, (PVOID*)&pBitmapBits, NULL, 0);
	if ((m_hBitmap != NULL) && (pBitmapBits != NULL))
	{
		const PBYTE pTempBits = pBitmapImage + pBitmapInfo->bmiHeader.biSize +
								pBitmapInfo->bmiHeader.biClrUsed * sizeof(RGBQUAD);
		CopyMemory(pBitmapBits, pTempBits, pBitmapInfo->bmiHeader.biSizeImage);
		// Unlock and free the bitmap graphics object
		UnlockResource(hMemBitmap);
		FreeResource(hMemBitmap);
		return TRUE;
	}

	// Something went wrong, so cleanup everything
	UnlockResource(hMemBitmap);
	FreeResource(hMemBitmap);
	Free();
	return FALSE;
}
BOOL Bitmap::Create(HDC hDC, int iWidth, int iHeight, COLORREF crColor)
{
	// Create a blank bitmap

	m_hBitmap			= CreateCompatibleBitmap(hDC, iWidth, iHeight);
	if (m_hBitmap == NULL) return FALSE;
	m_iWidth			= iWidth;						// Set the width and height
	m_iHeight			= iHeight;
	HDC hMemDC			= CreateCompatibleDC(hDC);		// Create a memory device context
	HBRUSH hBrush		= CreateSolidBrush(crColor);	// Create a solid brush
	HBITMAP hOldBitmap	= (HBITMAP)SelectObject(hMemDC, m_hBitmap);// Select the bitmap
	// Fill the bitmap with a solid color
	RECT rcBitmap		= { 0, 0, m_iWidth, m_iHeight };
	FillRect(hMemDC, &rcBitmap, hBrush);
	// Cleanup
	SelectObject(hMemDC, hOldBitmap);
	DeleteDC(hMemDC);
	DeleteObject(hBrush);
	return TRUE;
}
void Bitmap::Draw(HDC hDC, int x, int y, BOOL bTrans, COLORREF crTransColor)
{
	DrawPart(hDC, x, y, 0, 0, m_iWidth, m_iHeight, bTrans, crTransColor);
}
void Bitmap::DrawPart(HDC hDC, int x, int y, int xPart, int yPart, int wPart, 
					  int hPart, BOOL bTrans, COLORREF crTransColor)
{
	if (m_hBitmap != NULL)
	{
		// Create a memory device context for the bitmap
		HDC LocalDC = CreateCompatibleDC(hDC);
		// Select the bitmap into the device context
		HBITMAP hOldBitmap = (HBITMAP)SelectObject(LocalDC, m_hBitmap);
		// Draw the bitmap to the destination device context
		if(bTrans)	TransparentBlt(hDC, x, y, wPart, hPart, LocalDC, xPart, yPart, wPart, hPart, crTransColor);
		else		BitBlt(hDC, x, y, wPart, hPart, LocalDC, xPart, yPart, SRCCOPY);

		// Restore and delete the memory device context
		SelectObject(LocalDC, hOldBitmap);
		DeleteDC(LocalDC);
	}
}
/*
PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)
{
	BITMAP		bmp;
	PBITMAPINFO	pbmi; 
    WORD		cClrBits; 

    //Retrieve the bitmap color format, width, and height. 
    if(!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) errhandler("GetObject", hwnd); 

    // Convert the color format to a count of bits. 
    cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
    if		(cClrBits == 1)		cClrBits = 1; 
    else if	(cClrBits <= 4)		cClrBits = 4; 
    else if	(cClrBits <= 8)		cClrBits = 8; 
    else if	(cClrBits <= 16)	cClrBits = 16; 
    else if	(cClrBits <= 24)	cClrBits = 24; 
    else						cClrBits = 32; 

    //Allocate memory for the BITMAPINFO structure (This structure contains
	//a BITMAPINFOHEADER structure and an array of RGBQUAD data structures).
     if (cClrBits != 24) pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
		 sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << cClrBits));
     // There is no RGBQUAD array for the 24-bit-per-pixel format. 
     else pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER)); 

    // Initialize the fields in the BITMAPINFO structure. 
    pbmi->bmiHeader.biSize			= sizeof(BITMAPINFOHEADER); 
    pbmi->bmiHeader.biWidth			= bmp.bmWidth; 
    pbmi->bmiHeader.biHeight		= bmp.bmHeight; 
    pbmi->bmiHeader.biPlanes		= bmp.bmPlanes; 
    pbmi->bmiHeader.biBitCount		= bmp.bmBitsPixel; 
    if (cClrBits < 24) pbmi->bmiHeader.biClrUsed = (1 << cClrBits); 

    // If the bitmap is not compressed, set the BI_RGB flag. 
    pbmi->bmiHeader.biCompression	= BI_RGB; 

    //Compute the number of bytes in the array of color indices and store the 
	//result in biSizeImage. For Windows NT, the width must be DWORD aligned 
	//unless the bitmap is RLE compressed. This example shows this. For Windows 
	//95/98/Me, the width must be WORD aligned unless the bitmap is RLE compressed.
    pbmi->bmiHeader.biSizeImage = 
		((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) / 8 * pbmi->bmiHeader.biHeight; 
    // Set biClrImportant to 0, indicating that all of the 
    // device colors are important. 
     pbmi->bmiHeader.biClrImportant = 0; 
     return pbmi; 
 } 
//The following example code defines a function that initializes the remaining 
//structures, retrieves the array of palette indices, opens the file, copies 
//the data, and closes the file. 
void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC) 
{
	HANDLE				hf;			//file handle 
	BITMAPFILEHEADER	hdr;		//bitmap file-header 
	PBITMAPINFOHEADER	pbih;		//bitmap info-header 
	LPBYTE				lpBits;		//memory pointer 
	DWORD				dwTotal;	//total count of bytes 
	DWORD				cb;			//incremental count of bytes 
	BYTE				*hp;		//byte pointer 
	DWORD				dwTmp; 

	pbih	= (PBITMAPINFOHEADER) pbi; 
	lpBits	= (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
	
	if(!lpBits) errhandler("GlobalAlloc", hwnd); 
	
	//Retrieve the color table (RGBQUAD array) and the
	//bits (array of palette indices) from the DIB. 
	if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, DIB_RGB_COLORS)) 
		errhandler("GetDIBits", hwnd);
	
	//Create the .BMP file. 
	hf = 
		CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, (DWORD) 0, NULL,
					CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); 
	if(hf == INVALID_HANDLE_VALUE) errhandler("CreateFile", hwnd); 

	hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" 
	
	//Compute the size of the entire file. 
	hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
						pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih->biSizeImage);
	
	hdr.bfReserved1 = 0; hdr.bfReserved2 = 0; 
	
	//Compute the offset to the array of color indices. 
	hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
		pbih->biSize + pbih->biClrUsed * sizeof (RGBQUAD); 
	
	//Copy the BITMAPFILEHEADER into the .BMP file. 
	if(!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp,  NULL)) 
		errhandler("WriteFile", hwnd);
	
	//Copy the BITMAPINFOHEADER and RGBQUAD array into the file. 
	if(!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + 
		pbih->biClrUsed * sizeof (RGBQUAD), (LPDWORD) &dwTmp, ( NULL))
		errhandler("WriteFile", hwnd);
	
	//Copy the array of color indices into the .BMP file. 
	dwTotal = cb = pbih->biSizeImage; 
	hp = lpBits; 
	if(!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) 
		errhandler("WriteFile", hwnd); 
	
	//Close the .BMP file. 
	if (!CloseHandle(hf)) errhandler("CloseHandle", hwnd); 
    
	//Free memory. 
	GlobalFree((HGLOBAL)lpBits);
}*/