📄 bmp.cpp
字号:
// BMP.cpp: implementation of the BMP class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BMP.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
BMP::BMP()
{
m_nHeight = 0;
m_nWidth = 0;
m_nFileSize = 0;
m_nScanWidth = 0;
m_nColorBits = 0;
m_pDib = NULL;
m_pDibBits = NULL;
}
BMP::~BMP()
{
}
int WIDTHBYTES(int Width)
{
return ((Width+31)/32*4);
}
BOOL BMP::LoadImage(CString FileName)
{
/**************
BITMAPFILEHEADER | (14 byte)
------------------------
+ BITMAPINFOHEADER (40 byte)|
+ Palette (4 byte)| BITMAPINFO(44 byte)
***************/
int test1 =sizeof(BITMAPINFOHEADER); //40
int test2 = sizeof(BITMAPFILEHEADER); //14
int test3 = sizeof(LOGPALETTE); //8
int test4 = sizeof(PALETTEENTRY); //4
int test5 = sizeof(RGBQUAD); //4
int test7 = sizeof(LOGPALETTE); ///8
int test8 = sizeof(BITMAPINFO); //44
/******************/
m_sFilePath = FileName;
CFile file(m_sFilePath,CFile::modeRead);
m_sFilePath = file.GetFilePath();
m_sFileName = file.GetFileName();
m_sFilePath = m_sFilePath.Left(m_sFilePath.GetLength()-m_sFileName.GetLength());
file.Close();
//创建文件句柄
HANDLE hFile = ::CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
ASSERT(hFile != INVALID_HANDLE_VALUE);
//获取文件大小
m_nFileSize = GetFileSize(hFile,NULL);
m_pDib = new unsigned char[m_nFileSize];
ASSERT(m_pDib != NULL);
//读图像
unsigned long WriteNum;
ReadFile(hFile,m_pDib,m_nFileSize,&WriteNum,NULL);
ASSERT(m_nFileSize == (long)WriteNum);
CloseHandle(hFile);
/////////////////////////////////////////////////
//获取图象信息
/*BITMAPFILEHEADER *pBFH; //图象文件头
BITMAPINFOHEADER *pBIH; //图象信息头
unsigned char *pPixel;
unsigned char *pFirst = m_pDib;
pBFH = (BITMAPFILEHEADER *)pFirst;
pFirst += sizeof(BITMAPFILEHEADER);
pBIH = (BITMAPINFOHEADER *)pFirst;
pFirst += sizeof(BITMAPINFOHEADER);
//获取图象的实际象素值
pPixel = pFirst + 256*sizeof(RGBQUAD);
// pPixel = pFirst;
BYTE gray1 =pPixel[0];
long lWidth = pBIH->biWidth;
long lHeight = pBIH->biHeight;*/
//////////////////////////////////////////////
//获取文件头和文件信息头
//(1)指针指向文件的头
unsigned char *pDib = (unsigned char *)m_pDib;
BITMAPFILEHEADER *pFileHeader = (BITMAPFILEHEADER * )pDib;
if(pFileHeader->bfType != 'MB')
{
AfxMessageBox("文件类型有误,无法打开,请重新选择");
return FALSE;
}
//(2)指向BITMAPFILEHEADER的末尾
pDib += sizeof(BITMAPFILEHEADER);
BITMAPINFOHEADER *pInfoHeader = (BITMAPINFOHEADER * )pDib;
//初始化成员数据
m_nHeight = pInfoHeader->biHeight;
m_nWidth = pInfoHeader->biWidth ;
m_nScanWidth = WIDTHBYTES(m_nWidth*pInfoHeader->biBitCount);
m_nColorBits = pInfoHeader->biBitCount;
//(3)指向BITMAPINFOHEADER的末尾
pDib += sizeof(BITMAPINFOHEADER);
int ColorNumber = 1<<m_nColorBits; //图像的颜色数图像的颜色数pow(2,m_nColorBits)
RGBQUAD *pPaletteInfo = (RGBQUAD*)pDib;
if( m_Palette.GetSafeHandle() != NULL ) //删除现有的调色板信息
m_Palette.DeleteObject();
if( m_nColorBits == 24 ) //真彩色图像,无调色板
{
m_pDibBits = pDib;
BYTE GRAY1 = m_pDibBits[0];
return TRUE; //退出函数,不执行席面的操作
}
//否则设置调色板(对于8位)
LOGPALETTE *pLogPal = (LOGPALETTE *) new char[sizeof(LOGPALETTE)+
ColorNumber * sizeof(PALETTEENTRY)];
if( pLogPal != NULL )
{
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = ColorNumber;
for( int i = 0; i < ColorNumber; i++ )
{
pLogPal->palPalEntry[i].peRed = pPaletteInfo[i].rgbRed;
pLogPal->palPalEntry[i].peGreen = pPaletteInfo[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue = pPaletteInfo[i].rgbBlue;
//初始化调色板数组
m_nPalette[i][0] = pPaletteInfo[i].rgbBlue;
m_nPalette[i][1] = pPaletteInfo[i].rgbGreen;
m_nPalette[i][2] = pPaletteInfo[i].rgbRed;
}
m_Palette.CreatePalette( pLogPal );
delete [] pLogPal;
}
//(4)指向位图数据(Palette的末尾)
m_pDibBits = pDib + ColorNumber * sizeof(RGBQUAD);
//BYTE gray = m_pDibBits[0];
/**************
m_pDib--> BITMAPFILEHEADER
----------------------
BITMAPINFOHEADER
Palette
------------------------
m_pDibBits--> Data
***************/
return TRUE;
}
BOOL BMP::SaveImage(CString FileName)
{
if( m_pDibBits == NULL )
{
AfxMessageBox("还没有打开文件,请先载入一幅图像再保存!",0,0);
return( FALSE );
}
HANDLE hFile = ::CreateFile(FileName,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile == NULL)
{
AfxMessageBox("无法创建文件.",0,0);
CloseHandle(hFile);
hFile = NULL;
return FALSE;
}
unsigned long WriteNum;
WriteFile(hFile,m_pDib,m_nFileSize,&WriteNum,NULL);
if(WriteNum != (unsigned long)m_nFileSize)
return FALSE;
CloseHandle(hFile);
return TRUE;
return TRUE;
}
BOOL BMP::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight)
{
if( m_Palette.GetSafeHandle() != NULL )
{
// 选择调色板,实现调色板并保存旧的调色板
CPalette *pOldPalette;
pOldPalette = pDC->SelectPalette( &m_Palette, FALSE );
pDC->RealizePalette();
pDC->SelectPalette( pOldPalette, FALSE );
}
//调用StrechDibBits绘图
if( nWidth == -1 )
nWidth = m_nWidth;
if( nHeight == -1 )
nHeight = m_nHeight;
//使用拉伸模式使彩色图像显示时的彩色效果最好
::SetStretchBltMode(pDC->m_hDC, COLORONCOLOR);
StretchDIBits( pDC->m_hDC, nX, nY, nWidth, nHeight, 0, 0,
m_nWidth, m_nHeight, m_pDibBits,
(BITMAPINFO *)(m_pDib + sizeof(BITMAPFILEHEADER)),
BI_RGB, SRCCOPY );
return TRUE;
}
int BMP::GetImageWidth()
{
return m_nWidth;
}
int BMP::GetImageHeight()
{
return m_nHeight;
}
int BMP::GetImageBits()
{
return m_nColorBits;
}
BOOL BMP::GetPixel(int i, int j, COLORREF &Value)
{
if( (i < 0)||(i>=m_nHeight)||(j<0)||(j>=m_nWidth) )
return FALSE;
if(m_nColorBits == 24)
{
BYTE *pData = m_pDibBits + (m_nHeight-1-i)*m_nScanWidth + j*3;
Value = RGB(pData[2], pData[1], pData[0]);
}
else if( m_nColorBits == 8 )
{
BYTE *pData = m_pDibBits + (m_nHeight-1-i)*m_nScanWidth + j;
Value = RGB( *pData, *pData, *pData );
}
return TRUE;
}
BOOL BMP::SetPixel(int i, int j, COLORREF Value)
{
if( (i < 0)||(i>=m_nHeight)||(j<0)||(j>=m_nWidth) )
return FALSE;
if( m_nColorBits == 24 )
{
BYTE *pData = m_pDibBits + (m_nHeight-1-i)*m_nScanWidth + j*3;
pData[0] = GetBValue(Value);
pData[1] = GetGValue(Value);
pData[2] = GetRValue(Value);
}
else if( m_nColorBits == 8 )
{
BYTE *pData = m_pDibBits + (m_nHeight-1-i)*m_nScanWidth + j;
*pData = GetBValue(Value);
}
return TRUE;
}
CString BMP::GetFileName()
{
return m_sFileName;
}
CString BMP::GetFilePath()
{
return m_sFilePath;
}
int BMP::ConvolutionPixel8(int i, int j, int Values[][9], int nSize, int Division, int Offset)
{
int gray = 0;
int cof=0; int size=0;
for(int m=0;m<nSize;m++)
{
for(int n=0;n<nSize;n++)
{
COLORREF c;
if(GetPixel(i-nSize/2+m,j-nSize/2+n,c))
{
gray += (Values[m][n] *GetBValue(c));
cof += Values[m][n];
size ++;
}
}//end n
}//end m
if(cof <0) //如果系数小于0,取原值
{
COLORREF c;
GetPixel(i,j,c);
gray =GetBValue(c);
}
else if(size <nSize*nSize)
{
if(cof == 0) cof =1;
gray = min(gray/cof +Offset,255);
}
else gray = min(gray/Division + Offset,255);
//把变换的结果保存到新建的数组中
gray = max(0,gray);
return gray;
}
float BMP::ConvolutionPixel8f(int i, int j, int Values[][9], int nSize, int Division, int Offset)
{
float gray = 0;
float cof=0; int size=0;
for(int m=0;m<nSize;m++)
{
for(int n=0;n<nSize;n++)
{
COLORREF c;
if(GetPixel(i-nSize/2+m,j-nSize/2+n,c))
{
gray += (Values[m][n] *GetBValue(c));
cof += Values[m][n];
size ++;
}
}//end n
}//end m
if(cof <0) //如果系数小于0,取原值
{
COLORREF c;
GetPixel(i,j,c);
gray = GetBValue(c);
}
else if(size <nSize*nSize)
{
if(cof == 0) cof =1;
gray = (float)(gray/cof +Offset);
}
else gray = float(gray/(float)Division + Offset);
//把变换的结果保存到新建的数组中
return gray;
}
void BMP::ConvertDIB8(int Values[][9], int nSize, int Division, int Offset)
{
int Width = GetImageWidth();
int Height = GetImageHeight();
int ColorBits = GetImageBits();
int WidthBytes = WIDTHBYTES(Width*ColorBits);
//开辟与图象同样大小的数组,用于保存图象结果
unsigned char *pDibBits = new unsigned char[WidthBytes*Height];
for(int i = 0 ;i < Height; i++)
{
for(int j = 0;j < Width; j++)
{
//计算第i行,第j列象素的新值
int gray = ConvolutionPixel8(i,j,Values,nSize,Division,Offset);
BYTE *pData = pDibBits + (Height-i-1)*WidthBytes+j;
*pData = gray;
}
}
//赋值
for(i=0;i<Height*WidthBytes;i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -