📄 cdib.cpp
字号:
// cdib.cpp// new version for WIN32#include "stdafx.h"#include "cdib.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifIMPLEMENT_SERIAL(CDib, CObject, 0);CDib::CDib(){ m_hFile = NULL; m_hBitmap = NULL; m_hPalette = NULL; m_nBmihAlloc = m_nImageAlloc = noAlloc; Empty();}CDib::CDib(CSize size, int nBitCount){ m_hFile = NULL; m_hBitmap = NULL; m_hPalette = NULL; m_nBmihAlloc = m_nImageAlloc = noAlloc; Empty(); ComputePaletteSize(nBitCount); m_lpBMIH = (LPBITMAPINFOHEADER) new char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries]; m_nBmihAlloc = crtAlloc; m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER); m_lpBMIH->biWidth = size.cx; m_lpBMIH->biHeight = size.cy; m_lpBMIH->biPlanes = 1; m_lpBMIH->biBitCount = nBitCount; m_lpBMIH->biCompression = BI_RGB; m_lpBMIH->biSizeImage = 0; m_lpBMIH->biXPelsPerMeter = 0; m_lpBMIH->biYPelsPerMeter = 0; m_lpBMIH->biClrUsed = m_nColorTableEntries; m_lpBMIH->biClrImportant = m_nColorTableEntries; ComputeMetrics(); memset(m_lpvColorTable, 0, sizeof(RGBQUAD) * m_nColorTableEntries); m_lpImage = NULL; // no data yet}CDib::~CDib(){ Empty();}CSize CDib::GetDimensions(){ if(m_lpBMIH == NULL) return CSize(0, 0); return CSize((int) m_lpBMIH->biWidth, (int) m_lpBMIH->biHeight);}BOOL CDib::AttachMapFile(const char* strPathname, BOOL bShare) // for reading{ // if we open the same file twice, Windows treats it as 2 separate files // doesn't work with rare BMP files where # palette entries > biClrUsed HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ, bShare ? FILE_SHARE_READ : 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ASSERT(hFile != INVALID_HANDLE_VALUE); DWORD dwFileSize = ::GetFileSize(hFile, NULL); HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); DWORD dwErr = ::GetLastError(); if(hMap == NULL) { AfxMessageBox("Empty bitmap file"); return FALSE; } LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // map whole file ASSERT(lpvFile != NULL); if(((LPBITMAPFILEHEADER) lpvFile)->bfType != 0x4d42) { AfxMessageBox("Invalid bitmap file"); DetachMapFile(); return FALSE; } AttachMemory((LPBYTE) lpvFile + sizeof(BITMAPFILEHEADER)); m_lpvFile = lpvFile; m_hFile = hFile; m_hMap = hMap; return TRUE;}BOOL CDib::CopyToMapFile(const char* strPathname){ // copies DIB to a new file, releases prior pointers // if you previously used CreateSection, the HBITMAP will be NULL (and unusable) BITMAPFILEHEADER bmfh; bmfh.bfType = 0x4d42; // 'BM' bmfh.bfSize = m_dwSizeImage + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries + sizeof(BITMAPFILEHEADER); // meaning of bfSize open to interpretation bmfh.bfReserved1 = bmfh.bfReserved2 = 0; bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries; HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); ASSERT(hFile != INVALID_HANDLE_VALUE); int nSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries + m_dwSizeImage; HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, nSize, NULL); DWORD dwErr = ::GetLastError(); ASSERT(hMap != NULL); LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // map whole file ASSERT(lpvFile != NULL); LPBYTE lpbCurrent = (LPBYTE) lpvFile; memcpy(lpbCurrent, &bmfh, sizeof(BITMAPFILEHEADER)); // file header lpbCurrent += sizeof(BITMAPFILEHEADER); LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) lpbCurrent; memcpy(lpbCurrent, m_lpBMIH, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries); // info lpbCurrent += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries; memcpy(lpbCurrent, m_lpImage, m_dwSizeImage); // bit image DWORD dwSizeImage = m_dwSizeImage; Empty(); m_dwSizeImage = dwSizeImage; m_nBmihAlloc = m_nImageAlloc = noAlloc; m_lpBMIH = lpBMIH; m_lpImage = lpbCurrent; m_hFile = hFile; m_hMap = hMap; m_lpvFile = lpvFile; ComputePaletteSize(m_lpBMIH->biBitCount); ComputeMetrics(); MakePalette(); return TRUE;}BOOL CDib::AttachMemory(LPVOID lpvMem, BOOL bMustDelete, HGLOBAL hGlobal){ // assumes contiguous BITMAPINFOHEADER, color table, image // color table could be zero length Empty(); m_hGlobal = hGlobal; if(bMustDelete == FALSE) { m_nBmihAlloc = noAlloc; } else { m_nBmihAlloc = ((hGlobal == NULL) ? crtAlloc : heapAlloc); } try { m_lpBMIH = (LPBITMAPINFOHEADER) lpvMem; ComputeMetrics(); ComputePaletteSize(m_lpBMIH->biBitCount); m_lpImage = (LPBYTE) m_lpvColorTable + sizeof(RGBQUAD) * m_nColorTableEntries; MakePalette(); } catch(CException* pe) { AfxMessageBox("AttachMemory error"); pe->Delete(); return FALSE; } return TRUE;}UINT CDib::UsePalette(CDC* pDC, BOOL bBackground /* = FALSE */){ if(m_hPalette == NULL) return 0; HDC hdc = pDC->GetSafeHdc(); ::SelectPalette(hdc, m_hPalette, bBackground); return ::RealizePalette(hdc);}BOOL CDib::Draw(CDC* pDC, CPoint origin, CSize size){ if(m_lpBMIH == NULL) return FALSE; if(m_hPalette != NULL) { ::SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE); } pDC->SetStretchBltMode(COLORONCOLOR); ::StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy, 0, 0, m_lpBMIH->biWidth, m_lpBMIH->biHeight, m_lpImage, (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS, SRCCOPY); return TRUE;}HBITMAP CDib::CreateSection(CDC* pDC /* = NULL */){ if(m_lpBMIH == NULL) return NULL; if(m_lpImage != NULL) return NULL; // can only do this if image doesn't exist m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS, (LPVOID*) &m_lpImage, NULL, 0); ASSERT(m_lpImage != NULL); return m_hBitmap;}BOOL CDib::MakePalette(){ // makes a logical palette (m_hPalette) from the DIB's color table // this palette will be selected and realized prior to drawing the DIB if(m_nColorTableEntries == 0) return FALSE; if(m_hPalette != NULL) ::DeleteObject(m_hPalette); TRACE("CDib::MakePalette -- m_nColorTableEntries = %d\n", m_nColorTableEntries); LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) + m_nColorTableEntries * sizeof(PALETTEENTRY)]; pLogPal->palVersion = 0x300; pLogPal->palNumEntries = m_nColorTableEntries; LPRGBQUAD pDibQuad = (LPRGBQUAD) m_lpvColorTable; for(int i = 0; i < m_nColorTableEntries; i++) { pLogPal->palPalEntry[i].peRed = pDibQuad->rgbRed; pLogPal->palPalEntry[i].peGreen = pDibQuad->rgbGreen; pLogPal->palPalEntry[i].peBlue = pDibQuad->rgbBlue; pLogPal->palPalEntry[i].peFlags = 0; pDibQuad++; } m_hPalette = ::CreatePalette(pLogPal); delete pLogPal; return TRUE;} BOOL CDib::SetSystemPalette(CDC* pDC){ // if the DIB doesn't have a color table, we can use the system's halftone palette if(m_nColorTableEntries != 0) return FALSE; m_hPalette = ::CreateHalftonePalette(pDC->GetSafeHdc()); return TRUE;}HBITMAP CDib::CreateBitmap(CDC* pDC){ if (m_dwSizeImage == 0) return NULL; HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), m_lpBMIH, CBM_INIT, m_lpImage, (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS); ASSERT(hBitmap != NULL); return hBitmap;}BOOL CDib::Compress(CDC* pDC, BOOL bCompress /* = TRUE */){ // 1. makes GDI bitmap from existing DIB // 2. makes a new DIB from GDI bitmap with compression // 3. cleans up the original DIB // 4. puts the new DIB in the object if((m_lpBMIH->biBitCount != 4) && (m_lpBMIH->biBitCount != 8)) return FALSE; // compression supported only for 4 bpp and 8 bpp DIBs if(m_hBitmap) return FALSE; // can't compress a DIB Section! TRACE("Compress: original palette size = %d\n", m_nColorTableEntries); HDC hdc = pDC->GetSafeHdc(); HPALETTE hOldPalette = ::SelectPalette(hdc, m_hPalette, FALSE); HBITMAP hBitmap; // temporary if((hBitmap = CreateBitmap(pDC)) == NULL) return FALSE; int nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries; LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) new char[nSize]; memcpy(lpBMIH, m_lpBMIH, nSize); // new header if(bCompress) { switch (lpBMIH->biBitCount) { case 4: lpBMIH->biCompression = BI_RLE4; break; case 8: lpBMIH->biCompression = BI_RLE8; break; default: ASSERT(FALSE); } // calls GetDIBits with null data pointer to get size of compressed DIB if(!::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight, NULL, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS)) { AfxMessageBox("Unable to compress this DIB"); // probably a problem with the color table ::DeleteObject(hBitmap); delete [] lpBMIH; ::SelectPalette(hdc, hOldPalette, FALSE); return FALSE; } if (lpBMIH->biSizeImage == 0) { AfxMessageBox("Driver can't do compression");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -