📄 bmpfile.cpp
字号:
// BmpFile.cpp : implementation file
//
#include "stdafx.h"
#include "MfcScroll1.h"
#include "BmpFile.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CBmpFile
IMPLEMENT_DYNCREATE(CBmpFile, CObject)
CBmpFile::CBmpFile()
{
InitMemberVar();
}
CBmpFile::CBmpFile(CSize size, int nBitCount)
{
InitMemberVar();
ComputePaletteSize(nBitCount);
m_pBmih = (LPBITMAPINFOHEADER) new
char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries];
m_pBmih->biSize = sizeof(BITMAPINFOHEADER);
m_pBmih->biWidth = size.cx;
m_pBmih->biHeight = size.cy;
m_pBmih->biPlanes = 1;
m_pBmih->biBitCount = nBitCount;
m_pBmih->biCompression = BI_RGB;
m_pBmih->biSizeImage = 0;
m_pBmih->biXPelsPerMeter = 0;
m_pBmih->biYPelsPerMeter = 0;
m_pBmih->biClrUsed = m_nColorTableEntries;
m_pBmih->biClrImportant = m_nColorTableEntries;
CalcBufSize();
memset(m_pColorTable, 0, sizeof(RGBQUAD) * m_nColorTableEntries);
}
CBmpFile::~CBmpFile()
{
Empty();
}
void CBmpFile::InitMemberVar()
{
m_pBmih = NULL;
m_pBits = NULL;
m_hPalette = NULL;
m_hBitmap = NULL;
m_pColorTable = NULL;
m_nColorTableEntries = 0;
m_dwSizeImage = 0;
m_bNoDelBits = 0;
m_bGray = 0;
}
/////////////////////////////////////////////////////////////////////////////
// CBmpFile message handlers
CSize CBmpFile::GetDimensions()
{
if(m_pBmih == NULL)
return CSize(0, 0);
return CSize((int) m_pBmih->biWidth, (int) m_pBmih->biHeight);
}
UINT CBmpFile::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 CBmpFile::Draw(CDC* pDC, CPoint origin, CSize size)
{
if(m_pBmih == 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_pBmih->biWidth, m_pBmih->biHeight,
m_pBits, (LPBITMAPINFO) m_pBmih, DIB_RGB_COLORS, SRCCOPY);
return TRUE;
}
BOOL CBmpFile::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);
LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) +
m_nColorTableEntries * sizeof(PALETTEENTRY)];
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = m_nColorTableEntries;
LPRGBQUAD pDibQuad = (LPRGBQUAD) m_pColorTable;
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 CBmpFile::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 CBmpFile::CreateBitmap(CDC* pDC)
{
if (m_dwSizeImage == 0) return NULL;
HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), m_pBmih,
CBM_INIT, m_pBits, (LPBITMAPINFO) m_pBmih, DIB_RGB_COLORS);
ASSERT(hBitmap != NULL);
return hBitmap;
}
BOOL CBmpFile::Read(CFile* pFile)
{
Empty();
UINT nCount, nSize;
BITMAPFILEHEADER bmfh;
try {
nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
if(nCount != sizeof(BITMAPFILEHEADER)) {
throw new CException;
}
if(bmfh.bfType != 0x4d42) {
throw new CException;
}
nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
m_pBmih = (LPBITMAPINFOHEADER) new char[nSize];
nCount = pFile->Read(m_pBmih, nSize); // info hdr & color table
if(nCount != nSize) {
throw new CException;
}
CalcBufSize();
ComputePaletteSize(m_pBmih->biBitCount);
MakePalette();
m_pBits = (LPBYTE) new char[m_dwSizeImage];
m_bNoDelBits = 0;
nCount = pFile->Read(m_pBits, m_dwSizeImage); // image only
if(nCount != m_dwSizeImage) {
throw new CException;
}
}
catch(CException* pe) {
Empty();
AfxMessageBox("Read error");
pe->Delete();
return FALSE;
}
return TRUE;
}
BOOL CBmpFile::ReadSection(CFile* pFile, CDC* pDC /* = NULL */)
{
// new function reads BMP from disk and creates a DIB section
// allows modification of bitmaps from disk
// 1. read file header to get size of info hdr + color table
// 2. read info hdr (to get image size) and color table
// 3. create DIB section based on header parms
// 4. read image into memory that CreateDibSection allocates
Empty();
int nCount, nSize;
BITMAPFILEHEADER bmfh;
try {
nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
if(nCount != sizeof(BITMAPFILEHEADER)) {
throw new CException;
}
if(bmfh.bfType != 0x4d42) {
throw new CException;
}
nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
m_pBmih = (LPBITMAPINFOHEADER) new char[nSize];
nCount = pFile->Read(m_pBmih, nSize); // info hdr & color table
if(m_pBmih->biCompression != BI_RGB) {
throw new CException;
}
CalcBufSize();
ComputePaletteSize(m_pBmih->biBitCount);
MakePalette();
UsePalette(pDC);
m_bNoDelBits = 1;
m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_pBmih,
DIB_RGB_COLORS, (LPVOID*) &m_pBits, NULL, 0);
ASSERT(m_pBits != NULL);
nCount = pFile->Read(m_pBits, m_dwSizeImage); // image only
}
catch(CException* pe){
AfxMessageBox("ReadSection error");
pe->Delete();
return FALSE;
}
return TRUE;
}
BOOL CBmpFile::Write(CFile* pFile)
{
BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4d42; // 'BM'
int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
bmfh.bfSize = sizeof(BITMAPFILEHEADER) + nSizeHdr + m_dwSizeImage;
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * m_nColorTableEntries;
try {
pFile->Write((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
pFile->Write((LPVOID) m_pBmih, nSizeHdr);
pFile->Write((LPVOID) m_pBits, m_dwSizeImage);
}
catch(CException* pe) {
pe->Delete();
AfxMessageBox("write error");
return FALSE;
}
return TRUE;
}
// helper functions
void CBmpFile::ComputePaletteSize(int nBitCount)
{
if((m_pBmih == NULL) || (m_pBmih->biClrUsed == 0)) {
switch(nBitCount) {
case 1:
m_nColorTableEntries = 2;
break;
case 4:
m_nColorTableEntries = 16;
break;
case 8:
m_nColorTableEntries = 256;
break;
case 16:
case 24:
case 32:
m_nColorTableEntries = 0;
break;
default:
ASSERT(FALSE);
}
}
else {
m_nColorTableEntries = m_pBmih->biClrUsed;
}
ASSERT((m_nColorTableEntries >= 0) && (m_nColorTableEntries <= 256));
}
void CBmpFile::CalcBufSize()
{
m_dwSizeImage = m_pBmih->biSizeImage;
if(m_dwSizeImage == 0)
{
DWORD dwBytes = ((DWORD) m_pBmih->biWidth * m_pBmih->biBitCount+31) / 32*4;
m_dwSizeImage = dwBytes * m_pBmih->biHeight; // no compression
}
m_pColorTable = (LPBYTE) m_pBmih + sizeof(BITMAPINFOHEADER);
}
void CBmpFile::Empty()
{
if( m_pBmih ) {
delete[] m_pBmih;
m_pBmih = NULL;
}
if(m_hBitmap)
{
::DeleteObject(m_hBitmap);
m_hBitmap = NULL;
}
if( m_pBits && !m_bNoDelBits )
delete[] m_pBits;
m_pBits = NULL;
if(m_hPalette)
{
::DeleteObject(m_hPalette);
m_hPalette = NULL;
}
m_pColorTable = NULL;
m_nColorTableEntries = 0;
m_dwSizeImage = 0;
m_bGray = 0;
}
HBITMAP CBmpFile::Detach()
{
HBITMAP hBmp = NULL;
if( m_bNoDelBits && m_hBitmap )
{
hBmp = m_hBitmap;
m_hBitmap = NULL;
m_pBits = NULL;
Empty();
}
return hBmp;
}
BOOL CBmpFile::LoadFile( LPCTSTR szPathName)
{
CFile file;
int i = 0;
if( file.Open( szPathName,CFile::modeRead ) )
{
i = Read( &file );
file.Close( );
}
return i;
}
BOOL CBmpFile::LoadFileSection(LPCTSTR szPathName, CDC* pDC /*= NULL*/)
{
CFile file;
int i = 0;
if( file.Open( szPathName,CFile::modeRead ) )
{
i = ReadSection( &file, pDC );
file.Close( );
}
return i;
}
BOOL CBmpFile::WriteFile(LPCTSTR szPathName)
{
CFile file;
int i = 0;
if( file.Open( szPathName,CFile::modeWrite ) )
{
i = Write( &file );
file.Close( );
}
return i;
}
void CBmpFile::GetPixel( CPoint &pt,BYTE &r,BYTE &g,BYTE &b)
{
if( m_pBmih == NULL )
return;
int y = pt.y, x = pt.x, xByte;
BYTE uChar, xBit;
if( pt.y < 0 )
y = 0-y;
if( y >= m_pBmih->biHeight )
y = m_pBmih->biHeight-1;
if( pt.x >= m_pBmih->biWidth )
x = m_pBmih->biWidth-1;
xByte = x*m_pBmih->biBitCount/8;
xBit = BYTE(x*m_pBmih->biBitCount%8);
DWORD bmHeight = m_pBmih->biHeight - y - 1;
DWORD bmWidthBytes = (m_pBmih->biWidth * m_pBmih->biBitCount + 31) / 32*4;
DWORD dwOffset = bmWidthBytes*bmHeight + xByte;
UINT uIndex;
LPBYTE pByte = m_pBits + dwOffset;
LPRGBQUAD pRGBQURD = (LPRGBQUAD)m_pColorTable;
switch( m_pBmih->biBitCount )
{
case 1:
uChar = *pByte;
uIndex = (uChar>>(7-xBit)) & 1;
r = pRGBQURD[uIndex].rgbRed;
g = pRGBQURD[uIndex].rgbGreen;
b = pRGBQURD[uIndex].rgbBlue;
break;
case 4:
uChar = *pByte;
uIndex = (uChar>>(4-xBit)) & 15;
r = pRGBQURD[uIndex].rgbRed;
g = pRGBQURD[uIndex].rgbGreen;
b = pRGBQURD[uIndex].rgbBlue;
break;
case 8:
uIndex = *pByte;
r = pRGBQURD[uIndex].rgbRed;
g = pRGBQURD[uIndex].rgbGreen;
b = pRGBQURD[uIndex].rgbBlue;
break;
case 16:
{
PWORD pWord = (PWORD)pByte;
uIndex = *pWord;
r = ( (uIndex >> 10) & 31)<<3;
g = ((uIndex >> 5) & 31)<<3;
b = (uIndex & 31)<<3;
break;
}
case 24:
case 32:
r = *pByte++;
g = *pByte++;
b = *pByte;
break;
}
}
void CBmpFile::GrayImage( CDC *pDC )
{
if( m_pBmih == NULL || m_pBits == NULL || m_bGray )
return;
DWORD bmWidthBytes = (m_pBmih->biWidth * m_pBmih->biBitCount + 31) / 32*4;
int i,j;
BYTE r,b,g;
LPBYTE pByte = m_pBits;
LPRGBQUAD pRGBQURD = (LPRGBQUAD)m_pColorTable;
switch( m_pBmih->biBitCount )
{
case 1:
case 4:
case 8:
for( i=0;i<m_nColorTableEntries; i++ )
{
j = (pRGBQURD[i].rgbRed*59+pRGBQURD[i].rgbGreen*30+pRGBQURD[i].rgbBlue*11)/100;
pRGBQURD[i].rgbRed = BYTE(j);
pRGBQURD[i].rgbGreen = BYTE(j);;
pRGBQURD[i].rgbBlue = BYTE(j);;
}
break;
case 16:
{
PWORD pWord;
register UINT uIndex;
for( i=0; i<m_pBmih->biHeight; i++ )
{
pWord = (PWORD)pByte;
for( j=0; j<m_pBmih->biWidth; j++ )
{
uIndex = *pWord;
r = (uIndex >> 10) & 31;
g = (uIndex >> 5) & 31;
b = uIndex & 31;
uIndex = r = (r*59 + g*30 + b*11)/100;
uIndex <<= 5;
uIndex += r;
uIndex <<= 5;
uIndex += r;
*pWord++ = uIndex;
}
pByte += bmWidthBytes;
}
break;
}
case 24:
case 32:
{
register PBYTE pData1,pData2;
for( i=0; i<m_pBmih->biHeight; i++ )
{
pData1 = pData2 = pByte;
for( j=0; j<m_pBmih->biWidth; j++ )
{
r = *pData1++;
g = *pData1++;
b = *pData1++;
r = BYTE( (r*59 + g*30 + b*11)/100 );
*pData2++ = r;
*pData2++ = r;
*pData2++ = r;
}
pByte += bmWidthBytes;
}
break;
}
}
HBITMAP hBitmap = ::CreateDIBSection( pDC->GetSafeHdc(), (LPBITMAPINFO) m_pBmih,
DIB_RGB_COLORS, (LPVOID*) &pByte, NULL, 0);
ASSERT(pByte != NULL);
memcpy( pByte, m_pBits,m_dwSizeImage);
if( m_hBitmap )
::DeleteObject(m_hBitmap);
m_hBitmap = hBitmap;
if( m_pBits && !m_bNoDelBits )
delete[] m_pBits;
m_pBits = pByte;
m_bNoDelBits = 1;
m_bGray = 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -