📄 dib.cpp
字号:
// DIB.cpp : implementation file
//
#include "stdafx.h"
#include "DIB.h"
#include "math.h"
#include <fstream>
#include <iostream>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define TEMPLATE_SMOOTH_BOX 1
#define TEMPLATE_SMOOTH_GAUSS 2
#define TEMPLATE_SHARPEN_LAPLACIAN 3
int Template_Smooth_Box[9]={1,1,1,1,1,1,1,1,1};
int Template_Smooth_Gauss[9]={1,2,1,2,4,2,1,2,1};
int Template_Sharpen_Laplacian[9]={-1,-1,-1,-1,9,-1,-1,-1,-1};
/////////////////////////////////////////////////////////////////////////////
// CDIB
#define WIDTHBYTES(i) ((i+31)/32*4)
/*************************************************************************
*
* 函数名称:
* CDIB()
*
* 参数:
* 返回值:
*
* 说明:
* 类CDIB的无参构造函数
*
*
************************************************************************/
CDIB::CDIB()
{
m_pBMI=NULL;
m_pDIBData=NULL;
m_pBMF=NULL;
m_biHeight=NULL;
m_biWidth=NULL;
m_dataBytes=NULL;
m_dwByteNumber=NULL;
m_LineBytes=NULL;
m_NumColors=NULL;
}
/*************************************************************************
*
* 函数名称:
* ~CDIB()
*
* 参数:
* 返回值:
*
* 说明:
* 类CDIB的析构函数,主要完成内存的释放任务
*
************************************************************************/
CDIB::~CDIB()
{
if(m_pBMI!=NULL)
delete m_pBMI;
if(m_pDIBData!=NULL)
delete m_pDIBData;
if(m_pBMF!=NULL)
delete m_pBMF;
}
/*************************************************************************
*
* 函数名称:
* LoadFromFile()
*
* 参数:
* LPCSTR lpszFileName- 要加载的图象文件的路径
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于从BMP文件构造一个CDIB对象
*
* 要求目标图像为24位或者更低位图。
************************************************************************/
BOOL CDIB::LoadFromFile(LPCTSTR lpszFileName)
{
CFile file;
BITMAPFILEHEADER* pBMF=NULL;
BITMAPINFO* pBMI=NULL;
BYTE* pDIBData=NULL;
DWORD NumColors;
if(!file.Open(lpszFileName,CFile::modeRead|CFile::typeBinary))
{
#ifdef _DEBIG
AfxMessageBox("打开文件错误");
#endif
return FALSE;
}
pBMF=(BITMAPFILEHEADER*)new char[sizeof(BITMAPFILEHEADER)];
if(!pBMF)
{
AfxMessageBox("分配内存出错!");
return FALSE;
}
if(file.Read(pBMF,sizeof(BITMAPFILEHEADER))
!=sizeof(BITMAPFILEHEADER))
{
#ifdef _DEBUG
AfxMessageBox("Error Read File!");
#endif
delete pBMF;
pBMF = NULL;
return FALSE;
}
if(pBMF->bfType!=0x4d42)//位图标志'BM'
{
#ifdef _DEBUG
AfxMessageBox("不是BMP文件!");
#endif
delete pBMF;
pBMF = NULL;
return FALSE;
}
//读入信息头
BITMAPINFOHEADER bih;
if(file.Read(&bih,sizeof(bih))!=sizeof(bih))
{
#ifdef _DEBUG
AfxMessageBox("读文件出错!");
#endif
return FALSE;
}
m_biWidth=bih.biWidth;
m_biHeight=bih.biHeight;
m_LineBytes=(DWORD)WIDTHBYTES(bih.biWidth*bih.biBitCount);
if(bih.biClrUsed!=0)
NumColors=(DWORD)bih.biClrUsed;
else
switch(bih.biBitCount){//表示颜色时用到的位数
case 1:
NumColors=2;
break;
case 4:
NumColors=16;
break;
case 8:
NumColors=256;
break;
case 24:
case 32:
NumColors=0;//真彩色时不用调色板
break;
default:
return FALSE;
}
m_NumColors=NumColors;
pBMI=(BITMAPINFO*)new char[sizeof(bih)+NumColors*sizeof(RGBQUAD)];
if(!pBMI)
{
#ifdef _DEBUG
AfxMessageBox("分配内存出错!");
#endif
return FALSE;
}
if(file.Seek(sizeof(BITMAPFILEHEADER),CFile::begin)!=sizeof(BITMAPFILEHEADER))
{
#ifdef _DEBUG
AfxMessageBox("移动文件指针出错!");
#endif
return FALSE;
}//CBitmap CDC BITMAP BITMAPFILEHEADER GetDIBits
if(file.Read(pBMI,sizeof(bih)+NumColors*sizeof(RGBQUAD))
!=sizeof(bih)+NumColors*sizeof(RGBQUAD))
{
#ifdef _DEBUG
AfxMessageBox("Error Read File!");
#endif
return FALSE;
}
//bfSize为整个图象文件的字节数
DWORD dataBytes=pBMF->bfSize - pBMF->bfOffBits;
m_dataBytes=dataBytes;
pDIBData=(BYTE*)new char[dataBytes];
if(!pDIBData)
{
#ifdef _DEBUG
AfxMessageBox("分配内存出错!");
#endif
return FALSE;
}
if(file.ReadHuge(pDIBData,dataBytes)!=dataBytes)
{
#ifdef _DEBUG
AfxMessageBox("读文件出错!");
#endif
delete pBMF;
delete pBMI;
delete pDIBData;
return FALSE;
}
m_dwByteNumber = dataBytes;
file.Close();
if(m_pBMI!=NULL)
delete m_pBMI;
m_pBMI=pBMI;//图象信息头
if(m_pBMF!=NULL)
delete m_pBMF;
m_pBMF=pBMF;//文件头
if(m_pDIBData!=NULL)
delete m_pDIBData;
m_pDIBData=pDIBData;//图象正文
if(Conert32To24())
{
#ifdef _DEBUG
// AfxMessageBox("读文件32转24成功!");
#endif
}
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* Convert32To24()
*
* 参数:
* 返回值:
* bool - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于将32位位图转换为24位位图
*
* 如果图象不是32位的,则本函数不做运算。
************************************************************************/
bool CDIB::Conert32To24()
{
if((m_pBMI->bmiHeader).biBitCount == 32)
{
//修改位深数字
(m_pBMI->bmiHeader).biBitCount = 24;
(m_pBMI->bmiHeader).biCompression = BI_RGB;//没有压缩
(m_pBMI->bmiHeader).biSizeImage = 0;
(m_pBMI->bmiHeader).biClrUsed = 0;
//修改新的图象文件字节数目
m_pBMF->bfSize -= (m_pBMF->bfSize - m_pBMF->bfOffBits)/4;
//修改像数字节数
m_dataBytes -= m_dwByteNumber/4;
BYTE * buf = (BYTE *) new char[m_dataBytes];
if(!buf)
{
//申请内存失败
return false;
}
m_LineBytes=(DWORD)WIDTHBYTES((m_pBMI->bmiHeader).biWidth * (m_pBMI->bmiHeader).biBitCount);
//去掉多余的字节
for(DWORD i = 0, j = 0; i < m_dwByteNumber;i++ )
{
if(i%4 == 3)//空白字节
{
continue;
}
*(buf + j++) = *(m_pDIBData + i);
}
if(m_pDIBData) delete m_pDIBData;
m_pDIBData = buf;
}
return true;
}
/*************************************************************************
*
* 函数名称:
* SaveToFile()
*
* 参数:
* LPCSTR lpszFileName- 将要保存的文件路径。
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于将图象保存到指定路径。
*
************************************************************************/
BOOL CDIB::SaveToFile(LPCSTR lpszFileName)
{
CFile file;
if(!file.Open(lpszFileName,CFile::modeCreate|CFile::modeWrite|CFile::typeBinary))
{
#ifdef _DEBUG
AfxMessageBox("打开文件错误");
#endif
return FALSE;
}
file.Write(m_pBMF,sizeof(BITMAPFILEHEADER));
file.Write(m_pBMI,sizeof(BITMAPINFOHEADER)+m_NumColors*sizeof(RGBQUAD));
file.WriteHuge(m_pDIBData,m_dataBytes);
file.Close();
return TRUE;//CFileFind
}
void CDIB::ShowDIB(CDC* pDC,int nLeft,int nTop,int nWidth,int nHeight)
{
pDC->SetStretchBltMode(COLORONCOLOR);
StretchDIBits(pDC->GetSafeHdc(),nLeft,nTop,nWidth,nHeight,0,0,GetDIBWidth(),GetDIBHeight(),m_pDIBData,m_pBMI,DIB_RGB_COLORS,SRCCOPY);
}
void CDIB::Translation(int xOffset,int yOffset)
{
int SrcX0,SrcY0,SrcX1,SrcY1,DstX0,DstY0,DstX1,DstY1;
int RectWidth,RectHeight;
BOOL xVisible,yVisible;
BYTE* pTempData;
BYTE* lpTempData;
BYTE* lpPtr;
int i;
pTempData=(BYTE*)new char[m_dataBytes];
memset(pTempData,255,m_dataBytes);
lpTempData=pTempData;
lpPtr=m_pDIBData;
xVisible=TRUE;
if(xOffset<=-m_biWidth)
{
xVisible=FALSE;
}
else if(xOffset<=0)
{
DstX0=0;
DstX1=m_biWidth+xOffset;
}
else if(xOffset<m_biWidth)
{
DstX0=xOffset;
DstX1=m_biWidth;
}
else
xVisible=FALSE;
SrcX0=DstX0-xOffset;
SrcX1=DstX1-xOffset;
RectWidth=DstX1-DstX0;
yVisible=TRUE;
if(yOffset<=-m_biHeight)
yVisible=FALSE;
else if(yOffset<=0)
{
DstY0=0;
DstY1=m_biHeight+yOffset;
}
else if(yOffset<m_biHeight)
{
DstY0=yOffset;
DstY1=m_biHeight;
}
else
{
yVisible=FALSE;
}
SrcY0=DstY0-yOffset;
SrcY1=DstY1-yOffset;
RectHeight=DstY1-DstY0;
if(xVisible&&yVisible)
{
for(i=0;i<RectHeight;i++)
{
lpPtr=m_pDIBData+m_dataBytes-m_LineBytes-(i+SrcY0)*m_LineBytes+SrcX0;
lpTempData=pTempData+m_dataBytes-m_LineBytes-(i+DstY0)*m_LineBytes+DstX0;
memcpy(lpTempData,lpPtr,RectWidth);
}
memcpy(m_pDIBData,pTempData,m_dataBytes);
delete pTempData;
}
}
/*************************************************************************
*
* 函数名称:
* Invert()
*
* 参数:
* 返回值:
* VOID
*
* 说明:
* 该函数用于对图像进行反色。
*
* 注意,本函数反色是通过让调色板反色来实现让图象反色的效果。像数索引植未作任何修改。
************************************************************************/
void CDIB::Invert()
{
BYTE* pTempData;
BYTE* lpTempData;
BYTE* lpPtr;
BITMAPINFO* pTempInfo;
LONG x,y;
DWORD i;
unsigned char Red,Green,Blue;
pTempData=(BYTE*)new char[m_dataBytes];
pTempInfo=(BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER)+m_NumColors*sizeof(RGBQUAD)];
if(!pTempInfo || !pTempData)
{
#ifdef _DEBUG
AfxMessageBox("分配内存错误!");
#endif
return;
}
if(m_NumColors == 0)
{
for(y=0;y<m_biHeight;y++)
{
lpPtr=m_pDIBData+(m_dataBytes-m_LineBytes-y*m_LineBytes);
lpTempData=pTempData+(m_dataBytes-m_LineBytes-y*m_LineBytes);
for(x=0;x<m_biWidth;x++)
{
Blue=(unsigned char)(*lpPtr++);
Green=(unsigned char)(*lpPtr++);
Red=(unsigned char)(*lpPtr++);
*(lpTempData++)=(unsigned char)(255-Blue);
*(lpTempData++)=(unsigned char)(255-Green);
*(lpTempData++)=(unsigned char)(255-Red);
}
}
memcpy(m_pDIBData,pTempData,m_dataBytes);
delete pTempData;
}
else
{
memcpy(pTempInfo,m_pBMI,sizeof(BITMAPINFOHEADER)+m_NumColors*sizeof(RGBQUAD));
for(i=0;i<m_NumColors;i++)
{
pTempInfo->bmiColors[i].rgbBlue=255-m_pBMI->bmiColors[i].rgbBlue;
pTempInfo->bmiColors[i].rgbGreen=255-m_pBMI->bmiColors[i].rgbGreen;
pTempInfo->bmiColors[i].rgbRed=255-m_pBMI->bmiColors[i].rgbRed;
}
memcpy(m_pBMI,pTempInfo,sizeof(BITMAPINFOHEADER)+m_NumColors*sizeof(RGBQUAD));
}
}
/*************************************************************************
*
* 函数名称:
* ColortoGrayScale()
*
* 参数:
* 返回值:
* void
*
* 说明:
* 该函数用于将24位真彩位图转换成256色灰度图。
*
* 要求目标图像为24位真彩,如果是32位则要先转换成24位,通过Convert32To24()
************************************************************************/
void CDIB::ColortoGrayScale()
{
BITMAPINFO* pTempInfo;
BYTE* pTempData;
BYTE* lpTempData;
BYTE* lpPtr;
DWORD i;
LONG x,y;
float Y;
DWORD LineBytesOld;
DWORD dataBytesOld;
unsigned char Red,Green,Blue,Gray;
if(m_NumColors==0)//真彩图
{
m_NumColors=256;
pTempInfo=(BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER)+m_NumColors*sizeof(RGBQUAD)];
if(!pTempInfo)
{
#ifdef _DEBUG
AfxMessageBox("分配内存出错!");
#endif
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -