📄 dib.cpp
字号:
/* * * dib.cpp * * Copyright (C) 2006 Michael H. Overlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact at poster_printer@yahoo.com * */#include "dib.h"#include "mathutils.h"#include "utils.h"DWORD CalculateDWORDAligned(IN DWORD dw) ;DWORD CalculateBytesPerLine(IN DWORD dwPixelsPerLine) ;// *************************************************************************************************// ** class DibFromMemory ************************************************************************// *************************************************************************************************DibFromMemory::DibFromMemory(void) : m_bInited(FALSE), m_pbi(NULL), m_pBits(NULL) { m_szd_Inches.cx = m_szd_Inches.cy = m_ptdLogPix.x = m_ptdLogPix.y = 0;}DibFromMemory::~DibFromMemory() { // NOTHING TO DELETE}BOOL DibFromMemory::Init(const void *pMemImage, DWORD dwImageSize) { BOOL bRetValue = FALSE; const BITMAPFILEHEADER *pbfh = (const BITMAPFILEHEADER *) pMemImage; if (pbfh->bfType == 0x4d42 && pbfh->bfSize == dwImageSize && pbfh->bfReserved1 == 0 && pbfh->bfReserved2 == 0 ) { m_pBits = (PCBYTE) pMemImage + pbfh->bfOffBits; DWORD dwOffset = sizeof(*pbfh); m_pbi = (const BITMAPINFO*) ( (PCBYTE) pMemImage + dwOffset ); if (m_pbi->bmiHeader.biSize == sizeof(m_pbi->bmiHeader)) { m_sz_Pixels.cx = m_pbi->bmiHeader.biWidth; m_sz_Pixels.cy = m_pbi->bmiHeader.biHeight; BOOL bGotLogPix = FALSE; if (m_pbi->bmiHeader.biXPelsPerMeter != 0 && m_pbi->bmiHeader.biYPelsPerMeter != 0 ) { m_ptdLogPix.x = (double) m_pbi->bmiHeader.biXPelsPerMeter * MM_PER_INCH / 1000; m_ptdLogPix.y = (double) m_pbi->bmiHeader.biYPelsPerMeter * MM_PER_INCH / 1000; bGotLogPix = TRUE; } else { HDC hdcRef = ::GetDC(NULL); if (hdcRef != NULL) { int hs = ::GetDeviceCaps(hdcRef, HORZSIZE); int vs = ::GetDeviceCaps(hdcRef, VERTSIZE); int hr = ::GetDeviceCaps(hdcRef, HORZRES); int vr = ::GetDeviceCaps(hdcRef, VERTRES); ::ReleaseDC(NULL, hdcRef); m_ptdLogPix.x = (double) hr / hs * MM_PER_INCH; m_ptdLogPix.y = (double) vr / vs * MM_PER_INCH; bGotLogPix = TRUE; } } if (bGotLogPix) { m_szd_Inches.cx = m_pbi->bmiHeader.biWidth / m_ptdLogPix.x; m_szd_Inches.cy = m_pbi->bmiHeader.biHeight / m_ptdLogPix.y; bRetValue = TRUE; } } } if (bRetValue) { m_bInited = TRUE; } return bRetValue;}int DibFromMemory::StretchDIBits(HDC hdc, const RECT& rDest, const RECT& rSrc, DWORD dwRop) const { ASSERT(m_bInited); int kRetValue = ::StretchDIBits( hdc, rDest.left, rDest.top, RW(rDest), RH(rDest), rSrc.left, rSrc.top, RW(rSrc), RH(rSrc), m_pBits, m_pbi, DIB_RGB_COLORS, dwRop ); return kRetValue;}int DibFromMemory::StretchDIBits( HDC hdc, int xDest, int yDest, int cxDest, int cyDest, int xSrc, int ySrc, int cxSrc, int cySrc, DWORD dwRop) const { ASSERT(m_bInited); int kRetValue = ::StretchDIBits( hdc, xDest, yDest, cxDest, cyDest, xSrc, ySrc, cxSrc, cySrc, m_pBits, m_pbi, DIB_RGB_COLORS, dwRop ); return kRetValue;}const POINTD& DibFromMemory::GetLogPix(void) const { ASSERT(m_bInited); return m_ptdLogPix; }const SIZED& DibFromMemory::GetSize_Inches(void) const { ASSERT(m_bInited); return m_szd_Inches; }const SIZE& DibFromMemory::GetSize_Pixels(void) const { ASSERT(m_bInited); return m_sz_Pixels; }// *************************************************************************************************// ** class DibFromFileMap ***********************************************************************// *************************************************************************************************DibFromFileMap::DibFromFileMap(void) { // NOTHING TO DO}DibFromFileMap::~DibFromFileMap() { // NOTHING TO DO}BOOL DibFromFileMap::Open(const tstring& tstrFileName) { BOOL bRetValue = FALSE; try { if (m_mfm.Open(tstrFileName)) { if (this->Init(m_mfm.GetBasePtr(), m_mfm.GetSize())) { bRetValue = TRUE; } } } catch(...) { } if (!bRetValue) { try { if (m_mfm.IsOpen()) { m_mfm.Close(); } } catch(...) {} } return bRetValue;}void DibFromFileMap::Close(void) { m_bInited = FALSE; m_mfm.Close();}// *************************************************************************************************// ** class My24BPPDIBSection ********************************************************************// *************************************************************************************************My24BPPDIBSection::My24BPPDIBSection(void) { m_hbmp = NULL;}My24BPPDIBSection::~My24BPPDIBSection() { this->Close();}HBITMAP My24BPPDIBSection::Create(IN HDC hdc, IN const tstring& tstrFileName, IN const SIZED& szd_Inches, IN const POINTD& ptdLogPix) { ASSERT( !this->IsOpen() ); ASSERT( m_hbmp == NULL ); DWORD dwPixelDataOffset; DWORD dwImagePixelDataBytes; SIZE szImage_Pixels; DWORD dwFileSize ; if (TheirCalculateSizes(dwFileSize, dwPixelDataOffset, dwImagePixelDataBytes, szImage_Pixels, szd_Inches, ptdLogPix)) { try { BOOL bCreated = m_mfm.Create(tstrFileName, dwFileSize); if (bCreated) { ::BITMAPFILEHEADER bfh; ::ZeroMemory(&bfh, sizeof(bfh)); bfh.bfType = 0x4d42; bfh.bfSize = dwFileSize; bfh.bfOffBits = dwPixelDataOffset; ::BITMAPINFOHEADER bih; ::ZeroMemory(&bih, sizeof(bih)); bih.biSize = sizeof(bih); bih.biWidth = szImage_Pixels.cx; bih.biHeight = szImage_Pixels.cy; bih.biBitCount = 24; bih.biPlanes = 1; bih.biCompression = BI_RGB; bih.biSizeImage = dwImagePixelDataBytes; bih.biXPelsPerMeter = RoundToLong(ptdLogPix.x * INCHES_PER_MM * 1000); bih.biYPelsPerMeter = RoundToLong(ptdLogPix.y * INCHES_PER_MM * 1000); DWORD dwOffset = 0; * (BITMAPFILEHEADER *) m_mfm.GetOffsetPtr(dwOffset) = bfh; dwOffset += sizeof(bfh); ::LPBITMAPINFO lpbmi = (::LPBITMAPINFO) m_mfm.GetOffsetPtr(dwOffset); * (::LPBITMAPINFOHEADER) lpbmi = bih; HANDLE hSection = m_mfm.GetFileMapHandle(); UINT uUsage = DIB_RGB_COLORS; VOID *pBits = NULL; DWORD dwtemp = sizeof(DWORD); m_hbmp = ::CreateDIBSection( hdc, lpbmi, uUsage, &pBits, hSection, dwPixelDataOffset ); if (m_hbmp != NULL) { m_ptdLogPix = ptdLogPix; m_szd_Inches = szd_Inches; m_sz_Pixels = szImage_Pixels; } } } catch(...) { if (m_hbmp != NULL) { ::DeleteObject(m_hbmp); m_hbmp = NULL; } } } if (m_hbmp == NULL) { if (m_mfm.IsOpen()) { m_mfm.Close(); } } return m_hbmp;}BOOL My24BPPDIBSection::IsOpen(void) const { BOOL bOpen = m_mfm.IsOpen(); ASSERT( !bOpen || m_hbmp != NULL ); return bOpen;}void My24BPPDIBSection::Close(void) { if (m_hbmp != NULL) { ::DeleteObject(m_hbmp); } if (m_mfm.IsOpen()) { m_mfm.Close(); }}const POINTD& My24BPPDIBSection::GetLogPix(void) const { ASSERT(this->IsOpen()); return m_ptdLogPix;}const SIZED& My24BPPDIBSection::GetSize_Inches(void) const { ASSERT(this->IsOpen()); return m_szd_Inches;}const SIZE& My24BPPDIBSection::GetSize_Pixels(void) const { ASSERT(this->IsOpen()); return m_sz_Pixels;}// ****// **** class My24BPPDIBSection: static members// ****BOOL My24BPPDIBSection::TheirCalculateFileSize( OUT DWORD& dwFileSize, OUT SIZE& szImage_Pixels, IN const SIZED& szd_Inches, IN const POINTD& ptdLogPix ) { DWORD dwPixelDataOffset; DWORD dwImagePixelDataBytes; BOOL bRetValue = My24BPPDIBSection::TheirCalculateSizes( dwFileSize, dwPixelDataOffset, dwImagePixelDataBytes, szImage_Pixels, szd_Inches, ptdLogPix ); return bRetValue;}BOOL My24BPPDIBSection::TheirCalculateSizes( OUT DWORD& dwFileSize, OUT DWORD& dwPixelDataOffset, OUT DWORD& dwImagePixelDataBytes, OUT SIZE& szImage_Pixels, IN const SIZED& szd_Inches, IN const POINTD& ptdLogPix) { BOOL bRetValue = FALSE; // NOTE: MAY BE THAT WIN95 DIB LINES ARE "WORD" ALIGNED (?) // ALTHOUGH I REMEMBER 4-BYTE ALIGNMENT BACK TO WIN 3.1 szImage_Pixels.cx = RoundToLong(szd_Inches.cx * ptdLogPix.x); szImage_Pixels.cy = RoundToLong(szd_Inches.cy * ptdLogPix.y); DWORD dwBytesPerLine = CalculateBytesPerLine(szImage_Pixels.cx); DWORD dwPixelDataOffsetUnAligned = sizeof(::BITMAPFILEHEADER) + sizeof(::BITMAPINFOHEADER); dwPixelDataOffset = CalculateDWORDAligned(dwPixelDataOffsetUnAligned); double dTemp = dwBytesPerLine; dTemp *= szImage_Pixels.cy; // SHOULD BE ABLE TO HANDLE UP TO UNSIGNED DWORD MAX, BUT BEING CONSERVATIVE if (dTemp < 0x7fffffffL - dwPixelDataOffset) { dwImagePixelDataBytes = dwBytesPerLine * szImage_Pixels.cy; dwFileSize = dwPixelDataOffset + dwImagePixelDataBytes; bRetValue = TRUE; } return bRetValue;}// *********************************************************************************************// ** MODULE PRIVATE ROUTINES ****************************************************************// *********************************************************************************************static DWORD CalculateDWORDAligned(IN DWORD dw) { DWORD dwRetValue = (dw + 3) & ( ~ (DWORD) 3 ); return dwRetValue;}static DWORD CalculateBytesPerLine(IN DWORD dwPixelsPerLine) { // LINES MUST BE 4-BYTE ALIGNED AKA 32 BIT DWORD dwBytesUnAligned = dwPixelsPerLine * 3; DWORD dwBytesAligned = CalculateDWORDAligned(dwBytesUnAligned); return dwBytesAligned;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -