📄 dib.cpp
字号:
// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Cloud.h"
#include "Dib.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define PI 3.14159265358979
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDib::CDib()
{
m_Height=0;
m_Width=0;
hDIB=NULL;
bmInfoHeader=NULL;
bmpInfo =NULL;
lpDIBBits=NULL;
}
CDib::~CDib()
{
ClearMemory();
}
/////////////////////////////////////////////////////////////////////////
//打开并读取图像文件
void CDib::ReadDIBFile(LPTSTR lpFilename)
{
BITMAPFILEHEADER bmfHeader;//图像文件头
CFile File;
CFileException Err;
if(!File.Open(lpFilename,CFile::modeRead|CFile::shareDenyNone,&Err))
{
AfxMessageBox(Err.m_cause);
return;
}
File.Read(&bmfHeader,sizeof(bmfHeader));
if(bmfHeader.bfType!=0x4d42)
{
AfxMessageBox("此文件不是位图文件");
return;
}
DWORD Filelen=File.GetLength();
if(bmfHeader.bfSize!=Filelen)
{
AfxMessageBox("该文件已经损坏!");
return;
}
hDIB=NULL;
hDIB=new BYTE[Filelen-sizeof(BITMAPFILEHEADER)];
if(!hDIB)
{
AfxMessageBox("内存不够!");
return;
}
File.Read(hDIB,Filelen-sizeof(BITMAPFILEHEADER));
File.Close();
}
/////////////////////////////////////////////////////////////////////////
//装载DIB
void CDib::LoadDIB(LPTSTR lpFilename)
{
ReadDIBFile(lpFilename);
bmInfoHeader=(LPBITMAPINFOHEADER)hDIB;
bmpInfo=(LPBITMAPINFO)hDIB;
int ColorsNum=GetDIBColorsNum(bmInfoHeader);
lpDIBBits=(BYTE*)hDIB+ColorsNum*sizeof(RGBQUAD)+sizeof(BITMAPINFOHEADER);
m_Height=bmInfoHeader->biHeight;
m_Width=bmInfoHeader->biWidth;
}
long CDib::GetImageHeight()
{
return m_Height;
}
long CDib::GetImageWidth()
{
return m_Width;
}
/////////////////////////////////////////////////////////////////////////
//从得到图像颜色数
int CDib::GetDIBColorsNum(BITMAPINFOHEADER* bmInfoHeader)
{
int ColorsNum;//图像颜色数
switch(bmInfoHeader->biBitCount)
{
case 1:
ColorsNum=2;
break;
case 4:
ColorsNum=16;
break;
case 8:
ColorsNum=256;
break;
default:
ColorsNum=0;
break;
}
return ColorsNum;
}
/////////////////////////////////////////////////////////////////////////
//把DIB选入到指定设备hDC
BOOL CDib::PaintDIB(HDC hDC,long width,long height)
{
int bSuccess;
HPALETTE hPal=NULL;
HPALETTE hOldPal;
if(!hDIB)
return FALSE;
if(!hPal)
CreateDIBPalette();
if(hPal)
{
hOldPal=SelectPalette(hDC,hPal,TRUE);
RealizePalette(hDC);
}
SetStretchBltMode(hDC,COLORONCOLOR);
bSuccess=StretchDIBits(hDC,0,0,width,
height,0,0,m_Width,m_Height,lpDIBBits,
bmpInfo,DIB_RGB_COLORS,SRCCOPY);
if(hOldPal)
SelectPalette(hDC,hOldPal,FALSE);
return bSuccess;
}
/////////////////////////////////////////////////////////////////////////
//生成自己的调色板
HPALETTE CDib::CreateDIBPalette()
{
LOGPALETTE* lpPal;
HPALETTE hPal=NULL;
int wNumColors=GetDIBColorsNum(bmInfoHeader);
lpPal=(LOGPALETTE*)new BYTE[wNumColors*sizeof(PALETTEENTRY)+2*sizeof(WORD)];
lpPal->palNumEntries=wNumColors;
lpPal->palVersion=1;
for(int i=0;i<wNumColors;i++)
{
lpPal->palPalEntry[i].peBlue=bmpInfo->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peGreen=bmpInfo->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peRed=bmpInfo->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peFlags=bmpInfo->bmiColors[i].rgbReserved=(BYTE)0;
}
hPal=CreatePalette(lpPal);
return hPal;
}
/////////////////////////////////////////////////////////////////////////
//释放内存
void CDib::ClearMemory()
{
delete[] hDIB;
delete[] bmInfoHeader;
delete[] bmpInfo;
delete[] lpDIBBits;
}
/////////////////////////////////////////////////////////////////////////
//获得DIB数据指针
HANDLE CDib::GetDIBHandle()
{
return hDIB;
}
/////////////////////////////////////////////////////////////////////////
//从DIB获得DDB
//////////////////////////////////////////
//////////图像灰度线性变换函数
BOOL CDib::OnChangeBrightness(float fa,float fb)
{
if(!lpDIBBits)
{
AfxMessageBox("请先打开图像");
return FALSE;
}
BYTE* temDIBits;
if(bmInfoHeader->biBitCount!=24)
{
AfxMessageBox("只能对24位真彩色的图像进行变换");
return FALSE;
}
int w=m_Width;
int h=m_Height;
int sign=w%2;
long total=w*h*3;
long k=0;
if(sign)
w+=1;
temDIBits=new BYTE[total];
memcpy(temDIBits,lpDIBBits,total);
for(int i=0;i<h;i++)
{
for(int j=0;j<w;j++)
{
float fTem;
fTem=fa*temDIBits[k]+fb;//红色通道
if(fTem>255)
{
lpDIBBits[k]=(BYTE)255;
}else
if(fTem<0)
{
lpDIBBits[k]=(BYTE)0;
}else
{
lpDIBBits[k]=(BYTE)(fTem+0.5);
}
fTem=fa*temDIBits[k+1]+fb;//绿色通道
if(fTem>255)
{
lpDIBBits[k+1]=(BYTE)255;
}else
if(fTem<0)
{
lpDIBBits[k+1]=(BYTE)0;
}else
{
lpDIBBits[k+1]=(BYTE)(fTem+0.5);
}
fTem=fa*temDIBits[k+2]+fb;//蓝色通道
if(fTem>255)
{
lpDIBBits[k+2]=(BYTE)255;
}else
if(fTem<0)
{
lpDIBBits[k+2]=(BYTE)0;
}else
{
lpDIBBits[k+2]=(BYTE)(fTem+0.5);
}
if(k>=total)
break;
k+=3;
}
}
return TRUE;
}
/////////////////////////////////////////////////////////////////
//////////////////灰度拉伸函数
BOOL CDib::OnGrayStretch(BYTE x1,BYTE x2,BYTE y1,BYTE y2)
{
if(!lpDIBBits)
{
AfxMessageBox("请先打开图像");
return FALSE;
}
if(bmInfoHeader->biBitCount!=24)
{
AfxMessageBox("只能对24位真彩色的图像进行变换");
return FALSE;
}
int w=m_Width;
int h=m_Height;
int sign=w%2;
long total=w*h*3;
long k=0;
if(sign)
w+=1;
BYTE A=(y2-y1)/(x2-x1);
for(int i=0;i<h;i++)
{
for(int j=0;j<w;j++)
{
float fTem;
if(lpDIBBits[k]>=x1&&lpDIBBits[k]<=x2)
{
fTem=lpDIBBits[k];
lpDIBBits[k]=(BYTE)fTem*A+y1;
lpDIBBits[k+1]=(BYTE)fTem*A+y1;
lpDIBBits[k+2]=(BYTE)fTem*A+y1;
}else if(lpDIBBits[k]<x1)
{
lpDIBBits[k]=y1;
lpDIBBits[k+1]=y1;
lpDIBBits[k+2]=y1;
}else
{
lpDIBBits[k]=y2;
lpDIBBits[k+1]=y2;
lpDIBBits[k+2]=y2;
}
if(k>=total)
break;
k+=3;
}
}
return TRUE;
}
/////////////////////////////////////////////////////////////////
//////////////////灰度化图像函数
BOOL CDib::OnChangeToGray()
{
if(!lpDIBBits)
{
AfxMessageBox("请先打开图像");
return FALSE;
}
if(bmInfoHeader->biBitCount!=24)
{
AfxMessageBox("只能对24位真彩色的图像进行变换");
return FALSE;
}
int w=m_Width;
int h=m_Height;
int sign=w%2;
long total=w*h*3;
long k=0;
if(sign)
w+=1;
for(int i=0;i<h;i++)
{
for(int j=0;j<w;j++)
{
float fTem;
fTem=(float)(lpDIBBits[k]+lpDIBBits[k+1]+lpDIBBits[k+2])/3;//灰度值为三色RGB的平均值
lpDIBBits[k]=(BYTE)fTem;
lpDIBBits[k+1]=(BYTE)fTem;
lpDIBBits[k+2]=(BYTE)fTem;
if(k>=total)
break;
k+=3;
}
}
return TRUE;
}
////////////////////////////////////////////////////////
//直方图均衡化函数
void CDib::OnHistogramEqualize()
{
if(!lpDIBBits)
{
AfxMessageBox("请先打开图像");
return;
}
if(bmInfoHeader->biBitCount!=24)
{
AfxMessageBox("只能对24位真彩色的图像进行变换");
return;
}
OnChangeToGray();//灰度化图像
int w=m_Width;
int h=m_Height;
int sign=w%2;
long total=w*h*3;
long k=0;//像素lpBITBits的下标
long Temp;
BYTE bMap[256];//新的灰度表
long iCount[256];//图像0-255每种灰度的点数
for(int i=0;i<256;i++)
{
iCount[i]=0;
}
if(sign)
w+=1;
for(i=0;i<h;i++)//统计每一级灰度的点的数量
{
for(int j=0;j<w;j++)
{
iCount[lpDIBBits[k]]++;
if(k>=total)
break;
k+=3;
}
}
for(i=0;i<256;i++)//计算新的灰度表
{
Temp=0;
for(int j=0;j<i;j++)
{
Temp+=iCount[j];
}
bMap[i]=(BYTE)(Temp*255/h/w);
}
k=0;
for(i=0;i<h;i++)//给每个像素点付新值
{
for(int j=0;j<w;j++)
{
BYTE tem=lpDIBBits[k];
lpDIBBits[k]=bMap[tem];
lpDIBBits[k+1]=bMap[tem];
lpDIBBits[k+2]=bMap[tem];
if(k>=total)
break;
k+=3;
}
}
}
////////////////////////////////////////////////////////////////////////
///傅里叶变换In输入,其长度是图像占有字节数的两倍,i=偶数为实部,
//i=奇数为虚部;nn是一个数组代表图像的宽度和高度,
//sign为1或-1,分别表示正、负傅里叶变换
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -