#include "stdafx.h" #include "CeXDib.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif CCeXDib::CCeXDib() { m_hDib = NULL; m_dwLineWidth = 0; m_wColors = 0; m_hMemDC = NULL; m_hBitmap = NULL; m_lpBits = NULL; FreeResources(); } CCeXDib::~CCeXDib() { FreeResources(); } void CCeXDib::FreeResources() { if (m_hMemDC) ::DeleteDC(m_hMemDC); if (m_hBitmap) ::DeleteObject(m_hBitmap); if (m_hDib) delete m_hDib; m_hDib = NULL; m_hMemDC = NULL; m_hBitmap = NULL; m_lpBits = NULL; memset(&m_bi, 0, sizeof(m_bi)); } // End of FreeResources HDIB CCeXDib::Create(DWORD dwWidth, DWORD dwHeight, WORD wBitCount) { LPBITMAPINFOHEADER lpbi = NULL; // Pointer to BITMAPINFOHEADER DWORD dwLen = 0; // Size of memory block FreeResources(); // Following is taken from // CDIBSectionLite class by Chris Maunder switch (wBitCount) { case 1: m_wColors = 2; break; #ifdef _WIN32_WCE case 2: m_wColors = 4; break; // winCE only #endif case 4: m_wColors = 16; break; case 8: m_wColors = 256; break; case 16: case 24: case 32: m_wColors = 0; break; // 16,24 or 32 bpp have no color table default: m_wColors = 0; } // switch /* // Make sure bits per pixel is valid if (wBitCount <= 1) wBitCount = 1; else if (wBitCount <= 4) wBitCount = 4; else if (wBitCount <= 8) wBitCount = 8; else wBitCount = 24; switch (wBitCount) { case 1: m_wColors = 2; break; case 4: m_wColors = 16; break; case 8: m_wColors = 256; break; default: m_wColors = 0; break; } // switch */ m_dwLineWidth = WIDTHBYTES(wBitCount * dwWidth); // Initialize BITMAPINFOHEADER m_bi.biSize = sizeof(BITMAPINFOHEADER); m_bi.biWidth = dwWidth; // fill in width from parameter m_bi.biHeight = dwHeight; // fill in height from parameter m_bi.biPlanes = 1; // must be 1 m_bi.biBitCount = wBitCount; // from parameter m_bi.biCompression = BI_RGB; m_bi.biSizeImage = m_dwLineWidth * dwHeight; m_bi.biXPelsPerMeter = 0; m_bi.biYPelsPerMeter = 0; m_bi.biClrUsed = 0; m_bi.biClrImportant = 0; // Calculate size of memory block required to store the DIB. This // block should be big enough to hold the BITMAPINFOHEADER, the color // table, and the bits. dwLen = GetSize(); m_hDib = new HDIB[dwLen]; // Allocate memory block to store our bitmap if (m_hDib == NULL) return NULL; // Use our bitmap info structure to fill in first part of // our DIB with the BITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)(m_hDib); *lpbi = m_bi; return m_hDib; // Return handle to the DIB } // End of Create DWORD CCeXDib::GetSize() { return m_bi.biSize + m_bi.biSizeImage + GetPaletteSize(); } // End of GetSize DWORD CCeXDib::GetPaletteSize() { return (m_wColors * sizeof(RGBQUAD)); } // End of GetPaletteSize LPBYTE CCeXDib::GetBits() { if (m_hDib) return ((LPBYTE)m_hDib + *(LPDWORD)m_hDib + GetPaletteSize()); return NULL; } // End of GetBits DWORD CCeXDib::GetWidth() { return m_bi.biWidth; } // End of GetWidth DWORD CCeXDib::GetHeight() { return m_bi.biHeight; } // End of GetHeight DWORD CCeXDib::GetLineWidth() { return m_dwLineWidth; } // End of GetLineWidth void CCeXDib::BlendPalette(COLORREF crColor, DWORD dwPerc) { if (m_hDib == NULL || m_wColors == 0) return; LPBYTE iDst = (LPBYTE)(m_hDib) + sizeof(BITMAPINFOHEADER); long i,r,g,b; RGBQUAD* pPal = (RGBQUAD*)iDst; r = GetRValue(crColor); g = GetGValue(crColor); b = GetBValue(crColor); if (dwPerc > 100) dwPerc = 100; for (i = 0; i < m_wColors; i++) { pPal[i].rgbBlue = (BYTE)((pPal[i].rgbBlue * (100 - dwPerc) + b * dwPerc) / 100); pPal[i].rgbGreen = (BYTE)((pPal[i].rgbGreen * (100 - dwPerc) + g * dwPerc) / 100); pPal[i].rgbRed = (BYTE)((pPal[i].rgbRed * (100 - dwPerc) + r * dwPerc) / 100); } // for } // End of BlendPalette void CCeXDib::Clear(BYTE byVal) { if (m_hDib) memset(GetBits(), byVal, m_bi.biSizeImage); } // End of Clear void CCeXDib::SetPixelIndex(DWORD dwX, DWORD dwY, BYTE byI) { if ((m_hDib == NULL) || (m_wColors == 0) || ((long)dwX < 0) || ((long)dwY < 0) || (dwX >= (DWORD)m_bi.biWidth) || (dwY >= (DWORD)m_bi.biHeight)) return; LPBYTE iDst = GetBits(); iDst[(m_bi.biHeight - dwY - 1) * m_dwLineWidth + dwX] = byI; } // End of SetPixelIndex void CCeXDib::Clone(CCeXDib* src) { Create(src->GetWidth(), src->GetHeight(), src->GetBitCount()); if (m_hDib) memcpy(m_hDib, src->m_hDib, GetSize()); } // End of Clone WORD CCeXDib::GetBitCount() { return m_bi.biBitCount; } // End of GetBitCount void CCeXDib::SetPaletteIndex(BYTE byIdx, BYTE byR, BYTE byG, BYTE byB) { if (m_hDib && m_wColors) { LPBYTE iDst = (LPBYTE)(m_hDib) + sizeof(BITMAPINFOHEADER); if ((byIdx >= 0) && (byIdx < m_wColors)) { long ldx = byIdx * sizeof(RGBQUAD); iDst[ldx++] = (BYTE)byB; iDst[ldx++] = (BYTE)byG; iDst[ldx++] = (BYTE)byR; iDst[ldx] = (BYTE)0; } // if } // if } // End of SetPaletteIndex void CCeXDib::Draw(HDC hDC, DWORD dwX, DWORD dwY) { HBITMAP hBitmap = NULL; HBITMAP hOldBitmap = NULL; HDC hMemDC = NULL; if (m_hBitmap == NULL) { m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)m_hDib, DIB_RGB_COLORS, &m_lpBits, NULL, 0); if (m_hBitmap == NULL) return; if (m_lpBits == NULL) { ::DeleteObject(m_hBitmap); m_hBitmap = NULL; return; } // if } // if memcpy(m_lpBits, GetBits(), m_bi.biSizeImage); if (m_hMemDC == NULL) { m_hMemDC = CreateCompatibleDC(hDC); if (m_hMemDC == NULL) return; } // if hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap); BitBlt(hDC, dwX, dwY, m_bi.biWidth, m_bi.biHeight, m_hMemDC, 0, 0, SRCCOPY); SelectObject(m_hMemDC, hOldBitmap); } // End of Draw void CCeXDib::SetGrayPalette() { RGBQUAD pal[256]; RGBQUAD* ppal; LPBYTE iDst; int ni; if (m_hDib == NULL || m_wColors == 0) return; ppal = (RGBQUAD*)&pal[0]; iDst = (LPBYTE)(m_hDib) + sizeof(BITMAPINFOHEADER); for (ni = 0; ni < m_wColors; ni++) { pal[ni] = RGB2RGBQUAD(RGB(ni,ni,ni)); } // for pal[0] = RGB2RGBQUAD(RGB(0,0,0)); pal[m_wColors-1] = RGB2RGBQUAD(RGB(255,255,255)); memcpy(iDst, ppal, GetPaletteSize()); } // End of SetGrayPalette RGBQUAD CCeXDib::RGB2RGBQUAD(COLORREF cr) { RGBQUAD c; c.rgbRed = GetRValue(cr); /* get R, G, and B out of DWORD */ c.rgbGreen = GetGValue(cr); c.rgbBlue = GetBValue(cr); c.rgbReserved=0; return c; } // End of RGB2RGBQUAD WORD CCeXDib::GetNumColors() { return m_wColors; } // End of GetNumColors BOOL CCeXDib::WriteBMP(LPCTSTR bmpFileName) { BITMAPFILEHEADER hdr; HANDLE hFile; DWORD nByteWrite; if (*bmpFileName == _T('\0') || m_hDib == 0) return 0; hFile=CreateFile( // open if exist ini file bmpFileName, // pointer to name of the file GENERIC_WRITE, // access mode 0, // share mode NULL, // pointer to security descriptor CREATE_ALWAYS, // how to create FILE_ATTRIBUTE_NORMAL, // file attributes NULL // handle to file with attributes to copy ); if (hFile == INVALID_HANDLE_VALUE) return FALSE; // Fill in the fields of the file header hdr.bfType = BFT_BITMAP; hdr.bfSize = GetSize() + sizeof(BITMAPFILEHEADER); hdr.bfReserved1 = hdr.bfReserved2 = 0; hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER)+ m_bi.biSize + GetPaletteSize(); // Write the file header WriteFile( // write ini (sync mode <-> no overlapped) hFile, // handle of file to write (LPSTR) &hdr, // address of buffer that contains data sizeof(BITMAPFILEHEADER), // number of bytes to write &nByteWrite, // address of number of bytes written NULL // address of structure for data ); // Write the DIB header and the bits WriteFile( // write ini (sync mode <-> no overlapped) hFile, // handle of file to write (LPSTR) m_hDib, // address of buffer that contains data GetSize(), // number of bytes to write &nByteWrite, // address of number of bytes written NULL // address of structure for data ); CloseHandle(hFile); // free file handle return TRUE; } // End of WriteBMP