基于单文档的MFC图像增强

目录

function.h

ColorEnhanceDib.h

ColorEnhanceDib.cpp

Dib.h

 Dib.cpp

FrequencyFilterDib.h

 FrequencyFilterDib.cpp

 GrayTransformDib.h

 GrayTransformDib.cpp

HistogramDib.h

HistogramDib.cpp

 SharpenProcessDib.h

SharpenProcessDib.cpp

 SmoothProcessDib.h

SmoothProcessDib.cpp

数字图像处理View.h : C数字图像处理View 类的接口

数字图像处理View.cpp : C数字图像处理View 类的实现


1.新建单文档项目,编辑菜单

_CRT_SECURE_NO_WARNINGS

function.h

// function.h: interface for the function class.
//接口函数类
//#if !defined(AFX_FUNCTION_H__6E194843_FEB3_491F_8062_765AA3465CBC__INCLUDED_)
#define AFX_FUNCTION_H__6E194843_FEB3_491F_8062_765AA3465CBC__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Dib.h"
#include <math.h>
// 常数π
#define pi 3.1415926535
#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)
#include <direct.h>
#include <complex>
using namespace std;
#define PI 3.14159265358979323846//#endif // !defined(AFX_FUNCTION_H__6E194843_FEB3_491F_8062_765AA3465CBC__INCLUDED_)typedef struct{int Value;int Dist;int AngleNumber;
}	MaxValue;struct CplexNum
{double re;double im;
};/
//用于复数运算
CplexNum Add(CplexNum c1,CplexNum c2)
{CplexNum c;c.re=c1.re+c2.re;c.im=c1.im+c2.im;return c;
}
CplexNum Sub(CplexNum c1,CplexNum c2)
{CplexNum c;c.re=c1.re-c2.re;c.im=c1.im-c2.im;return c;
}
CplexNum Mul(CplexNum c1,CplexNum c2)
{CplexNum c;c.re=c1.re*c2.re-c1.im*c2.im;c.im=c1.re*c2.im+c2.re*c1.im;return c;
}/*************************************************************************
* 函数名称:AngleToRadian(int angle)
* 函数参数:
*   int angle
* 函数类型:float      
* 函数功能:用来角度到弧度的转换
************************************************************************/double AngleToRadian(int angle)
{return ((angle)*pi/180.0);
}/*************************************************************************
* 函数名称:ThreeCrossMat(double *pMatrix, int rank, double *pQMatrix, 
double *pMainCross, double *pHypoCross)
* 函数参数:
*   double  *pMatrix ,指向矩阵的指针
*   int     rank  ,矩阵阶数
*   double	 *pQMatrix  , householder变换后的的矩阵的指针
*   double  *pMainCross ,对称三角阵中的主对角元素的指针
*   double  *pHypoCross , 对称三角阵中的次对角元素的指针
* 函数类型:BOOL
*函数功能:将n阶实对称矩阵化为对称三角阵
************************************************************************/BOOL  ThreeCrossMat(double *pMatrix, int rank, double *pQMatrix, double *pMainCross, double *pHypoCross)
{	int i, j, k, u;//变量声明double h, f, g, h2;   for(i = 0; i <= rank-1; i++)// 将矩阵pQMatrix初始化{for(j = 0; j <= rank-1; j++){u = i*rank + j; pQMatrix[u] = pMatrix[u];}}for (i = rank-1; i >= 1; i--){h = 0.0;if (i > 1)for (k = 0; k <= i-1; k++){u = i*rank + k; h = h + pQMatrix[u]*pQMatrix[u];}      if (h + 1.0 == 1.0)// 如果一行全部为零{pHypoCross[i] = 0.0;if (i == 1) {pHypoCross[i] = pQMatrix[i*rank+i-1];}pMainCross[i] = 0.0;}        		else{// 否则求正交矩阵的值pHypoCross[i] = sqrt(h);// 求次对角元素的值            			u = i*rank + i - 1;if (pQMatrix[u] > 0.0) // 判断i行i-1列元素是不是大于零{pHypoCross[i] = -pHypoCross[i];}            h = h - pQMatrix[u]*pHypoCross[i];pQMatrix[u] = pQMatrix[u] - pHypoCross[i];f = 0.0;            			for (j = 0; j <= i-1; j++)// householder变换{ pQMatrix[j*rank+i] = pQMatrix[i*rank+j] / h;g = 0.0;for (k = 0; k <= j; k++){g = g + pQMatrix[j*rank+k]*pQMatrix[i*rank+k];}                if (j+1 <= i-1)for (k = j+1; k <= i-1; k++){g = g + pQMatrix[k*rank+j]*pQMatrix[i*rank+k];}                pHypoCross[j] = g / h;f = f + g*pQMatrix[j*rank+i];}h2 = f / (h + h);            			for (j = 0; j <= i-1; j++)// 求正交矩阵的值{f = pQMatrix[i*rank + j];g = pHypoCross[j] - h2*f;pHypoCross[j] = g;for (k = 0; k <= j; k++){u = j*rank + k;pQMatrix[u] = pQMatrix[u] - f*pHypoCross[k] - g*pQMatrix[i*rank + k];}}pMainCross[i] = h;}}for (i = 0; i <= rank-2; i++) // 赋零值{pHypoCross[i] = pHypoCross[i + 1];}pHypoCross[rank - 1] = 0.0;pMainCross[0]        = 0.0;    for (i = 0; i <= rank-1; i++){ // 主对角元素的计算		if ((pMainCross[i] != 0.0) && (i-1 >= 0))for (j = 0; j <= i-1; j++){g = 0.0;for (k = 0; k <= i-1; k++){g = g + pQMatrix[i*rank + k]*pQMatrix[k*rank + j];}for (k = 0; k <= i-1; k++){ u = k*rank + j;pQMatrix[u] = pQMatrix[u] - g*pQMatrix[k*rank + i];}}       u = i*rank + i;// 存储主对角线的元素pMainCross[i] = pQMatrix[u]; pQMatrix[u]   = 1.0;       		if (i-1 >= 0)// 将三对角外所有的元素赋零值for (j = 0; j <= i-1; j++){ pQMatrix[i*rank + j] = 0.0; pQMatrix[j*rank+i]   = 0.0;}}    return(TRUE);// 返回
}/*************************************************************************
*
* 函数名称:EigenvalueVector(int rank, double *pMainCross, double *pHypoCross, 
double *pMatrix, double Precision, int MaxT)
* 函数参数:
*   int     rank ,矩阵A的阶数
*   double	 *pMainCross  ,对称三角阵中的主对角元素的指针,返回时存放A的特征值
*   double  *pHypoCross  ,对称三角阵中的次对角元素的指针
*	 double  *pMatrix  ,对称矩阵A的特征向量的指针
*   double Precision ,控制精度
*   int MaxT  , 最大迭代次数
* 函数类型:BOOL 
* 函数功能:用计算实对称三角矩阵的全部特征值以及相应的特征向量
************************************************************************/
BOOL EigenvalueVector(int rank, double *pMainCross, double *pHypoCross, double *pMatrix, double Precision, int MaxT)
{int i, j, k, m, it, u, v;// 变量声明double d, f, h, g, p, r, e, s;pHypoCross[rank - 1] = 0.0; // 初始化d = 0.0; f = 0.0;for(j = 0; j <= rank-1; j++){							//  迭代精度的控制		it = 0;h = Precision * (fabs(pMainCross[j]) + fabs(pHypoCross[j]));if(h > d) {d = h;}m = j;while((m <= rank-1) && (fabs(pHypoCross[m]) > d)) {m = m + 1;    }if(m != j){// 迭代求矩阵A的特征值和特征向量do{// 超过迭代次数,迭代失败if(it == MaxT){return(FALSE);}it = it + 1;g = pMainCross[j];p = (pMainCross[j + 1] - g) / (2.0 * pHypoCross[j]);r = sqrt(p*p + 1.0);                // 如果p大于0if (p >= 0.0){pMainCross[j] = pHypoCross[j]/(p + r);}else{pMainCross[j] = pHypoCross[j]/(p - r); }h = g - pMainCross[j];                //  计算主对角线的元素for (i = j + 1; i <= rank - 1; i++){pMainCross[i] = pMainCross[i] - h;  }// 赋值f = f + h;p = pMainCross[m];e = 1.0; s = 0.0;for(i = m - 1; i >= j; i--){g = e * pHypoCross[i];h = e * p;//  主对角线元素的绝对值是否大于次对角线元素的if(fabs(p) >= fabs(pHypoCross[i])){e = pHypoCross[i] / p;r = sqrt(e*e + 1.0);pHypoCross[i + 1] = s*p*r; s = e / r;  e = 1.0 / r;}else{e = p / pHypoCross[i]; r = sqrt(e*e + 1.0);pHypoCross[i+1] = s * pHypoCross[i] * r;s = 1.0 / r; e = e / r;}                   p = e*pMainCross[i] - s*g;pMainCross[i + 1] = h + s*(e*g + s*pMainCross[i]);// 重新存储特征向量for(k = 0; k <= rank - 1; k++){u = k*rank + i + 1; v = u - 1;h = pMatrix[u]; pMatrix[u] = s*pMatrix[v] + e*h;pMatrix[v] = e*pMatrix[v] - s*h;}}               // 将主对角线和次对角线元素重新赋值pHypoCross[j] = s * p; pMainCross[j] = e * p;}while (fabs(pHypoCross[j]) > d);}pMainCross[j] = pMainCross[j] + f;}   	for (i = 0; i <= rank-1; i++){// 返回A的特征值k = i; p = pMainCross[i];        		if(i+1 <= rank-1){// 将A特征值赋给pj = i + 1;while((j <= rank-1) && (pMainCross[j] <= p)){ k = j; p = pMainCross[j]; j = j+1;}}        		if (k != i){// 存储A的特征值和特征向量pMainCross[k] = pMainCross[i];pMainCross[i] = p;for(j = 0; j <= rank-1; j++){u = j*rank + i; v = j*rank + k;p = pMatrix[u]; pMatrix[u] = pMatrix[v];pMatrix[v] = p;}}}  return(TRUE);// 返回
}/*************************************************************************
* 函数名称:LogTranslation(LPSTR lpSrcStartBits, long lWidth, long lHeight, long lLineBytes)
* 函数参数:
LPSTR	lpSrcStartBits,指向DIB起始像素的指针
long	lWidth,DIB图像的宽度
long	lHeight,DIB图像的高度
long	lLineBytes,DIB图像的行字节数,为4的倍数
* 函数类型:BOOL        
* 函数功能:该函数用来对图像进行对数变换 
************************************************************************/BOOL  LogTranslation(LPSTR lpSrcStartBits, long lWidth, long lHeight, long lLineBytes)
{			long i;                 //行循环变量long j;                 //列循环变量unsigned char*	lpSrcUnChr;	//指向像素的指针for(i = 0; i < lHeight; i++)// 行{		for(j = 0; j < lWidth; j++)// 列{	lpSrcUnChr= (unsigned char*)lpSrcStartBits + lLineBytes * (lHeight - 1 - i) + j;// 指向DIB第i行,第j个像素的指针*lpSrcUnChr=50*(unsigned char)log((double)(*lpSrcUnChr+1));}}return TRUE;
}/*************************************************************************
* 函数名称:
*   Transpose(LPSTR lpSrcDib,LPSTR lpDibBits,long	lWidth,long	lHeight,
long lLineBytes,long lDstLineBytes)
* 函数参数:
*   LPSTR	lpSrcDib,指向源DIB的指针
LPSTR	lpSrcStartBits,指向DIB起始像素的指针
long	lWidth,DIB图像的宽度
long	lHeight,DIB图像的高度
long	lLineBytes,DIB图像的行字节数,为4的倍数
long	lDstLineBytes,临时DIB图像的行字节数,为4的倍数
* 函数类型:BOOL        
* 函数功能:该函数用来转置DIB图像
************************************************************************/BOOL  Transpose(LPSTR lpSrcDib,LPSTR lpSrcStartBits,long lWidth,long lHeight,long lLineBytes,long lDstLineBytes)
{long i;                 //行循环变量long j;                 //列循环变量LPSTR	lpSrcDIBBits;	//指向源像素的指针LPSTR	lpDstDIBBits;	//指向临时图像对应像素的指针LPSTR	lpDstStartBits;	//指向临时图像对应像素的指针 		HLOCAL	hDstDIBBits;	//临时图像句柄LPBITMAPINFOHEADER lpbmi;							  // 指向BITMAPINFOHEADER结构的指针lpbmi = (LPBITMAPINFOHEADER)lpSrcDib;hDstDIBBits= LocalAlloc(LHND, lWidth * lDstLineBytes);// 分配临时内存if (hDstDIBBits== NULL)								 // 判断是否内存分配{		return FALSE;									// 分配内存失败}	lpDstStartBits= (char * )LocalLock(hDstDIBBits);	// 锁定内存		for(i = 0; i < lHeight; i++)						// 针对图像每行进行操作{		for(j = 0; j < lWidth; j++)						// 针对每行图像每列进行操作{						lpSrcDIBBits= (char *)lpSrcStartBits + lLineBytes * (lHeight - 1 - i) + j;// 指向源DIB第i行,第j个像素的指针lpDstDIBBits= (char *)lpDstStartBits + lDstLineBytes * (lWidth - 1 - j) + i;// 指向转置DIB第j行,第i个像素的指针			*(lpDstDIBBits)= *(lpSrcDIBBits);			// 复制像素			}		}	memcpy(lpSrcStartBits, lpDstStartBits, lWidth * lDstLineBytes);// 复制转置后的图像lpbmi->biWidth = lHeight;		lpbmi->biHeight = lWidth;LocalUnlock(hDstDIBBits);							// 释放内存LocalFree(hDstDIBBits);								return TRUE;										// 返回
}/*************************************************************************
* 函数名称:Mirror(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
* 函数参数:
LPSTR	lpSrcStartBits,指向DIB起始像素的指针
long	lWidth,DIB图像的宽度
long	lHeight,DIB图像的高度
long	lLineBytes,DIB图像的行字节数,为4的倍数
* 函数类型:BOOL        
* 函数功能:该函数用来镜像DIB图像,本程序只实现了水平镜像,垂直镜像的原理书中也谈到。 很容易实现           
************************************************************************/BOOL  Mirror(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
{	long i;                 //行循环变量long j;                 //列循环变量LPSTR	lpSrcDIBBits;	//指向源像素的指针LPSTR	lpDstDIBBits;	//指向临时图像对应像素的指针 		HLOCAL	hDstDIBBits;	//临时图像句柄LPSTR	lpBits;	// 指向中间像素的指针,当复制图像时,提供临时的像素内存空间hDstDIBBits= LocalAlloc(LHND, lLineBytes);// 分配临时内存保存行图像if (hDstDIBBits == NULL)		{		return FALSE;									// 分配内存失败}		lpDstDIBBits= (char * )LocalLock(hDstDIBBits);// 锁定				for(i = 0; i < lHeight; i++)// 水平镜像,针对图像每行进行操作{			for(j = 0; j < lWidth / 2; j++)// 针对每行图像左半部分进行操作{							lpSrcDIBBits= (char *)lpSrcStartBits + lLineBytes * i + j;// 指向倒数第i行,第j个像素的指针								lpBits= (char *)lpSrcStartBits + lLineBytes * (i + 1) - j;// 指向倒数第i+1行,倒数第j个像素的指针								*lpDstDIBBits=*lpBits;//保存中间像素								*lpBits = *lpSrcDIBBits;// 将倒数第i行,第j个像素复制到倒数第i行,倒数第j个像素								*lpSrcDIBBits=*lpDstDIBBits;// 将倒数第i行,倒数第j个像素复制到倒数第i行,第j个像素}			}		LocalUnlock(hDstDIBBits);// 释放内存LocalFree(hDstDIBBits);return TRUE;
}/*************************************************************************
* 函数名称:Mirror2(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
* 函数参数:
LPSTR	lpSrcStartBits,指向DIB起始像素的指针
long	lWidth,DIB图像的宽度
long	lHeight,DIB图像的高度
long	lLineBytes,DIB图像的行字节数,为4的倍数
* 函数类型:BOOL        
* 函数功能:该函数用来垂直镜像DIB图像         
************************************************************************/BOOL  Mirror2(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
{	long i;                 //行循环变量long j;                 //列循环变量LPSTR	lpSrcDIBBits;	//指向源像素的指针LPSTR	lpDstDIBBits;	//指向临时图像对应像素的指针 		HLOCAL	hDstDIBBits;	//临时图像句柄LPSTR	lpBits;	// 指向中间像素的指针,当复制图像时,提供临时的像素内存空间hDstDIBBits= LocalAlloc(LHND, lLineBytes);// 分配临时内存保存行图像if (hDstDIBBits == NULL)		{		return FALSE;									// 分配内存失败}		lpDstDIBBits= (char * )LocalLock(hDstDIBBits);// 锁定				for(i = 0; i < lHeight / 2; i++)// 垂直镜像,针对图像每行进行操作{			//for(j = 0; j < lWidth / 2; j++)// 针对每行图像左半部分进行操作//{							lpSrcDIBBits= (char *)lpSrcStartBits + lLineBytes * i ;//+ j;// 指向倒数第i行,第j个像素的指针								lpBits= (char *)lpSrcStartBits + lLineBytes * (lHeight - i + 1);// - j;// 指向倒数第i+1行,倒数第j个像素的指针								memcpy(lpDstDIBBits, lpBits, lLineBytes);memcpy(lpBits, lpSrcDIBBits, lLineBytes);memcpy(lpSrcDIBBits, lpDstDIBBits, lLineBytes);//*lpDstDIBBits=*lpBits;//保存中间像素								//*lpBits = *lpSrcDIBBits;// 将倒数第i行,第j个像素复制到倒数第i行,倒数第j个像素								//*lpSrcDIBBits=*lpDstDIBBits;// 将倒数第i行,倒数第j个像素复制到倒数第i行,第j个像素//}			}		LocalUnlock(hDstDIBBits);// 释放内存LocalFree(hDstDIBBits);return TRUE;
}/*************************************************************************
* 函数名称:Translation(LPSTR lpSrcStartBits, long lWidth, long lHeight, long lXOffset, 
long lYOffset,long lLineBytes,long lDstLineBytes)
* 函数参数:
*   LPSTR	lpSrcStartBits,指向源DIB起始像素的指针
* 	 long	lWidth,DIB图像的宽度
* 	 long	lHeight,DIB图像的高度
* 	 long	lXOffset,X方向偏移量
* 	 long	lYOffset,Y方向偏移量
* 	 long	lLineBytes,DIB图像的行字节数,为4的倍数
* 	 long	lDstLineBytes,临时DIB图像的行字节数,为4的倍数
* 函数类型:BOOL        
* 函数功能:该函数用来平移DIB图像
************************************************************************/
BOOL  Translation(LPSTR lpSrcStartBits, long lWidth, long lHeight, long lXOffset, long lYOffset,long lLineBytes,long lDstLineBytes)					 
{	long i;                 //行循环变量long j;                 //列循环变量LPSTR	lpSrcDIBBits;	//指向源像素的指针LPSTR	lpDstDIBBits;	//指向临时图像对应像素的指针LPSTR	lpDstStartBits;	//指向临时图像对应像素的指针 		HLOCAL	hDstDIBBits;	//临时图像句柄hDstDIBBits= LocalAlloc(LHND, lWidth * lDstLineBytes);// 分配临时内存lpDstStartBits= (char * )LocalLock(hDstDIBBits);// 锁定内存	if (hDstDIBBits== NULL)// 判断是否内存分配		return FALSE;// 分配内存失败				for(i = 0; i < lHeight; i++)// 行{for(j = 0; j < lWidth; j++)	// 列{lpDstDIBBits=(char*)lpDstStartBits+lLineBytes*(lHeight-1-i)+j;// 指向新DIB第i行,第j个像素的指针												if( (j-lYOffset>= 0) && (j-lYOffset< lWidth) && // 像素在源DIB中的坐标j-lXOffset(i-lXOffset>= 0) && (i-lXOffset < lHeight))// 判断是否在源图范围内{lpSrcDIBBits=(char *)lpSrcStartBits+lLineBytes*(lHeight-1-(i-lXOffset))+(j-lYOffset);// 指向源DIB第i0行,第j0个像素的指针								*lpDstDIBBits= *lpSrcDIBBits;// 复制像素}else{				* ((unsigned char*)lpDstDIBBits) = 255;// 源图中没有的像素,赋为255}			}}memcpy(lpSrcStartBits, lpDstStartBits, lLineBytes * lHeight);// 复制图像		LocalUnlock(hDstDIBBits);// 释放内存LocalFree(hDstDIBBits);		return TRUE;
}/*************************************************************************
* 函数名称:Rotate(LPSTR lpSrcDib, LPSTR lpSrcStartBits,long lWidth, long lHeight,
long lLineBytes,	WORD palSize, long lDstWidth, 
long lDstHeight,long lDstLineBytes,float	fSina, float fCosa)
* 函数参数:
*   LPSTR lpSrcDib,指向源DIB的指针
*   LPSTR lpSrcStartBits,指向源DIB的起始像素的指针
*   long lWidth,源DIB图像宽度
*   long lHeight,源DIB图像高度
*	 long lLineBytes,源DIB图像字节宽度(4的倍数)
*	 WORD palSize,源DIB图像调色板大小
*	 long lDstWidth,目标图像宽度
*	 long lDstHeight,目标DIB图像高度
*	 long lDstLineBytes,目标DIB图像行字节数(4的倍数)
*	 float	fSina,旋转角的余弦,说明:为了避免两次求取正余弦,这里作为两个函数参数来用
*	 float fCosa,旋转角的正弦
* 函数类型:HGLOBAL
* 函数功能:用来旋转DIB图像
************************************************************************/
HGLOBAL  Rotate(LPSTR lpSrcDib, LPSTR lpSrcStartBits,long lWidth, long lHeight,long lLineBytes,	WORD palSize, long lDstWidth, long lDstHeight,long lDstLineBytes,float	fSina, float fCosa)
{	float varFloat1;        //浮点参数变量1float varFloat2;        //浮点参数变量2LPSTR	lpDstDib;		//指向临时图像的指针long i;                 //行循环变量long j;                 //列循环变量long i1;                 //行循环变量long j1;                 //列循环变量LPSTR	lpSrcDIBBits;	//指向源像素的指针LPSTR	lpDstDIBBits;	//指向临时图像对应像素的指针LPSTR	lpDstStartBits;	//指向临时图像对应像素的指针 			LPBITMAPINFOHEADER lpbmi;// 指向BITMAPINFOHEADER结构的指针		varFloat1= (float) (-0.5 * (lDstWidth - 1) * fCosa - 0.5 * (lDstHeight - 1) * fSina// 将经常用到的两个常数事先求出,以便作为常数使用+ 0.5 * (lDstWidth  - 1));varFloat2= (float) ( 0.5 * (lDstWidth - 1) * fSina - 0.5 * (lDstHeight - 1) * fCosa+ 0.5 * (lDstHeight - 1));		HGLOBAL hDIB = (HGLOBAL) ::GlobalAlloc(GHND, lDstLineBytes * lDstHeight + *(LPDWORD)lpSrcDib +palSize);// 分配内存,以保存新DIB		if (hDIB == NULL)// 判断是否是有效的DIB对象{		return FALSE;// 不是,则返回}	lpDstDib=  (char * )::GlobalLock((HGLOBAL) hDIB);// 锁定内存		memcpy(lpDstDib,lpSrcDib, *(LPDWORD)lpSrcDib +palSize);// 复制DIB信息头和调色板			lpbmi = (LPBITMAPINFOHEADER)lpDstDib;// 获取指针	lpbmi->biHeight=lDstHeight;// 更新DIB中图像的高度和宽度lpbmi->biWidth =lDstWidth;lpDstStartBits=lpDstDib+ *(LPDWORD)lpDstDib+palSize;// 求像素起始位置,作用如同::FindDIBBits(gCo.lpSrcDib),这里尝试使用了这种方法,以避免对全局函数的调用for(i = 0; i < lDstHeight; i++)// 行操作{		for(j = 0; j < lDstWidth; j++)// 列操作{			lpDstDIBBits= (char *)lpDstStartBits+ lDstLineBytes * (lDstHeight - 1 - i) + j;// 指向新DIB第i行,第j个像素的指针			i1= (long) (-((float) j) * fSina + ((float) i) * fCosa + varFloat2 + 0.5);// 计算该像素在源DIB中的坐标j1= (long) ( ((float) j) * fCosa + ((float) i) * fSina + varFloat1 + 0.5);						if( (j1>= 0) && (j1< lWidth) && (i1>= 0) && (i1< lHeight)){// 判断是否在源图内				lpSrcDIBBits= (char *)lpSrcStartBits+ lLineBytes * (lHeight - 1 -i1) + j1;// 指向源DIB第i0行,第j0个像素的指针								*lpDstDIBBits= *lpSrcDIBBits;// 复制像素}else{* ((unsigned char*)lpDstDIBBits) = 255;// 源图中不存在的像素,赋为255}			}		}return hDIB;
}/*************************************************************************
* 函数名称:Zoom(LPSTR lpSrcDib, LPSTR lpSrcStartBits,long lWidth, long lHeight,
long lLineBytes,	WORD palSize, long lDstWidth, 
long lDstHeight,long lDstLineBytes,float	fXZoomRatio, float fYZoomRatio)
* 函数参数:
*   LPSTR lpSrcDib,指向源DIB的指针
*   LPSTR lpSrcStartBits,指向源DIB的起始像素的指针
*   long lWidth,源DIB图像宽度
*   long lHeight,源DIB图像高度
*	 long lLineBytes,源DIB图像字节宽度(4的倍数)
*	 WORD palSize,源DIB图像调色板大小
*	 long lDstWidth,目标图像宽度
*	 long lDstHeight,目标DIB图像高度
*	 long lDstLineBytes,目标DIB图像行字节数(4的倍数)
*	 float	fhorRatio,水平缩放比率
*	 float fverRatio,垂直缩放比率
* 函数类型:HGLOBAL
* 函数功能:用来缩放DIB图像
************************************************************************/HGLOBAL  Zoom(LPSTR lpSrcDib, LPSTR lpSrcStartBits,long lWidth, long lHeight,long lLineBytes,	WORD palSize,long lDstWidth,long lDstLineBytes,long lDstHeight,float fhorRatio,float fverRatio)
{			LPSTR	lpDstDib;		//指向临时图像的指针	long i;                 //行循环变量long j;                 //列循环变量long i1;                 //行循环变量long j1;                 //列循环变量LPSTR	lpSrcDIBBits;	//指向源像素的指针LPSTR	lpDstDIBBits;	//指向临时图像对应像素的指针LPSTR	lpDstStartBits;	//指向临时图像对应像素的指针 		LPBITMAPINFOHEADER lpbmi;// 指向BITMAPINFO结构的指针// 分配内存,以保存缩放后的DIBHGLOBAL hDIB = (HGLOBAL) ::GlobalAlloc(GHND, lDstLineBytes* lDstHeight + *(LPDWORD)lpSrcDib +palSize);	if (hDIB == NULL)// 判断是否是有效的DIB对象{		return FALSE;// 不是,则返回}		lpDstDib=  (char * )::GlobalLock((HGLOBAL) hDIB);// 锁定内存		memcpy(lpDstDib, lpSrcDib, *(LPDWORD)lpSrcDib +palSize);// 复制DIB信息头和调色板		lpDstStartBits=lpDstDib+ *(LPDWORD)lpDstDib// 找到新DIB像素起始位置+palSize;// 求像素起始位置,作用如同::FindDIBBits(lpSrcDib),这里尝试使用了这种方法,以避免对全局函数的调用		lpbmi = (LPBITMAPINFOHEADER)lpDstDib;// 获取指针lpbmi->biWidth = lDstWidth;// 更新DIB中图像的高度和宽度lpbmi->biHeight =lDstHeight;	for(i = 0; i < lDstHeight; i++)// 行操作{		for(j = 0; j < lDstWidth; j++)// 列操作{// 指向新DIB第i行,第j个像素的指针lpDstDIBBits= (char *)lpDstStartBits + lDstLineBytes * (lDstHeight-1-i)+j;						i1= (long) (i / fverRatio + 0.5);// 计算该像素在源DIB中的坐标j1= (long) (j / fhorRatio + 0.5);			if( (j1>= 0) && (j1< lWidth) && (i1>= 0) && (i1< lHeight)){// 判断是否在源图内				lpSrcDIBBits= (char *)lpSrcStartBits+ lLineBytes * (lHeight - 1 -i1) + j1;// 指向源DIB第i行,第j个像素的指针								*lpDstDIBBits= *lpSrcDIBBits;// 复制像素}else{* ((unsigned char*)lpDstDIBBits) = 255;// 源图中不存在的像素,赋为255}				}		}return hDIB;
}/*************************************************************************
* 函数名称:FastFourierTran(CplexNum * pTd, CplexNum* pFd, int power)
* 函数参数:
*   CplexNum * pTd,指向时域数组的指针
*   CplexNum * pFd,指向频域数组的指针
*   int             power,2的幂数,即迭代次数
* 函数类型:void 
函数功能:用来实现快速付立叶变换
************************************************************************/
void  FastFourierTran(CplexNum * pTd, CplexNum * pFd, int power)
{	long i;                 //行循环变量long j;                 //列循环变量long	dotCount;// 付立叶变换点数		int		k;// 循环变量		int		bfsize,p;// 中间变量		double	angle;// 角度	CplexNum *pWn,*temReg1,*temReg2,*temReg;	dotCount= 1 <<power;// 计算付立叶变换点数		pWn= new CplexNum[sizeof(CplexNum)*dotCount/ 2];// 分配运算所需存储器temReg1 = new CplexNum[sizeof(CplexNum)*dotCount];temReg2 = new CplexNum[sizeof(CplexNum)*dotCount];		for(i = 0; i < dotCount/ 2; i++)// 计算加权系数{angle = -i * pi* 2 / dotCount;pWn[i].re = cos(angle);pWn[i].im=sin(angle);}	memcpy(temReg1, pTd, sizeof(CplexNum)*dotCount);// 将时域点写入temReg1		for(k = 0; k < power; k++)// 采用蝶形算法进行快速付立叶变换{for(j = 0; j < 1 << k; j++){bfsize = 1 << (power-k);for(i = 0; i < bfsize / 2; i++){p = j * bfsize;temReg2[i+p]=Add(temReg1[i+p],temReg1[i+p+bfsize/2]);temReg2[i+p+bfsize/2]=Mul(Sub(temReg1[i+p],temReg1[i+p+bfsize/2]),pWn[i*(1<<k)]);}}temReg  = temReg1;temReg1 = temReg2;temReg2 = temReg;}		for(j = 0; j <dotCount; j++)// 重新排序{p = 0;for(i = 0; i <power; i++){if (j&(1<<i)){p+=1<<(power-i-1);}}pFd[j]=temReg1[p];}		delete pWn;// 释放内存delete temReg1;delete temReg2;
}/*************************************************************************
*
* 函数名称:InverFastFourierTran(CplexNum * pFd, CplexNum * pTd, int power)
* 函数参数:
*   CplexNum  * pFd,指向频域值的指针
*   CplexNum * pTd,指向时域值的指针
*   int power	,2的幂数
*函数类型:void
*函数功能:用来实现快速付立叶反变换
************************************************************************/
void  InverFastFourierTran(CplexNum * pFd, CplexNum * pTd, int power)
{	LONG	dotCount;			// 付立叶变换点数	int		i;				// 循环变量CplexNum *pX;		dotCount= 1 << power;		// 计算付立叶变换点数		pX = new CplexNum[sizeof(CplexNum)*dotCount];// 分配运算所需存储器		memcpy(pX, pFd, sizeof(CplexNum)*dotCount);// 将频域点写入X		for(i = 0; i <dotCount; i++)// 求共轭{pX[i].re= pX[i].re;pX[i].im=-pX[i].im;}	FastFourierTran(pX, pTd, power);// 调用快速付立叶变换		for(i = 0; i <dotCount; i++)// 求时域点的共轭{pTd[i].re =pTd[i].re/dotCount;pTd[i].im=-pTd[i].im/dotCount;}		delete pX;				// 释放内存
}/*************************************************************************
* 函数名称:Fourier(CplexNum * pTd, int lWidth, int lHeight, CplexNum * pFd)
* 函数参数:
*   CplexNum * pTd,指向时域值的指针
*   int    lWidth,图像宽度
*   int    lHeight,图像高度
*   CplexNum * pFd	,指向频域值的指针
*
* 函数类型:void
* 函数功能:二维快速傅立叶变换
*************************************************************************/
void  Fourier(CplexNum * pTd, int lWidth, int lHeight, CplexNum * pFd)
{// 循环控制变量int	j;int	i;// 进行傅立叶变换的宽度和高度,(2的整数次幂)// 图像的宽度和高度不一定为2的整数次幂int		wid=1;int 	hei=1;int		widpor=0,heiPor=0;//2的幂数while(wid * 2 <= lWidth)// 计算进行付立叶变换的宽度和高度(2的整数次方){wid *= 2;widpor++;}	while(hei * 2 <= lHeight){hei *= 2;heiPor++;}	for(i = 0; i < hei; i++){// x方向进行快速傅立叶变换FastFourierTran(&pTd[wid * i], &pFd[wid * i], widpor);}// pFd中目前存储了pTd经过行变换的结果// 为了直接利用FastFourierTran,需要把pFd的二维数据转置,再一次利用FastFourierTran进行// 傅立叶行变换(实际上相当于对列进行傅立叶变换)for(i = 0; i < hei; i++){for(j = 0; j < wid; j++){pTd[hei * j + i] = pFd[wid * i + j];}}for(j = 0; j < wid; j++){// 对x方向进行快速傅立叶变换,实际上相当于对原来的图像数据进行列方向的// 傅立叶变换FastFourierTran(&pTd[j * hei], &pFd[j * hei], heiPor);}// pFd中目前存储了pTd经过二维傅立叶变换的结果,但是为了方便列方向// 的傅立叶变换,对其进行了转置,现在把结果转置回来for(i = 0; i < hei; i++){for(j = 0; j < wid; j++){pTd[wid * i + j] = pFd[hei * j + i];}}memcpy(pTd, pFd, sizeof(CplexNum) * hei * wid );
}
/*************************************************************************
* 函数名称:InverseFourier(CplexNum * pFd, CplexNum * pTd, int lWidth, int lHeight)
* 函数参数:
*   CplexNum * pTd,指向时域值的指针
*   CplexNum * pFd	,指向频域值的指针
*   int    lWidth,图像宽度
*   int    lHeight,图像高度
* 函数类型:void
* 函数功能:二维快速傅立叶反变换
*************************************************************************/
void  InverseFourier(CplexNum * pFd, CplexNum * pTd, int lWidth, int lHeight)
{// 循环控制变量int	j;int	i;// 进行傅立叶变换的宽度和高度,(2的整数次幂)// 图像的宽度和高度不一定为2的整数次幂int		wid=1;int 	hei=1;int		widpor=0,heiPor=0;//2的幂数while(wid * 2 <= lWidth)// 计算进行付立叶变换的宽度和高度(2的整数次方){wid *= 2;widpor++;}	while(hei * 2 <= lHeight){hei *= 2;heiPor++;}		// 分配工作需要的内存空间CplexNum *pCWork= new CplexNum[sizeof(CplexNum)*wid * hei];//临时变量CplexNum *pCTmp ;// 为了利用傅立叶正变换,可以把傅立叶频域的数据取共轭// 然后直接利用正变换,输出结果就是傅立叶反变换结果的共轭for(i = 0; i < hei; i++){for(j = 0; j < wid; j++){pCTmp = &pFd[wid * i + j] ;pCWork[wid * i + j].re=pCTmp->re;pCWork[wid * i + j].im=-pCTmp->im;//= complex<double>( pCTmp->real() , -pCTmp->imag() );}}// 调用傅立叶正变换Fourier(pCWork, lWidth, lHeight, pTd) ;// 求时域点的共轭,求得最终结果// 根据傅立叶变换原理,利用这样的方法求得的结果和实际的时域数据// 相差一个系数for(i = 0; i < hei; i++){for(j = 0; j < wid; j++){pCTmp = &pTd[wid * i + j];pTd[wid * i + j].re=pCTmp->re/(wid*hei);pTd[wid * i + j].im=-pCTmp->im/(wid*hei);			}}delete pCWork ;
}/*************************************************************************
* 函数名称:DisFCosTran(double *pTd, double *pFd, int power)
* 函数参数:
*   double * pTd,指向时域值的指针
*   double * pFd,指向频域值的指针
*   int    power,2的幂数
*
* 函数类型:void
* 函数功能: 用来实现快速离散余弦变换
************************************************************************/
void  DisFCosTran(double *pTd, double *pFd, int power)
{	long i;                 //行循环变量				long	dotCount;// 离散余弦变换点数			double	dTemp;// 临时变量	CplexNum *temReg;		dotCount = 1<<power;// 计算离散余弦变换点数		temReg = new CplexNum[sizeof(CplexNum) *dotCount*2];// 分配内存		memset(temReg, 0, sizeof(CplexNum) * dotCount * 2);// 赋为0		for(i=0;i<dotCount;i++)// 将时域点写入数组temReg{temReg[i].re=pTd[i];temReg[i].im=0;}		FastFourierTran(temReg,temReg,power+1);// 调用快速付立叶变换		dTemp = 1/sqrt((double)dotCount);// 调整系数		pFd[0] = temReg[0].re*dTemp;// 求pFd[0]	dTemp *= sqrt(2.0f);		for(i = 1; i < dotCount; i++)// 求pFd[u]	{pFd[i]=(temReg[i].re* cos(i*pi/(dotCount*2)) + temReg[i].im* sin(i*pi/(dotCount*2))) * dTemp;}		delete temReg;// 释放内存
}/*************************************************************************
* 函数名称:CosTran(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
* 函数参数:
*   LPSTR lpSrcStartBits,指向DIB起始像素的指针
*   long lWidth,DIB的宽度
*   long lHeight,DIB的高度
*	 long lLineBytes,DIB的行字节数,为4的倍数
* 函数类型:BOOL
* 函数功能: 用来对图像进行离散余弦变换
************************************************************************/
BOOL  CosTran(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
{		unsigned char*	lpSrcUnChr;	//指向像素的指针long i;                 //行循环变量long j;                 //列循环变量 			long	wid=1,hei=1;// 进行付立叶变换的宽度和高度,初始化为1double	dTemp;// 中间变量	int		widpor=0,heiPor=0;//2的幂数while(wid * 2 <= lWidth)// 计算进行离散余弦变换的宽度和高度(2的整数次方){wid *= 2;widpor++;}	while(hei * 2 <= lHeight){hei *= 2;heiPor++;}		double *pTd= new double[wid * hei];// 分配内存double *pFd = new double[wid * hei];		for(i = 0; i < hei; i++)// 行{		for(j = 0; j < wid; j++)// 列{// 指向DIB第i行,第j个像素的指针lpSrcUnChr= (unsigned char*)lpSrcStartBits + lLineBytes * (lHeight- 1 - i) + j;						pTd[j + i * wid] = *(lpSrcUnChr);// 给时域赋值}}	for(i = 0; i < hei; i++){		DisFCosTran(&pTd[wid * i], &pFd[wid * i], widpor);// 对y方向进行离散余弦变换}		for(i = 0; i < hei; i++)// 保存计算结果{for(j = 0; j < wid; j++){pTd[j * hei + i] = pFd[j + wid * i];}}	for(j = 0; j < wid; j++){		DisFCosTran(&pTd[j * hei], &pFd[j * hei], heiPor);// 对x方向进行离散余弦变换}		for(i = 0; i < hei; i++)// 行{		for(j = 0; j < wid; j++)// 列{			dTemp = fabs(pFd[j*hei+i]);// 计算频谱if (dTemp > 255)// 是否超过255,超过的,直接设置为255{dTemp = 255;}			// 指向DIB第y行,第x个像素的指针lpSrcUnChr= (unsigned char*)lpSrcStartBits + lLineBytes * (lHeight- 1 - i) + j;						* (lpSrcUnChr) = (BYTE)(dTemp);// 更新源图像}}		delete pTd;// 释放内存delete pFd;	return TRUE;
}/*************************************************************************
* 函数名称:Walshei_Har(double *pTd, double *pFd, int power)
* 函数参数:
*   double * pTd,指向时域值的指针
*   double * pFd,指向频域值的指针
*   int    power,2的幂数
*
* 函数类型:void
* 函数功能: 用来实现快速沃尔什-哈达玛变换
************************************************************************/void  Walshei_Har(double *pTd, double *pFd, int power)
{	long	dotCount;// 沃尔什-哈达玛变换点数		int		i,j,k;// 循环变量	int		bfsize,p;// 中间变量	double *temReg1,*temReg2,*temReg;		dotCount = 1 << power;// 计算快速沃尔什变换点数		temReg1 = new double[dotCount];// 分配运算所需的数组temReg2 = new double[dotCount];memcpy(temReg1, pTd, sizeof(double) * dotCount);// 将时域点写入数组temReg1		for(k = 0; k < power; k++)// 蝶形运算{for(j = 0; j < 1<<k; j++){bfsize = 1 << (power-k);for(i = 0; i < bfsize / 2; i++){p = j * bfsize;temReg2[i + p] = temReg1[i + p] + temReg1[i + p + bfsize / 2];temReg2[i + p + bfsize / 2] = temReg1[i + p] - temReg1[i + p + bfsize / 2];}}				temReg = temReg1;// 互换temReg1和temReg2  temReg1 = temReg2;temReg2 = temReg;}	for(j = 0; j < dotCount; j++)// 调整系数{p = 0;for(i = 0; i < power; i++){if (j & (1<<i)){p += 1 << (power-i-1);}}pFd[j] = temReg1[p] / dotCount;}		delete temReg1;// 释放内存delete temReg2;
}/*************************************************************************
* 函数名称:Walsh_HarTran(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
* 函数参数:
*   LPSTR lpSrcStartBits,指向源DIB图像指针
*   long  lWidth,源DIB图像宽度
*   long  lHeight,源DIB图像高度
*   long lLineBytes,源DIB图像的行字节数,为4的倍数
* 函数类型:BOOL
* 函数功能:用来对图像进行沃尔什-哈达玛变换
************************************************************************/BOOL  Walsh_HarTran(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
{unsigned char*	lpSrcUnChr;	//指向像素的指针	long i;                 //行循环变量long j;                 //列循环变量		long	wid=1,hei=1;// 进行付立叶变换的宽度和高度,初始化为1double	dTemp;// 中间变量	int		widpor=0,heiPor=0;//2的幂数while(wid * 2 <= lWidth)// 计算进行离散余弦变换的宽度和高度(2的整数次方){wid *= 2;widpor++;}	while(hei * 2 <= lHeight){hei *= 2;heiPor++;}		double *pTd = new double[wid * hei];// 分配内存double *pFd = new double[wid * hei];		for(i = 0; i < hei; i++)// 行{for(j = 0; j < wid; j++)// 列{// 指向DIB第i行,第j个像素的指针lpSrcUnChr= (unsigned char*)lpSrcStartBits + lLineBytes * (lHeight- 1 - i) + j;						pTd[j + i * wid] = *(lpSrcUnChr);// 给时域赋值}}	for(i = 0; i < hei; i++){		Walshei_Har(pTd + wid * i, pFd + wid * i, widpor);// 对y方向进行沃尔什-哈达玛变换}		for(i = 0; i < hei; i++)// 保存计算结果{for(j = 0; j < wid; j++){pTd[j * hei + i] = pFd[j + wid * i];}}	for(j = 0; j < wid; j++){		Walshei_Har(pTd + j * hei, pFd+ j * hei, heiPor);// 对x方向进行沃尔什-哈达玛变换}		for(i = 0; i < hei; i++)// 行{		for(j = 0; j < wid; j++)// 列{			dTemp = fabs(pFd[j * hei + i] * 1000);// 计算频谱						if (dTemp > 255)// 对于超过255的,直接设置为255{dTemp = 255;}			// 指向DIB第i行,第j个像素的指针lpSrcUnChr= (unsigned char*)lpSrcStartBits + lLineBytes * (lHeight- 1 - i) + j;						* (lpSrcUnChr) = (BYTE)(dTemp);// 更新源图像}}		delete pTd;//释放内存delete pFd;return TRUE;
}/*************************************************************************
*
* 函数名称:
*   DisK_L(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
*函数参数:
*   LPSTR lpSrcStartBits,指向源DIB图像指针
*   long  lWidth,源DIB图像宽度
*   long  lHeight,源DIB图像高度
*   long lLineBytes,源DIB图像的行字节数,为4的倍数
* 函数类型:BOOL
* 函数功能:用来对图像进行旋转
************************************************************************/BOOL DisK_L(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
{unsigned char*	lpSrcUnChr;	//指向像素的指针	LONG	i,j,// 循环变量lMaxRange,// 经过变换后图像最大可能范围		AverEx,AverEy,//  目标坐标均值		ToaCount;//  目标总的像素数	double  Matr4C[2][2],// 坐标值的协方差矩阵QMatrix[2][2],// 存放协方差矩阵的特征向量		MainCross[2],HypoCross[2],//  三对角阵的主对角和次对角线元素		dTemp;// 临时变量LONG    lTempI,lTempJ;if(lWidth>lHeight)// 估计图像经过旋转后可能最大的宽度和高度{lMaxRange = lWidth;}else{lMaxRange =lHeight;}AverEx=0.0;// 初始化AverEy=0.0;ToaCount = 0;Matr4C[0][0] = Matr4C[0][1] = Matr4C[1][0] = Matr4C[1][1] = 0.0;double *F = new double[lWidth*lHeight];// 分配内存		for(i = 0; i < lHeight; i++)// 行{		for(j = 0; j < lWidth; j++)// 列{			F[i*lWidth + j] = 255;// 给旋转后坐标轴的每个点赋零值// 指向位图i行j列像素的指针lpSrcUnChr= (unsigned char*)lpSrcStartBits + lLineBytes*i + j;// 值小于255(非背景色白色)的像素认为目标的一部分// 并将其坐标值x和y看作二维随机矢量if((*lpSrcUnChr) < 255){				AverEx=AverEx+i;// 属于目标像素的Y坐标和X坐标累计值AverEy=AverEy+j;				ToaCount++;// 目标总的像素数加一// 随机矢量协方差矩阵的累计值Matr4C[0][0] = Matr4C[0][0] + i*i;Matr4C[0][1] = Matr4C[0][1] + i*j;Matr4C[1][0] = Matr4C[1][0] + j*i;Matr4C[1][1] = Matr4C[1][1] + j*j;}}}AverEx = AverEx/ToaCount;// 计算随机矢量的均值AverEy = AverEy/ToaCount;Matr4C[0][0] = Matr4C[0][0]/ToaCount - AverEx*AverEx;//  计算随机矢量的协方差矩阵Matr4C[0][1] = Matr4C[0][1]/ToaCount - AverEx*AverEy;Matr4C[1][0] = Matr4C[1][0]/ToaCount - AverEx*AverEy;Matr4C[1][1] = Matr4C[1][1]/ToaCount - AverEy*AverEy;double Precision = 0.000001;// 规定迭代的计算精度ThreeCrossMat(*Matr4C, 2, *QMatrix, MainCross, HypoCross);// 将协方差矩阵化作三对角对称阵		EigenvalueVector(2, MainCross,HypoCross, *Matr4C, Precision, 50);// 求协方差矩阵的特征值和特征矢向量dTemp = Matr4C[0][1];// 将特征列向量转化称特征列向量Matr4C[0][1] = Matr4C[1][0];Matr4C[1][0] = dTemp;for(i=0;i<=1;i++){// 对特征列向量进行归一化dTemp = pow(Matr4C[i][0],2) + pow(Matr4C[i][1],2);dTemp = sqrt(dTemp);Matr4C[i][0] = Matr4C[i][0]/dTemp;Matr4C[i][1] = Matr4C[i][1]/dTemp;}	// 查找经离散K-L变换后的坐标点在原坐标系中的坐标    for(i = -lMaxRange+1; i < lMaxRange; i++){for(j = -lMaxRange+1; j < lMaxRange; j++){//  将新坐标值映射到旧的坐标系int Cx = (int)(i*Matr4C[0][0]-j*Matr4C[0][1])+AverEx;int Cy = (int)(-i*Matr4C[1][0]+j*Matr4C[1][1])+AverEy;//  映射值是否属于源图像if( Cx>=0 && Cx<lHeight && Cy>=0 && Cy<lWidth ){lpSrcUnChr= (unsigned char*)lpSrcStartBits + lLineBytes*Cx + Cy;// 映射值是否属于原来的目标if(*(lpSrcUnChr)<255){//  将新坐标系原点平移到中心,以便显示lTempI=(LONG)(lHeight/2)+j;lTempJ=(LONG)(lWidth/2)+i;// 看如果能够进行显示,赋值给数组,进行存储if( lTempI>=0 && lTempI<lHeight && lTempJ>=0 && lTempJ<lWidth )F[lTempJ+ (lTempI) * lWidth]=*(lpSrcUnChr);}}		}}for(i = 0; i < lMaxRange; i++)// 行{		for(j = 0; j < lMaxRange; j++)// 列{			dTemp = F[i * lMaxRange + j] ;// 离散K-L变换后的像素值			// 指向位图i行j列像素的指针lpSrcUnChr= (unsigned char*)lpSrcStartBits + lLineBytes * (lHeight - 1 - i) + j;						* (lpSrcUnChr) = (BYTE)(dTemp);// 更新源图像}}		delete F;// 释放内存	return TRUE;// 返回
}/*************************************************************************
*
* \函数名称:
*   FFT_1D()
*
* \输入参数:
*   complex<double> * pCTData	- 指向时域数据的指针,输入的需要变换的数据
*   complex<double> * pCFData	- 指向频域数据的指针,输出的经过变换的数据
*   nLevel						-傅立叶变换蝶形算法的级数,2的幂数,
*
* \返回值:
*   无
*
* \说明:
*   一维快速傅立叶变换。
*
*************************************************************************
*/
void FFT_1D(complex<double> * pCTData, complex<double> * pCFData, int nLevel)
{// 循环控制变量int		i;int     j;int     k;// 傅立叶变换点数int	nCount =0 ;// 计算傅立叶变换点数nCount =(int)pow((double)2,(double)nLevel) ;// 某一级的长度int		nBtFlyLen;nBtFlyLen = 0 ;// 变换系数的角度 =2 * PI * i / nCountdouble	dAngle;complex<double> *pCW ;// 分配内存,存储傅立叶变化需要的系数表pCW  = new complex<double>[nCount / 2];// 计算傅立叶变换的系数for(i = 0; i < nCount / 2; i++){dAngle = -2 * PI * i / nCount;pCW[i] = complex<double> ( cos(dAngle), sin(dAngle) );}// 变换需要的工作空间complex<double> *pCWork1,*pCWork2; // 分配工作空间pCWork1 = new complex<double>[nCount];pCWork2 = new complex<double>[nCount];// 临时变量complex<double> *pCTmp;// 初始化,写入数据memcpy(pCWork1, pCTData, sizeof(complex<double>) * nCount);// 临时变量int nInter; nInter = 0;// 蝶形算法进行快速傅立叶变换for(k = 0; k < nLevel; k++){for(j = 0; j < (int)pow((double)2,(double)k); j++){//计算长度nBtFlyLen = (int)pow( (double)2,(double)(nLevel-k) );//倒序重排,加权计算for(i = 0; i < nBtFlyLen/2; i++){nInter = j * nBtFlyLen;pCWork2[i + nInter] = pCWork1[i + nInter] + pCWork1[i + nInter + nBtFlyLen / 2];pCWork2[i + nInter + nBtFlyLen / 2] =(pCWork1[i + nInter] - pCWork1[i + nInter + nBtFlyLen / 2]) * pCW[(int)(i * pow((double)2,(double)k))];}}// 交换 pCWork1和pCWork2的数据pCTmp   = pCWork1	;pCWork1 = pCWork2	;pCWork2 = pCTmp		;}// 重新排序for(j = 0; j < nCount; j++){nInter = 0;for(i = 0; i < nLevel; i++){if ( j&(1<<i) ){nInter += 1<<(nLevel-i-1);}}pCFData[j]=pCWork1[nInter];}// 释放内存空间delete pCW;delete pCWork1;delete pCWork2;pCW		=	NULL	;pCWork1 =	NULL	;pCWork2 =	NULL	;}
/*************************************************************************
*
* \函数名称:
*    IFFT_1D()
*
* \输入参数:
*   complex<double> * pCTData	- 指向时域数据的指针,输入的需要反变换的数据
*   complex<double> * pCFData	- 指向频域数据的指针,输出的经过反变换的数据
*   nLevel						-傅立叶变换蝶形算法的级数,2的幂数,
*
* \返回值:
*   无
*
* \说明:
*   一维快速傅立叶反变换。
*
************************************************************************
*/
void IFFT_1D(complex<double> * pCFData, complex<double> * pCTData, int nLevel)
{// 循环控制变量int		i;// 傅立叶反变换点数int nCount;// 计算傅立叶变换点数nCount = (int)pow((double)2,(double)nLevel) ;// 变换需要的工作空间complex<double> *pCWork;	// 分配工作空间pCWork = new complex<double>[nCount];// 将需要反变换的数据写入工作空间pCWorkmemcpy(pCWork, pCFData, sizeof(complex<double>) * nCount);// 为了利用傅立叶正变换,可以把傅立叶频域的数据取共轭// 然后直接利用正变换,输出结果就是傅立叶反变换结果的共轭for(i = 0; i < nCount; i++){pCWork[i] = complex<double> (pCWork[i].real(), -pCWork[i].imag());}// 调用快速傅立叶变换实现反变换,结果存储在pCTData中FFT_1D(pCWork, pCTData, nLevel);// 求时域点的共轭,求得最终结果// 根据傅立叶变换原理,利用这样的方法求得的结果和实际的时域数据// 相差一个系数nCountfor(i = 0; i < nCount; i++){pCTData[i] = complex<double> (pCTData[i].real() / nCount, -pCTData[i].imag() / nCount);}// 释放内存delete pCWork;pCWork = NULL;
}/*************************************************************************
*
* \函数名称:
*   FFT_2D()
*
* \输入参数:
*   complex<double> * pCTData	- 图像数据
*   int    nWidth				- 数据宽度
*   int    nHeight				- 数据高度
*   complex<double> * pCFData	- 傅立叶变换后的结果
*
* \返回值:
*   无
*
* \说明:
*   二维傅立叶变换。
*
************************************************************************
*/
void FFT_2D(complex<double> * pCTData, int nWidth, int nHeight, complex<double> * pCFData)
{// 循环控制变量int	x;int	y;// 临时变量double	dTmpOne;double  dTmpTwo;// 进行傅立叶变换的宽度和高度,(2的整数次幂)// 图像的宽度和高度不一定为2的整数次幂int		nTransWidth;int 	nTransHeight;// 计算进行傅立叶变换的宽度	(2的整数次幂)dTmpOne = log((double)nWidth)/log((double)2);dTmpTwo = ceil(dTmpOne)		   ;dTmpTwo = pow(2,dTmpTwo)	   ;nTransWidth = (int) dTmpTwo	   ;// 计算进行傅立叶变换的高度 (2的整数次幂)dTmpOne = log((double)nHeight)/log((double)2);dTmpTwo = ceil(dTmpOne)		   ;dTmpTwo = pow(2,dTmpTwo)	   ;nTransHeight = (int) dTmpTwo	   ;	// x,y(行列)方向上的迭代次数int		nXLev;int		nYLev;// 计算x,y(行列)方向上的迭代次数nXLev = (int) ( log((double)nTransWidth)/log((double)2) +  0.5 );nYLev = (int) ( log((double)nTransHeight)/log((double)2) + 0.5 );for(y = 0; y < nTransHeight; y++){// x方向进行快速傅立叶变换FFT_1D(&pCTData[nTransWidth * y], &pCFData[nTransWidth * y], nXLev);}// pCFData中目前存储了pCTData经过行变换的结果// 为了直接利用FFT_1D,需要把pCFData的二维数据转置,再一次利用FFT_1D进行// 傅立叶行变换(实际上相当于对列进行傅立叶变换)for(y = 0; y < nTransHeight; y++){for(x = 0; x < nTransWidth; x++){pCTData[nTransHeight * x + y] = pCFData[nTransWidth * y + x];}}for(x = 0; x < nTransWidth; x++){// 对x方向进行快速傅立叶变换,实际上相当于对原来的图像数据进行列方向的// 傅立叶变换FFT_1D(&pCTData[x * nTransHeight], &pCFData[x * nTransHeight], nYLev);}// pCFData中目前存储了pCTData经过二维傅立叶变换的结果,但是为了方便列方向// 的傅立叶变换,对其进行了转置,现在把结果转置回来for(y = 0; y < nTransHeight; y++){for(x = 0; x < nTransWidth; x++){pCTData[nTransWidth * y + x] = pCFData[nTransHeight * x + y];}}memcpy(pCTData, pCFData, sizeof(complex<double>) * nTransHeight * nTransWidth );
}/*************************************************************************
*
* \函数名称:
*   IFFT_2D()
*
* \输入参数:
*   complex<double> * pCFData	- 频域数据
*   complex<double> * pCTData	- 时域数据
*   int    nWidth				- 图像数据宽度
*   int    nHeight				- 图像数据高度
*
* \返回值:
*   无
*
* \说明:
*   二维傅立叶反变换。
*
************************************************************************
*/
void IFFT_2D(complex<double> * pCFData, complex<double> * pCTData, int nWidth, int nHeight)
{// 循环控制变量int	x;int	y;// 临时变量double	dTmpOne;double  dTmpTwo;// 进行傅立叶变换的宽度和高度,(2的整数次幂)// 图像的宽度和高度不一定为2的整数次幂int		nTransWidth;int 	nTransHeight;// 计算进行傅立叶变换的宽度	(2的整数次幂)dTmpOne = log((double)nWidth)/log((double)2);dTmpTwo = ceil(dTmpOne)		   ;dTmpTwo = pow(2,dTmpTwo)	   ;nTransWidth = (int) dTmpTwo	   ;// 计算进行傅立叶变换的高度 (2的整数次幂)dTmpOne = log((double)nHeight)/log((double)2);dTmpTwo = ceil(dTmpOne)		   ;dTmpTwo = pow((double)2,dTmpTwo)	   ;nTransHeight = (int) dTmpTwo	   ;// 分配工作需要的内存空间complex<double> *pCWork= new complex<double>[nTransWidth * nTransHeight];//临时变量complex<double> *pCTmp ;// 为了利用傅立叶正变换,可以把傅立叶频域的数据取共轭// 然后直接利用正变换,输出结果就是傅立叶反变换结果的共轭for(y = 0; y < nTransHeight; y++){for(x = 0; x < nTransWidth; x++){pCTmp = &pCFData[nTransWidth * y + x] ;pCWork[nTransWidth * y + x] = complex<double>( pCTmp->real() , -pCTmp->imag() );}}// 调用傅立叶正变换FFT_2D(pCWork, nWidth, nHeight, pCTData) ;// 求时域点的共轭,求得最终结果// 根据傅立叶变换原理,利用这样的方法求得的结果和实际的时域数据// 相差一个系数for(y = 0; y < nTransHeight; y++){for(x = 0; x < nTransWidth; x++){pCTmp = &pCTData[nTransWidth * y + x] ;pCTData[nTransWidth * y + x] = complex<double>( pCTmp->real()/(nTransWidth*nTransHeight),-pCTmp->imag()/(nTransWidth*nTransHeight) );}}delete pCWork ;pCWork = NULL ;
}/
const double hCoef[10][20] =
{{ .707106781187,  .707106781187},{ .482962913145,  .836516303738,  .224143868042, -.129409522551 },{ .332670552950,  .806891509311,  .459877502118, -.135011020010, -.085441273882,  .035226291882 },{ .230377813309,  .714846570553,  .630880767930, -.027983769417,-.187034811719,  .030841381836,  .032883011667, -.010597401785 },{ .160102397974,  .603829269797,  .724308528438,  .138428145901, -.242294887066,-.032244869585,  .077571493840, -.006241490213, -.012580751999,  .003335725285 },{ .111540743350,  .494623890398,  .751133908021,  .315250351709, -.226264693965,-.129766867567,  .097501605587,  .027522865530, -.031582039318,  .000553842201,.004777257511, -.001077301085 },{ .077852054085,  .396539319482,  .729132090846,  .469782287405, -.143906003929,-.224036184994,  .071309219267,  .080612609151, -.038029936935, -.016574541631,.012550998556,  .000429577973, -.001801640704,  .000353713800 },{ .054415842243,  .312871590914,  .675630736297,  .585354683654, -.015829105256,-.284015542962,  .000472484574,  .128747426620, -.017369301002, -.044088253931,.013981027917,  .008746094047, -.004870352993, -.000391740373,  .000675449406,-.000117476784 },{ .038077947364,  .243834674613,  .604823123690,  .657288078051,  .133197385825,-.293273783279, -.096840783223,  .148540749338,  .030725681479, -.067632829061,.000250947115,  .022361662124, -.004723204758, -.004281503682,  .001847646883,.000230385764, -.000251963189,  .000039347320 },{ .026670057901,  .188176800078,  .527201188932,  .688459039454,  .281172343661,-.249846424327, -.195946274377,  .127369340336,  .093057364604, -.071394147166,-.029457536822,  .033212674059,  .003606553567, -.010733175483,  .001395351747,.001992405295, -.000685856695, -.000116466855,  .000093588670, -.000013264203 }
};
/*************************************************************************
*
* \函数名称:
*   DWTStep_1D()
*
* \输入参数:
*   double * pDbSrc		- 指向源数据的指针
*   int nCurLevel		- 当前分界的层数
*   int nInv			- 是否为DWT,1表示为IDWT,0表示DWT
*   int nStep			- 当前的计算层数
*   int nSupp			- 小波基的紧支集的长度
*
* \返回值:
*   BOOL			- 成功则返回TRUE,否则返回FALSE
*
* \说明:
*   该函数用对存放在pDBSrc中的数据进行一层的一维DWT或者IDWT。其中,nInv为表示进行
*   DWT或者IDWT的标志。nCurLevel为当前需要进行分界的层数。nStep为已经分界的层数
*   计算后数据仍存放在pDbSrc中
*
*************************************************************************
*/
BOOL DWTStep_1D(double* pDbSrc, int nCurLevel,int nInv, int nStep,int nSupp)
{double s = sqrt((double)2);// 获得小波基的指针double* h = (double*)hCoef[nSupp-1];// 确认当前层数有效ASSERT(nCurLevel>=0);// 计算当前层数的长度int CurN = 1<<nCurLevel;if (nInv) CurN <<= 1;// 确认所选择的小波基和当前层数的长度有效if (nSupp<1 || nSupp>10 || CurN<2*nSupp) return FALSE;// 分配临时内存用于存放结果double *ptemp = new double[CurN];if (!ptemp) return FALSE;double	s1, s2;int	Index1, Index2;// 判断是进行DWT还是IDWTif (!nInv){	// DWTIndex1=0;Index2=2*nSupp-1;// 进行卷积,其中s1为低频部分,s2为高频部分的结果for (int i=0; i<CurN/2; i++){	s1 = s2 = 0;double t = -1;for (int j=0; j<2*nSupp; j++, t=-t){s1 += h[j]*pDbSrc[(Index1 & CurN-1) * nStep];s2 += t*h[j]*pDbSrc[(Index2 & CurN-1) * nStep];Index1++;Index2--;}// 将结果存放在临时内存中ptemp[i] = s1/s;ptemp[i+CurN/2] = s2/s;Index1 -= 2*nSupp;Index2 += 2*nSupp;Index1 += 2;Index2 += 2;}}// 否则进行IDWTelse{	// IDWTIndex1 = CurN/2;Index2 = CurN/2-nSupp+1;// 进行卷积,其中其中s1为低频部分,s2为高频部分的结果for (int i=0; i<CurN/2; i++){s1 = s2 = 0;int Index3 = 0;for (int j=0; j<nSupp; j++){s1 += h[Index3]*pDbSrc[(Index1 & CurN/2-1) * nStep]+h[Index3+1]*pDbSrc[((Index2 & CurN/2-1) + CurN/2) * nStep];s2 += h[Index3+1]*pDbSrc[(Index1 & CurN/2-1) * nStep]-h[Index3]*pDbSrc[((Index2 & CurN/2-1) + CurN/2) * nStep];Index3+=2;Index1--,		Index2++;}// 将结果存入临时内存ptemp[2*i] = s1*s;ptemp[2*i+1] = s2*s;Index1 += nSupp;Index2 -= nSupp;Index1++;Index2++;}}// 将结果存入源图像中for (int i=0; i<CurN; i++)pDbSrc[i*nStep] = ptemp[i];// 释放临时内存,并返回delete[] ptemp;return TRUE;
}/*************************************************************************
*
* \函数名称:
*   DWTStep_2D()
*
* \输入参数:
*   double * pDbSrc		- 指向源数据的指针
*   int nCurWLevel		- X方向上当前分解的层数
*   int nCurHLevel		- Y方向上当前分解的层数
*   int nMaxWLevel		- X方向上最大可分解的层数
*   int nMaxHLevel		- Y方向上最大可分解的层数
*   int nInv			- 是否为DWT,1表示为IDWT,0表示DWT
*   int nStep			- 当前的计算层数
*   int nSupp			- 小波基的紧支集的长度
*
* \返回值:
*   BOOL			- 成功则返回TRUE,否则返回FALSE
*
* \说明:
*   该函数用对存放在pDBSrc中的数据进行一层的二维DWT或者IDWT。
*   计算后数据仍存放在pDbSrc中
*
*************************************************************************
*/
BOOL DWTStep_2D(double* pDbSrc, int nCurWLevel, int nCurHLevel,int nMaxWLevel, int nMaxHLevel, int nInv, int nStep, int nSupp)
{// 计算图像的长度和宽度(2次幂对齐)int W = 1<<nMaxWLevel, H = 1<<nMaxHLevel;// 计算当前分解的图像的长度和宽度int CurW = 1<<nCurWLevel, CurH = 1<<nCurHLevel;// 判断是进行DWT还是IDWTif (!nInv){	int i = 0;// 对行进行一维DWTfor (i=0; i<CurH; i++)if (!DWTStep_1D(pDbSrc+(int)i*W*nStep, nCurWLevel, nInv, nStep, nSupp)) return FALSE;// 对列进行一维DWTfor (i=0; i<CurW; i++)if (!DWTStep_1D(pDbSrc+i*nStep, nCurHLevel, nInv, W*nStep, nSupp)) return FALSE;}// 否则进行IDWTelse{// 计算当前变换的图像的长度和宽度CurW <<= 1;CurH <<= 1;int i = 0;// 对列进行IDWTfor (i=0; i<CurW; i++)if (!DWTStep_1D(pDbSrc+i*nStep, nCurHLevel, nInv, W*nStep, nSupp)) return FALSE;// 对行进行IDWTfor (i=0; i<CurH; i++)if (!DWTStep_1D(pDbSrc+(int)i*W*nStep, nCurWLevel, nInv, nStep, nSupp)) return FALSE;}// 返回return TRUE;
}/*************************************************************************
*
* \函数名称:
*   FloatToByte()
*
* \输入参数:
*   double  f			- 输入双精度变量
*
* \返回值:
*   BYTE			- 返回比特型变量
*
* \说明:
*   该函数将输入的双精度变量转换为BYTE型的变量
*
*************************************************************************
*/
BYTE FloatToByte(double f)
{if (f<=0) return (BYTE)0;else if (f>=255) return (BYTE)255;else return (BYTE)(f+0.5);
}/*************************************************************************
*
* \函数名称:
*   FloatToChar()
*
* \输入参数:
*   double  f			- 输入双精度变量
*
* \返回值:
*   Char			- 返回字符变量
*
* \说明:
*   该函数将输入的双精度变量转换为Char型的变量
*
*************************************************************************
*/
char FloatToChar(double f)
{if (f>=0)if (f>=127.0)return (char)127;else return (char)(f+0.5);elseif (f<=-128)return (char)-128;else return -(char)(-f+0.5);
}/*************************************************************************
*
* \函数名称:
*   Log2()
*
* \输入参数:
*   int  n			- 输入整型变量
*
* \返回值:
*   int			- 返回输入参数的对数
*
* \说明:
*   该函数求取输入参数的以2为底的对数,并转换为整型输出。
*
*************************************************************************
*/
int Log2(int n)
{int rsl = 0;while (n >>= 1) rsl++;return rsl;
}BOOL DIBDWTStep(LPSTR lpDIBBits,double*m_pDbImage, int nWidth,int nHeight, int nInv,int m_nDWTCurDepth,int m_nSupp)
{// 循环变量int i, j;// 获取变换的最大层数int nMaxWLevel = Log2(nWidth);int nMaxHLevel = Log2(nHeight);int nMaxLevel;if (nWidth == 1<<nMaxWLevel && nHeight == 1<<nMaxHLevel)nMaxLevel = min(nMaxWLevel, nMaxHLevel);// 临时变量double	*pDbTemp;BYTE	*pBits;// 如果小波变换的存储内存还没有分配,则分配此内存if(!m_pDbImage){			m_pDbImage = new double[nWidth*nHeight];if (!m_pDbImage)	return FALSE;// 将图像数据放入m_pDbImage中 for (j=0; j<nHeight; j++){pDbTemp = m_pDbImage + j*nWidth;pBits = (unsigned char *)lpDIBBits + (nHeight-1-j)*nWidth;		for (i=0; i<nWidth; i++)pDbTemp[i] = pBits[i];}}// 进行小波变换(或反变换)if (!DWTStep_2D(m_pDbImage, nMaxWLevel-m_nDWTCurDepth, nMaxHLevel-m_nDWTCurDepth,nMaxWLevel, nMaxHLevel, nInv, 1, m_nSupp))return FALSE;// 如果是反变换,则当前层数减1if (nInv)m_nDWTCurDepth --;// 否则加1elsem_nDWTCurDepth ++;// 然后,将数据拷贝回原CDib中,并进行相应的数据转换int lfw = nWidth>>m_nDWTCurDepth, lfh = nHeight>>m_nDWTCurDepth;for (j=0; j<nHeight; j++){pDbTemp = m_pDbImage + j*nWidth;pBits = (unsigned char *)lpDIBBits + (nHeight-1-j)*nWidth;for (i=0; i<nWidth; i++){if (j<lfh && i<lfw)pBits[i] = FloatToByte(pDbTemp[i]);elsepBits[i] = BYTE(FloatToChar(pDbTemp[i]) ^ 0x80);			}}// 返回return TRUE;
}/*************************************************************************
* 函数名称:
*   Interpolation()
* 参数:
*   LPSTR lpDIBBits    - 指向源DIB图像指针
*   LONG  lWidth       - 源图像宽度(像素数)
*   LONG  lHeight      - 源图像高度(像素数)
*   FLOAT x			- 插值元素的x坐标
*   FLOAT y		    - 插值元素的y坐标
* 返回值:
*   unsigned char      - 返回插值计算结果。
* 说明:
*   该函数利用双线性插值算法来估算像素值。对于超出图像范围的像素,
* 直接返回255。
************************************************************************/
unsigned char Interpolation (LPSTR lpDIBBits, LONG lWidth, LONG lHeight, FLOAT x, FLOAT y)
{// 四个最临近像素的坐标(i1, j1), (i2, j1), (i1, j2), (i2, j2)LONG	i1, i2;LONG	j1, j2;unsigned char	f1, f2, f3, f4;	// 四个最临近像素值	unsigned char	f12, f34;		// 二个插值中间值	// 定义一个值,当像素坐标相差小于改值时认为坐标相同FLOAT			EXP;	LONG lLineBytes;				// 图像每行的字节数lLineBytes = WIDTHBYTES(lWidth * 8);EXP = (FLOAT) 0.0001;// 计算四个最临近像素的坐标i1 = (LONG) x;i2 = i1 + 1;j1 = (LONG) y;j2 = j1 + 1;// 根据不同情况分别处理if( (x < 0) || (x > lWidth - 1) || (y < 0) || (y > lHeight - 1)){		return 255;		// 要计算的点不在源图范围内,直接返回255。}else{if (fabs(x - lWidth + 1) <= EXP){// 要计算的点在图像右边缘上if (fabs(y - lHeight + 1) <= EXP){// 要计算的点正好是图像最右下角那一个像素,直接返回该点像素值f1 = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i1);return f1;}else{// 在图像右边缘上且不是最后一点,直接一次插值即可f1 = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i1);f3 = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i2);// 返回插值结果return ((unsigned char) (f1 + (y -j1) * (f3 - f1)));}}else if (fabs(y - lHeight + 1) <= EXP){// 要计算的点在图像下边缘上且不是最后一点,直接一次插值即可f1 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i1);f2 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i1);// 返回插值结果return ((unsigned char) (f1 + (x -i1) * (f2 - f1)));}else{// 计算四个最临近像素值f1 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i1);f2 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i1);f3 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j1) + i2);f4 = *((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - j2) + i2);// 插值1f12 = (unsigned char) (f1 + (x - i1) * (f2 - f1));			// 插值2f34 = (unsigned char) (f3 + (x - i1) * (f4 - f3));			// 插值3return ((unsigned char) (f12 + (y -j1) * (f34 - f12)));}}
}	//*************************************************************************
* 函数名称:
*   RotateDIB2()
* 参数:
*   LPSTR lpDIB		- 指向源DIB的指针
*   int iRotateAngle	- 旋转的角度(0-360度)
* 返回值:
*   HGLOBAL            - 旋转成功返回新DIB句柄,否则返回NULL。
* 说明:
*   该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。
* 调用该函数会自动扩大图像以显示所有的像素。函数中采用双线性插
* 值算法进行插值。
************************************************************************/
HGLOBAL RotateDIB2(LPSTR lpSrcDib, float fRotateAngle,LPSTR lpSrcStartBits,long lWidth, long lHeight,WORD palSize)
{	//LONG	lWidth;				// 源图像的宽度//LONG	lHeight;			// 源图像的高度	LONG	lNewWidth;			// 旋转后图像的宽度LONG	lNewHeight;			// 旋转后图像的高度LONG	lNewLineBytes;		// 旋转后图像的宽度(lNewWidth',必须是4的倍数)	LPSTR	lpDIBBits;			// 指向源图像的指针	HGLOBAL	hDIB;				// 旋转后新DIB句柄	LPSTR	lpDst;				// 指向旋转图像对应像素的指针	LPSTR	lpNewDIB;			// 指向旋转图像的指针LPSTR	lpNewDIBBits;	LPBITMAPINFOHEADER lpbmi;	// 指向BITMAPINFO结构的指针(Win3.0)	LPBITMAPCOREHEADER lpbmc;	// 指向BITMAPCOREINFO结构的指针LONG	i;					// 循环变量(像素在新DIB中的坐标)LONG	j;	FLOAT	i0;					// 像素在源DIB中的坐标FLOAT	j0;	//float	fRotateAngle;		// 旋转角度(弧度)	float	fSina, fCosa;		// 旋转角度的正弦和余弦	// 源图四个角的坐标(以图像中心为坐标系原点)float	fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;	// 旋转后四个角的坐标(以图像中心为坐标系原点)float	fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;float	f1,f2;lpDIBBits = lpSrcStartBits;		// 找到源DIB图像像素起始位置	//lWidth = DIBWidth(lpDIB);			// 获取图像的宽度//lHeight = DIBHeight(lpDIB);			// 获取图像的高度// 将旋转角度从度转换到弧度//float fRotateAngle = (float) AngleToRadian(RotPara.m_rotAngle);fSina = (float) sin((double)fRotateAngle);	// 计算旋转角度的正弦fCosa = (float) cos((double)fRotateAngle);	// 计算旋转角度的余弦// 计算原图的四个角的坐标(以图像中心为坐标系原点)fSrcX1 = (float) (- (lWidth  - 1) / 2);fSrcY1 = (float) (  (lHeight - 1) / 2);fSrcX2 = (float) (  (lWidth  - 1) / 2);fSrcY2 = (float) (  (lHeight - 1) / 2);fSrcX3 = (float) (- (lWidth  - 1) / 2);fSrcY3 = (float) (- (lHeight - 1) / 2);fSrcX4 = (float) (  (lWidth  - 1) / 2);fSrcY4 = (float) (- (lHeight - 1) / 2);// 计算新图四个角的坐标(以图像中心为坐标系原点)fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1;fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2;fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3;fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4;fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;// 计算旋转后的图像实际宽度lNewWidth  = (LONG)(max(fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2)) + 0.5);lNewLineBytes = WIDTHBYTES(lNewWidth * 8);// 计算旋转后的图像高度lNewHeight = (LONG)(max(fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2)) + 0.5);f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina+ 0.5 * (lWidth  - 1));f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa+ 0.5 * (lHeight - 1));// 分配内存,以保存新DIBhDIB = (HGLOBAL) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + *(LPDWORD)lpSrcDib + palSize);	if (hDIB == NULL){return NULL;}lpNewDIB =  (char * )::GlobalLock((HGLOBAL) hDIB);// 复制DIB信息头和调色板memcpy(lpNewDIB, lpSrcDib, *(LPDWORD)lpSrcDib + palSize);// 找到新DIB像素起始位置lpNewDIBBits = lpNewDIB+ *(LPDWORD)lpNewDIB +palSize;;//FindDIBBits(lpNewDIB);lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;/*// 更新DIB中图像的高度和宽度if (IS_WIN30_DIB(lpNewDIB)){// 对于Windows 3.0 DIBlpbmi->biWidth = lNewWidth;lpbmi->biHeight = lNewHeight;}else{// 对于其它格式的DIBlpbmc->bcWidth = (unsigned short) lNewWidth;lpbmc->bcHeight = (unsigned short) lNewHeight;}*/lpbmi->biWidth = lNewWidth;lpbmi->biHeight = lNewHeight;for(i = 0; i < lNewHeight; i++)		// 针对图像每行进行操作{			for(j = 0; j < lNewWidth; j++)	// 针对图像每列进行操作{// 指向新DIB第i行,第j个像素的指针// 注意此处宽度和高度是新DIB的宽度和高度lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;// 计算该像素在源DIB中的坐标i0 = -((float) j) * fSina + ((float) i) * fCosa + f2;j0 =  ((float) j) * fCosa + ((float) i) * fSina + f1;// 利用双线性插值算法来估算像素值*lpDst = Interpolation (lpDIBBits, lWidth, lHeight, j0, i0);			}		}return hDIB;
}#endif // !defined(AFX_FUNCTION_H__6E194843_FEB3_491F_8062_765AA3465CBC__INCLUDED_)

ColorEnhanceDib.h

//======================================================================
// 文件: ColorEnhanceDib.h
// 内容: 图像灰度的颜色增强-头文件
// 功能: (1)伪彩色增强
//        
// 
//======================================================================#pragma once#include "Dib.h"#include "afx.h"class CColorEnhanceDib
{
public:// 构造函数,初始化数据成员CColorEnhanceDib(CDib *pDib);// 析构函数	~CColorEnhanceDib(void);// 伪彩色增强void Pseudo_Color_Enhance( BYTE * bpColorsTable );private:// 数据成员,CDib对象的指针 CDib *m_pDib; };

ColorEnhanceDib.cpp

//======================================================================
// 文件: ColorEnhanceDib.cpp
// 内容: 图像灰度的颜色增强-源文件
// 功能: (1)伪彩色增强
//        
// 
//======================================================================
#include "StdAfx.h"
#include "ColorEnhanceDib.h"//=======================================================
// 函数功能: 构造函数,初始化数据成员
// 输入参数: 位图指针
// 返回值:   无
//=======================================================
CColorEnhanceDib::CColorEnhanceDib(CDib *pDib)
{m_pDib = pDib;
}//=======================================================
// 函数功能: 析构函数
// 输入参数: 无
// 返回值:   无
//=======================================================CColorEnhanceDib::~CColorEnhanceDib(void)
{}//=======================================================
// 函数功能: 伪彩色增强
// 输入参数: BYTE * bpColorsTable-指向要替换的伪彩色编码表
// 返回值:   无
//=======================================================void CColorEnhanceDib::Pseudo_Color_Enhance( BYTE * bpColorsTable )
{int i;					// 循环变量	DWORD wNumColors;		// 颜色表中的颜色数目LPRGBQUAD m_lpRgbQuad;wNumColors = m_pDib->GetNumOfColor();	// 获取原图像颜色表中的颜色数目m_lpRgbQuad= m_pDib->GetRgbQuad();      //获取元图像颜色表指针if (wNumColors == 256)				// 判断颜色数目是否是256色{		// 读取伪彩色编码,更新调色板for (i = 0; i < (int)wNumColors; i++){    // 更新调色板红色绿色蓝色分量(m_lpRgbQuad+i)->rgbBlue = bpColorsTable[i * 4];(m_lpRgbQuad+i)->rgbGreen = bpColorsTable[i * 4 + 1];(m_lpRgbQuad+i)->rgbRed = bpColorsTable[i * 4 + 2];				// 更新调色板保留位(m_lpRgbQuad+i)->rgbReserved = 0; 			}}}

Dib.h

//======================================================================
// 文件: Dib.h
// 内容: 设备无关位图类-头文件
// 功能: (1)位图的加载与保存;
//        (2)位图信息的获取;
//        (3)位图数据的获取;
//        (3)位图的显示;
//        (4)位图的转换;
//        (5)位图相关判断;
// 作者: 李平科
// 联系: lipingke@126.com
// 日期: 2009-7-26
//======================================================================#pragma once
//#define _CRT_SECURE_NO_WARNINGS
#include "afx.h"#define PalVersion   0x300                                 // 调色板版本class CDib : public CObject
{
public:// 构造函数,初始化数据成员CDib(void);// 析构函数,释放内存空间~CDib(void);// 从文件加载位图BOOL LoadFromFile(LPCTSTR lpszPath);// 将位图保存到文件BOOL SaveToFile(LPCTSTR lpszPath);// 获取位图文件名LPCTSTR GetFileName();// 获取位图宽度LONG GetWidth();// 获取位图高度LONG GetHeight();// 获取位图的宽度和高度CSize GetDimension();  // 获取位图大小DWORD GetSize();// 获取单个像素所占位数WORD GetBitCount();// 获取每行像素所占字节数UINT GetLineByte();// 获取位图颜色数DWORD GetNumOfColor();// 获取位图颜色表LPRGBQUAD GetRgbQuad();// 获取位图数据LPBYTE GetData();// 显示位图BOOL Draw(CDC *pDC, CPoint origin, CSize size);// 24位彩色位图转8位灰度位图BOOL RgbToGrade();// 8位灰度位图转24位彩色位图BOOL GradeToRgb();// 判断是否含有颜色表BOOL HasRgbQuad();// 判断是否是灰度图BOOL IsGrade();// 判断位图是否有效BOOL IsValid();  WORD   GetColorNum(LPSTR);                            //取得位图包含的颜色数目LPSTR  GetBits(LPSTR);                               //取得位图数据的入口地址DWORD  GetWidth(LPSTR);                              //取得位图的宽度WORD   GetPalSize(LPSTR);                            //取得调色板的大小DWORD  GetHeight(LPSTR);                             //取得位图的高度int     GetReqByteWidth(int);                     //转换后的字节数GetRequireByteWidthHGLOBAL   LoadFile(CFile&);                          //从文件中加载位图BITMAPFILEHEADER	bmfHeader;  //BITMAPFILEHEADER结构HGLOBAL				m_hDib;//DIB对象的句柄LPSTR				lpdib;      //指向DIB的指针LPBITMAPINFO        lpbminfo;	// 指向BITMAPINFO结构的指针LPBITMAPINFOHEADER  lpbmihrd;	//指向BITMAPINFOHEADER结构的指针//BITMAPFILEHEADER	bmfHeader;  //BITMAPFILEHEADER结构RGBQUAD*			lpRgbQuag;//指向颜色表的指针LPSTR				lpDIBBits;  // DIB像素指针BOOL   ConstructPalette(HGLOBAL, CPalette*);         //构造逻辑调色板protected:// 计算位图颜色表长度DWORD CalcRgbQuadLength();// 根据颜色表生成调色板BOOL MakePalette();// 清理空间void Empty(BOOL bFlag = TRUE);private:// 位图文件名char m_fileName[_MAX_PATH];// 位图文件头指针    LPBITMAPFILEHEADER m_lpBmpFileHeader; // 需要动态分配和释放 // 位图指针(包含除位图文件头的所有内容)LPBYTE m_lpDib;                       // 需要动态分配和释放// 位图信息指针LPBITMAPINFO m_lpBmpInfo;// 位图信息头指针LPBITMAPINFOHEADER m_lpBmpInfoHeader;  // 位图颜色表指针LPRGBQUAD m_lpRgbQuad; // 位图数据指针LPBYTE m_lpData; // 调色板句柄HPALETTE m_hPalette;// 是否有颜色表BOOL m_bHasRgbQuad;// 位图是否有效BOOL m_bValid;
};

 Dib.cpp

//======================================================================
// 文件: Dib.cpp
// 内容: 设备无关位图类-原文件
// 功能: (1)位图的加载与保存;
//        (2)位图信息的获取;
//        (3)位图数据的获取;
//        (3)位图的显示;
//        (4)位图的转换;
//        (5)位图相关判断;
// 作者: 李平科
// 联系: lipingke@126.com
// 日期: 2009-7-26
//======================================================================#include "StdAfx.h"
#include "Dib.h"//
#define DIB_MARKER   ((WORD) ('M' << 8) | 'B') // 用于判断位图的标志宏 
//
//=======================================================
// 函数功能: 构造函数,初始化数据成员
// 输入参数: 无
// 返回值:   无
//=======================================================
CDib::CDib(void)
{// 数据成员初始化strcpy(m_fileName, "");//https://blog.csdn.net/cyrilcloud/article/details/115337480//此处报错,在预处理其中添加_CRT_SECURE_NO_WARNINGS//strcpy_s(m_fileName, sizeof(""), "");m_lpBmpFileHeader = NULL;m_lpDib = NULL;   m_lpBmpInfo = NULL;m_lpBmpInfoHeader = NULL;m_lpRgbQuad = NULL;m_lpData = NULL;m_hPalette = NULL;m_bHasRgbQuad = FALSE;m_bValid = FALSE;
}//=======================================================
// 函数功能: 析构函数,释放内存空间
// 输入参数: 无
// 返回值:   无
//=======================================================
CDib::~CDib(void)
{// 清理空间Empty();
}//=======================================================
// 函数功能: 从文件加载位图
// 输入参数: LPCTSTR lpszPath-待加载位图文件路径
// 返回值:   BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::LoadFromFile(LPCTSTR lpszPath)
{// 记录位图文件名 路径-文件名strcpy(m_fileName, lpszPath);// 以读模式打开位图文件CFile dibFile;if(!dibFile.Open(m_fileName, CFile::modeRead | CFile::shareDenyWrite)){return FALSE;}// 清理空间Empty(); // 为位图文件头分配空间,并初始化为0m_lpBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];memset(m_lpBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); // 读取位图文件头int nCount = dibFile.Read((void *)m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER));if(nCount != sizeof(BITMAPFILEHEADER)) {return FALSE;} // 判断此文件是不是位图文件(“0x4d42”代表“BM”)if(m_lpBmpFileHeader->bfType == 0x4d42){// 是位图文件// 计算除位图文件头的空间大小,分配空间并初始化为0DWORD dwDibSize = dibFile.GetLength() - sizeof(BITMAPFILEHEADER);m_lpDib = new BYTE[dwDibSize];memset(m_lpDib, 0, dwDibSize);// 读取 除位图文件头的 所有数据dibFile.Read(m_lpDib, dwDibSize);// 关闭位图文件dibFile.Close();// 设置位图信息指针m_lpBmpInfo = (LPBITMAPINFO)m_lpDib;// 设置位图信息头指针m_lpBmpInfoHeader = (LPBITMAPINFOHEADER)m_lpDib;  //数组指针// 设置位图颜色表指针m_lpRgbQuad = (LPRGBQUAD)(m_lpDib + m_lpBmpInfoHeader->biSize); //数组指针+位图信息头40偏移量// 如果位图没有设置位图使用的颜色数,设置它if(m_lpBmpInfoHeader->biClrUsed == 0){m_lpBmpInfoHeader->biClrUsed = GetNumOfColor();}// 计算颜色表长度DWORD dwRgbQuadLength = CalcRgbQuadLength();// 设置位图数据指针m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + dwRgbQuadLength;// 判断是否有颜色表if(m_lpRgbQuad == (LPRGBQUAD)m_lpData)  //地址相等则表示 没有颜色表{m_lpRgbQuad = NULL;    // 将位图颜色表指针置空m_bHasRgbQuad = FALSE; // 无颜色表}else{m_bHasRgbQuad = TRUE;  // 有颜色表MakePalette();         // 根据颜色表生成调色板}        // 设置位图大小(因为很多位图文件都不设置此项)m_lpBmpInfoHeader->biSizeImage = GetSize();// 位图有效m_bValid = TRUE;return TRUE;}else{// 不是位图文件m_bValid = FALSE;return FALSE;}     }//=======================================================
// 函数功能: 将位图保存到文件
// 输入参数: LPCTSTR lpszPath-位图文件保存路径
// 返回值:   BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::SaveToFile(LPCTSTR lpszPath)
{// 以写模式打开文件CFile dibFile;if(!dibFile.Open(lpszPath, CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive)){return FALSE;}// 记录位图文件名strcpy(m_fileName, lpszPath);// 将文件头结构写进文件dibFile.Write(m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER));// 将文件信息头结构写进文件dibFile.Write(m_lpBmpInfoHeader, sizeof(BITMAPINFOHEADER));// 计算颜色表长度DWORD dwRgbQuadlength = CalcRgbQuadLength();// 如果有颜色表的话,将颜色表写进文件if(dwRgbQuadlength != 0){dibFile.Write(m_lpRgbQuad, dwRgbQuadlength);}                                                        // 将位图数据写进文件DWORD dwDataSize = GetLineByte() * GetHeight();dibFile.Write(m_lpData, dwDataSize);// 关闭文件dibFile.Close();return TRUE;
}//=======================================================
// 函数功能: 获取位图文件名
// 输入参数: 无
// 返回值:   LPCTSTR-位图文件名
//=======================================================
LPCTSTR CDib::GetFileName()
{return m_fileName;
}//=======================================================
// 函数功能: 获取位图宽度
// 输入参数: 无
// 返回值:   LONG-位图宽度
//=======================================================
LONG CDib::GetWidth()
{return m_lpBmpInfoHeader->biWidth;
}//=======================================================
// 函数功能: 获取位图高度
// 输入参数: 无
// 返回值:   LONG-位图高度
//=======================================================
LONG CDib::GetHeight()
{return m_lpBmpInfoHeader->biHeight;
}//=======================================================
// 函数功能: 获取位图的宽度和高度
// 输入参数: 无
// 返回值:   CSize-位图的宽度和高度
//=======================================================
CSize CDib::GetDimension()
{return CSize(GetWidth(), GetHeight());
}//=======================================================
// 函数功能: 获取位图大小
// 输入参数: 无
// 返回值:   DWORD-位图大小
//=======================================================
DWORD CDib::GetSize()
{if(m_lpBmpInfoHeader->biSizeImage != 0){return m_lpBmpInfoHeader->biSizeImage;}else{       return GetWidth() * GetHeight();}
}//=======================================================
// 函数功能: 获取单个像素所占位数
// 输入参数: 无
// 返回值:   WORD-单个像素所占位数
//=======================================================
WORD CDib::GetBitCount()
{return m_lpBmpInfoHeader->biBitCount;
}       //=======================================================
// 函数功能: 获取每行像素所占字节数
// 输入参数: 无
// 返回值:   UINT-每行像素所占字节数
//=======================================================
UINT CDib::GetLineByte()
{ return (GetWidth() * GetBitCount() / 8 + 3) / 4 * 4;;
}//=======================================================
// 函数功能: 获取位图颜色数
// 输入参数: 无
// 返回值:   DWORD-位图颜色数
//=======================================================
DWORD CDib::GetNumOfColor()
{UINT dwNumOfColor;     //biBitCount 每个像素位数 1-黑白图 4-16色 8-256色 24-真彩色//biClrUsed 位图使用的颜色数 if ((m_lpBmpInfoHeader->biClrUsed == 0) && (m_lpBmpInfoHeader->biBitCount < 9)){switch (m_lpBmpInfoHeader->biBitCount){case 1: dwNumOfColor = 2; break;case 4: dwNumOfColor = 16; break;case 8: dwNumOfColor = 256;}}else{dwNumOfColor = m_lpBmpInfoHeader->biClrUsed;}  		return dwNumOfColor; 
}//=======================================================
// 函数功能: 计算位图颜色表长度
// 输入参数: 无
// 返回值:   DWORD-位图颜色表长度
//=======================================================
DWORD CDib::CalcRgbQuadLength()
{DWORD dwNumOfColor = GetNumOfColor(); //位图使用的颜色数if(dwNumOfColor > 256){dwNumOfColor = 0;}return  dwNumOfColor * sizeof(RGBQUAD);
}//=======================================================
// 函数功能: 获取位图颜色表
// 输入参数: 无
// 返回值:   LPRGBQUAD-位图颜色表指针
//=======================================================
LPRGBQUAD CDib::GetRgbQuad()
{return m_lpRgbQuad;
}//=======================================================
// 函数功能: 获取位图数据
// 输入参数: 无
// 返回值:   LPBYTE-位图数据指针
//=======================================================
LPBYTE CDib::GetData()
{return m_lpData;
}//=======================================================
// 函数功能: 根据颜色表生成调色板
// 输入参数: 无
// 返回值:   BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::MakePalette()
{// 计算颜色表长度DWORD dwRgbQuadLength = CalcRgbQuadLength();// 如果颜色表长度为0,则不生成逻辑调色板if(dwRgbQuadLength == 0) {return FALSE;}//删除旧的调色板对象if(m_hPalette != NULL) {DeleteObject(m_hPalette);m_hPalette = NULL;}// 申请缓冲区,初始化为0DWORD dwNumOfColor = GetNumOfColor();DWORD dwSize = 2 * sizeof(WORD) + dwNumOfColor * sizeof(PALETTEENTRY);LPLOGPALETTE lpLogPalette = (LPLOGPALETTE) new BYTE[dwSize];memset(lpLogPalette, 0, dwSize);// 生成逻辑调色板lpLogPalette->palVersion = 0x300;lpLogPalette->palNumEntries = dwNumOfColor;LPRGBQUAD lpRgbQuad = (LPRGBQUAD) m_lpRgbQuad;for(int i = 0; i < dwNumOfColor; i++) {lpLogPalette->palPalEntry[i].peRed = lpRgbQuad->rgbRed;lpLogPalette->palPalEntry[i].peGreen = lpRgbQuad->rgbGreen;lpLogPalette->palPalEntry[i].peBlue = lpRgbQuad->rgbBlue;lpLogPalette->palPalEntry[i].peFlags = 0;lpRgbQuad++;}// 创建逻辑调色板m_hPalette = CreatePalette(lpLogPalette);// 释放缓冲区delete [] lpLogPalette;return TRUE;
}//=======================================================
// 函数功能: 显示位图
// 输入参数:
//            CDC *pDC-设备环境指针
//            CPoint origin-显示矩形区域的左上角
//            CSize size-显示矩形区域的尺寸
// 返回值:
//            BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::Draw(CDC *pDC, CPoint origin, CSize size)
{// 位图无效,无法绘制,返回错误if(!IsValid()){return FALSE;}// 旧的调色板句柄HPALETTE hOldPalette = NULL;// 如果位图指针为空,则返回FALSEif(m_lpDib == NULL) {return FALSE;}// 如果位图有调色板,则选进设备环境中if(m_hPalette != NULL) {hOldPalette = SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE);}// 设置位图伸缩模式pDC->SetStretchBltMode(COLORONCOLOR);//https://learn.microsoft.com/zh-CN/windows/win32/api/wingdi/nf-wingdi-setstretchbltmode// 将位图在pDC所指向的设备上进行显示StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy,0, 0, GetWidth(), GetHeight(), m_lpData, m_lpBmpInfo, DIB_RGB_COLORS, SRCCOPY);//https://learn.microsoft.com/zh-cn/windows/win32/api/wingdi/nf-wingdi-stretchdibits// 恢复旧的调色板if(hOldPalette != NULL){SelectPalette(pDC->GetSafeHdc(), hOldPalette, TRUE);}return TRUE;
}//=======================================================
// 函数功能: 24位彩色位图转8位灰度位图
// 输入参数: 无
// 返回值:   BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::RgbToGrade()
{// 位图无效,失败返回if(!IsValid()){return FALSE;}// 不是24位位图,失败返回if(GetBitCount() != 24){return FALSE;}// 是压缩位图,失败返回if(m_lpBmpInfoHeader->biCompression != BI_RGB){return FALSE;}// 如果不是灰度位图,才需要转换if(!IsGrade()){// 获取原位图信息LONG lHeight = GetHeight();LONG lWidth = GetWidth();UINT uLineByte = GetLineByte();// 计算灰度位图数据所需空间UINT uGradeBmpLineByte = (lWidth + 3) / 4 * 4;DWORD dwGradeBmpDataSize = uGradeBmpLineByte * lHeight; // 计算灰度位图所需空间DWORD dwGradeBmpSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256 + dwGradeBmpDataSize;// 设置灰度位图文件头LPBITMAPFILEHEADER lpGradeBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];memset(lpGradeBmpFileHeader, 0, sizeof(BITMAPFILEHEADER));lpGradeBmpFileHeader->bfType = 0x4d42;lpGradeBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwGradeBmpSize;lpGradeBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+ sizeof(RGBQUAD) * 256;lpGradeBmpFileHeader->bfReserved1 = 0;lpGradeBmpFileHeader->bfReserved2 = 0;            // 为灰度位图分配空间,并初始化为0LPBYTE lpGradeBmp = (LPBYTE)new BYTE[dwGradeBmpSize];memset(lpGradeBmp, 0, dwGradeBmpSize);// 设置灰度位图信息头LPBITMAPINFOHEADER lpGradeBmpInfoHeader = (LPBITMAPINFOHEADER)(lpGradeBmp);lpGradeBmpInfoHeader->biBitCount = 8;lpGradeBmpInfoHeader->biClrImportant = 0;lpGradeBmpInfoHeader->biClrUsed = 256;lpGradeBmpInfoHeader->biCompression = BI_RGB;lpGradeBmpInfoHeader->biHeight = lHeight;lpGradeBmpInfoHeader->biPlanes = 1;lpGradeBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER);lpGradeBmpInfoHeader->biSizeImage = dwGradeBmpDataSize;lpGradeBmpInfoHeader->biWidth = lWidth;lpGradeBmpInfoHeader->biXPelsPerMeter = m_lpBmpInfoHeader->biXPelsPerMeter;lpGradeBmpInfoHeader->biYPelsPerMeter = m_lpBmpInfoHeader->biYPelsPerMeter;// 设置灰度位图颜色表LPRGBQUAD lpGradeBmpRgbQuad = (LPRGBQUAD)(lpGradeBmp + sizeof(BITMAPINFOHEADER));// 初始化8位灰度图的调色板信息LPRGBQUAD lpRgbQuad;               for(int k = 0; k < 256; k++){lpRgbQuad = (LPRGBQUAD)(lpGradeBmpRgbQuad + k);lpRgbQuad->rgbBlue = k; lpRgbQuad->rgbGreen = k;lpRgbQuad->rgbRed = k;lpRgbQuad->rgbReserved = 0;}// 灰度位图数据处理BYTE r, g, b; LPBYTE lpGradeBmpData = (LPBYTE)(lpGradeBmp + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);// 进行颜色转换for(int i = 0; i < lHeight; i++){for(int j = 0; j < lWidth; j++){b = m_lpData[i * uLineByte + 3 * j];g = m_lpData[i * uLineByte + 3 * j + 1];r = m_lpData[i * uLineByte + 3 * j + 2];lpGradeBmpData[i * uGradeBmpLineByte + j] = (BYTE)(0.299 * r + 0.587 * g + 0.114 * b); }}// 释放原有位图空间Empty(FALSE);// 重新设定原位图指针指向m_lpBmpFileHeader = lpGradeBmpFileHeader;m_lpDib = lpGradeBmp;m_lpBmpInfo = (LPBITMAPINFO)(lpGradeBmp);m_lpBmpInfoHeader = lpGradeBmpInfoHeader;m_lpRgbQuad = lpGradeBmpRgbQuad;m_lpData = lpGradeBmpData;// 设置颜色表标志m_bHasRgbQuad = TRUE;  // 设置位图有效标志m_bValid = TRUE;// 生成调色板MakePalette();}return TRUE;   
}   //=======================================================
// 函数功能: 8位灰度位图转24位彩色位图
// 输入参数: 无
// 返回值:   BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::GradeToRgb()
{// 位图无效,失败退出if(!IsValid()){return FALSE;}// 不是8位位图,失败退出if(GetBitCount() != 8){return FALSE;}// 是压缩位图,失败返回if(m_lpBmpInfoHeader->biCompression != BI_RGB){return FALSE;}// 是灰度图时,才需转换if(IsGrade()){// 获取原位图信息LONG lHeight = GetHeight();LONG lWidth = GetWidth();UINT uLineByte = GetLineByte();// 计算彩色位图数据所需空间UINT uColorBmpLineByte = (lWidth * 24 / 8 + 3) / 4 * 4;DWORD dwColorBmpDataSize = uColorBmpLineByte * lHeight; // 计算彩色位图所需空间DWORD dwColorBmpSize = sizeof(BITMAPINFOHEADER) + dwColorBmpDataSize;// 设置彩色位图文件头LPBITMAPFILEHEADER lpColorBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];memset(lpColorBmpFileHeader, 0, sizeof(BITMAPFILEHEADER));lpColorBmpFileHeader->bfType = 0x4d42;lpColorBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwColorBmpSize;lpColorBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);lpColorBmpFileHeader->bfReserved1 = 0;lpColorBmpFileHeader->bfReserved2 = 0;    // 为彩色位图分配空间,并初始化为0LPBYTE lpColorBmp = (LPBYTE)new BYTE[dwColorBmpSize];memset(lpColorBmp, 0, dwColorBmpSize);// 设置彩色位图信息头LPBITMAPINFOHEADER lpColorBmpInfoHeader = (LPBITMAPINFOHEADER)(lpColorBmp);lpColorBmpInfoHeader->biBitCount = 24;lpColorBmpInfoHeader->biClrImportant = 0;lpColorBmpInfoHeader->biClrUsed = 0;lpColorBmpInfoHeader->biCompression = BI_RGB;lpColorBmpInfoHeader->biHeight = lHeight;lpColorBmpInfoHeader->biPlanes = 1;lpColorBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER);lpColorBmpInfoHeader->biSizeImage = dwColorBmpDataSize;lpColorBmpInfoHeader->biWidth = lWidth;lpColorBmpInfoHeader->biXPelsPerMeter = m_lpBmpInfoHeader->biXPelsPerMeter;lpColorBmpInfoHeader->biYPelsPerMeter = m_lpBmpInfoHeader->biYPelsPerMeter;// 彩色位图数据处理LPBYTE lpColorBmpData = (LPBYTE)(lpColorBmp + sizeof(BITMAPINFOHEADER));// 进行颜色转换for(int i = 0; i < lHeight; i++){for(int j = 0; j < lWidth; j++){BYTE btValue = m_lpData[i * uLineByte + j]; lpColorBmpData[i * uColorBmpLineByte + 3 * j] = btValue;lpColorBmpData[i * uColorBmpLineByte + 3 * j + 1] = btValue;lpColorBmpData[i * uColorBmpLineByte + 3 * j + 2] = btValue;  }}// 释放原有位图空间Empty(FALSE);// 重新设定原位图指针指向m_lpBmpFileHeader = lpColorBmpFileHeader;m_lpDib = lpColorBmp;m_lpBmpInfo = (LPBITMAPINFO)(lpColorBmp);m_lpBmpInfoHeader = lpColorBmpInfoHeader;m_lpRgbQuad = NULL;m_lpData = lpColorBmpData;// 设置颜色表标志m_bHasRgbQuad = FALSE;  // 设置位图有效标志m_bValid = TRUE;        }        return TRUE;   
}   //=======================================================
// 函数功能: 判断是否含有颜色表
// 输入参数: 无
// 返回值:   判断结果:TRUE-含有颜色表;FALSE-不含颜色表
//=======================================================
BOOL CDib::HasRgbQuad()
{return m_bHasRgbQuad;
}//=======================================================
// 函数功能: 判断是否是灰度图
// 输入参数: 无
// 返回值:   判断结果:TRUE-是灰度图;FALSE-是彩色图
//=======================================================
BOOL CDib::IsGrade()
{return (GetBitCount() < 9 && GetBitCount() > 0);
}//=======================================================
// 函数功能: 判断位图是否有效
// 输入参数: 无
// 返回值:   判断结果:TRUE-位图有效;FALSE-位图无效
//=======================================================
BOOL CDib::IsValid()
{return m_bValid;
}//=======================================================
// 函数功能: 清理空间
// 输入参数: BOOL bFlag-TRUE 全部清空;FALSE 部分清空
// 返回值:   无
//=======================================================
void CDib::Empty(BOOL bFlag)
{// 文件名清空if(bFlag){strcpy(m_fileName, "");}      // 释放位图文件头指针空间if(m_lpBmpFileHeader != NULL){delete [] m_lpBmpFileHeader;m_lpBmpFileHeader = NULL;}    // 释放位图指针空间if(m_lpDib != NULL){delete [] m_lpDib;m_lpDib = NULL;m_lpBmpInfo = NULL;m_lpBmpInfoHeader = NULL;m_lpRgbQuad = NULL;m_lpData = NULL;           }       // 释放调色板if(m_hPalette != NULL){DeleteObject(m_hPalette);m_hPalette = NULL;}    // 设置不含颜色表m_bHasRgbQuad = FALSE;// 设置位图无效m_bValid = FALSE;}  //新添加  是否存在重复
/*************************************************************************
* 函数名称:GetColorNum(LPSTR lpdib)
* 函数参数:
*   LPSTR lpdib,指向DIB对象的指针
* 函数类型:WORD
* 函数功能:该函数返回DIB中调色板的颜色的种数
************************************************************************/
WORD CDib::GetColorNum(LPSTR lpdib)
{long dwClrUsed = ((LPBITMAPINFOHEADER)lpdib)->biClrUsed;	// 读取dwClrUsed值	if (dwClrUsed != 0){return (WORD)dwClrUsed;// 如果dwClrUsed不为0,直接返回该值}WORD wBitCount = ((LPBITMAPINFOHEADER)lpdib)->biBitCount;// 读取biBitCount值		switch (wBitCount)// 按照像素的位数计算颜色数目{case 1:return 2;case 4:return 16;case 8:return 256;default:return 0;}
}=======================================================函数功能: 获取位图颜色数输入参数: 无返回值:   DWORD-位图颜色数
=======================================================
//DWORD CDib::GetNumOfColor()
//{
//	UINT dwNumOfColor;
//	//biBitCount 每个像素位数 1-黑白图 4-16色 8-256色 24-真彩色
//	//biClrUsed 位图使用的颜色数 
//	if ((m_lpBmpInfoHeader->biClrUsed == 0)
//		&& (m_lpBmpInfoHeader->biBitCount < 9))
//	{
//		switch (m_lpBmpInfoHeader->biBitCount)
//		{
//		case 1: dwNumOfColor = 2; break;
//		case 4: dwNumOfColor = 16; break;
//		case 8: dwNumOfColor = 256;
//		}
//	}
//	else
//	{
//		dwNumOfColor = m_lpBmpInfoHeader->biClrUsed;
//	}
//
//	return dwNumOfColor;
//}/*************************************************************************
* 函数名称:GetBits(LPSTR lpdib)
* 函数参数:
*   LPSTR lpdib,指向DIB对象的指针
* 函数类型:LPSTR
* 函数功能:计算DIB像素的起始位置,并返回指向它的指针
************************************************************************/LPSTR CDib::GetBits(LPSTR lpdib)
{return (lpdib + ((LPBITMAPINFOHEADER)lpdib)->biSize + GetPalSize(lpdib));//	return (lpdib + *(LPDWORD)lpdib+GetPalSize(lpdib));
}/*************************************************************************
* 函数名称:GetWidth(LPSTR lpdib)
* 函数参数:
*   LPSTR lpdib,指向DIB对象的指针
* 函数类型:DWORD
* 函数功能:该函数返回DIB中图像的宽度
************************************************************************/DWORD CDib::GetWidth(LPSTR lpdib)
{return ((LPBITMAPINFOHEADER)lpdib)->biWidth;//返回DIB宽度
}/*************************************************************************
* 函数名称:GetPalSize(LPSTR lpdib)
* 函数参数:
*   LPSTR lpdib,指向DIB对象的指针
* 函数类型:WORD
* 函数功能:该函数返回DIB中调色板的大小
************************************************************************/WORD CDib::GetPalSize(LPSTR lpdib)
{return (WORD)(GetColorNum(lpdib) * sizeof(RGBQUAD));// 计算DIB中调色板的大小
}/*************************************************************************
* 函数名称:GetHeight(LPSTR lpdib)
* 函数参数:
*   LPSTR lpdib ,指向DIB对象的指针
* 函数类型:DWORD
* 函数功能:该函数返回DIB中图像的高度
************************************************************************/DWORD CDib::GetHeight(LPSTR lpdib)
{return ((LPBITMAPINFOHEADER)lpdib)->biHeight;//返回DIB高度}/*************************************************************************
* 函数名称:GetReqByteWidth(int bits)
* 函数参数:
*   int bits,位数
* 函数类型:int
* 函数功能:获取需要的行字节数,应为4的倍数
*************************************************************************/
int  CDib::GetReqByteWidth(int bits)
{int getBytes = (bits + 31) / 32 * 4;return  getBytes;
}/*************************************************************************
* 函数名称:LoadFile(CFile& file)
* 函数参数:
*   CFile& file,要读取得文件文件CFile
* 函数类型:HGLOBAL
* 函数功能:将指定的文件中的DIB对象读到指定的内存区域中
*************************************************************************/HGLOBAL CDib::LoadFile(CFile& file)
{DWORD dwFileSize;dwFileSize = file.GetLength();// 获取文件大小	if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))// 读取DIB文件头{return NULL;// 大小不一致,返回NULL。}if (bmfHeader.bfType != DIB_MARKER)// 判断是否是DIB对象{return NULL;// 如果不是则返回NULL。}m_hDib = (HGLOBAL) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwFileSize - sizeof(BITMAPFILEHEADER));// 分配DIB内存if (m_hDib == 0){return NULL;// 分配失败,返回NULL}///给CDib类的成员变量赋值	lpdib = (LPSTR) ::GlobalLock((HGLOBAL)m_hDib);// 锁定lpbminfo = (BITMAPINFO*)lpdib;lpbmihrd = (BITMAPINFOHEADER*)lpdib;lpRgbQuag = (RGBQUAD*)(lpdib + lpbmihrd->biSize);int m_numberOfColors = GetColorNum((LPSTR)lpbmihrd);if (lpbmihrd->biClrUsed == 0)lpbmihrd->biClrUsed = m_numberOfColors;DWORD colorTableSize = m_numberOfColors *sizeof(RGBQUAD);lpDIBBits = lpdib + lpbmihrd->biSize + colorTableSize;/if (file.Read(lpdib, dwFileSize - sizeof(BITMAPFILEHEADER)) !=// 读像素dwFileSize - sizeof(BITMAPFILEHEADER))//大小不一致{::GlobalUnlock((HGLOBAL)m_hDib);	// 解除锁定			::GlobalFree((HGLOBAL)m_hDib);	// 释放内存return NULL;}::GlobalUnlock((HGLOBAL)m_hDib);// 解除锁定		return m_hDib;// 返回DIB句柄
}/*************************************************************************
* 函数名称:ConstructPalette(HGLOBAL hDIB, CPalette* pPal)
* 函数参数:
*   HGLOBAL hDIB,DIB对象的句柄
*   CPalette* pPal,调色板的指针
* 函数类型:BOOL
* 函数说明:该函数按照DIB创建一个逻辑调色板
************************************************************************/BOOL CDib::ConstructPalette(HGLOBAL hDIB, CPalette* pPal)
{HANDLE hLogPal;// 逻辑调色板的句柄	int iLoop;// 循环变量	BOOL bSuccess = FALSE;// 创建结果	if (hDIB == NULL)//判断是否是有效的DIB对象{return FALSE;// 返回FALSE}lpdib = (LPSTR) ::GlobalLock((HGLOBAL)hDIB);// 锁定DIBlpbminfo = (LPBITMAPINFO)lpdib;long wNumColors = GetColorNum(lpdib);// 获取DIB中颜色表中的颜色数目	if (wNumColors != 0){hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)// 分配为逻辑调色板内存+ sizeof(PALETTEENTRY)* wNumColors);if (hLogPal == 0)// 如果失败则退出{::GlobalUnlock((HGLOBAL)hDIB);// 解除锁定			return FALSE;}LPLOGPALETTE lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL)hLogPal);lpPal->palVersion = PalVersion;// 设置调色板版本号				lpPal->palNumEntries = (WORD)wNumColors;// 设置颜色数目		for (iLoop = 0; iLoop<(int)wNumColors; iLoop++)// 读取调色板{lpPal->palPalEntry[iLoop].peRed = lpbminfo->bmiColors[iLoop].rgbRed;// 读取三原色分量						lpPal->palPalEntry[iLoop].peGreen = lpbminfo->bmiColors[iLoop].rgbGreen;lpPal->palPalEntry[iLoop].peBlue = lpbminfo->bmiColors[iLoop].rgbBlue;lpPal->palPalEntry[iLoop].peFlags = 0;// 保留位			}bSuccess = pPal->CreatePalette(lpPal);// 按照逻辑调色板创建调色板,并返回指针			::GlobalUnlock((HGLOBAL)hLogPal);// 解除锁定				::GlobalFree((HGLOBAL)hLogPal);// 释放逻辑调色板}::GlobalUnlock((HGLOBAL)hDIB);// 解除锁定		return bSuccess;// 返回结果
}

FrequencyFilterDib.h

//======================================================================
// 文件: FrequencyFilterDib.h
// 内容: 图像频域滤波增强-头文件
// 功能: (1)傅立叶变换函数;       
//        (2)理想低通滤波函数
//        (3)理想高通滤波函数
// 
//======================================================================#pragma once#include "Dib.h" 
#include "afx.h"class CFrequencyFilterDib
{
public:// 构造函数,初始化数据成员CFrequencyFilterDib(CDib *pDib);// 析构函数	~CFrequencyFilterDib(void);//傅立叶变换函数void fourier(double * data, int height, int width, int isign);// 理想低通滤波函数void Perfect_Low_Filter(int u,int v);// 理想高通滤波函数void Perfect_High_Filter(int u,int v); private:// 数据成员,CDib对象的指针 CDib *m_pDib; };

 FrequencyFilterDib.cpp

//======================================================================
// 文件: FrequencyFilterDib.cpp
// 内容: 图像频域滤波增强-源文件
// 功能: (1)傅立叶变换函数;       
//        (2)理想低通滤波函数
//        (3)理想高通滤波函数
// 
//======================================================================#include "StdAfx.h"
#include "FrequencyFilterDib.h"
#include<math.h>
#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4) #define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
#define pi 3.14159265359//=======================================================
// 函数功能: 构造函数,初始化数据成员
// 输入参数: 位图指针
// 返回值:   无
//=======================================================
CFrequencyFilterDib::CFrequencyFilterDib(CDib *pDib)
{m_pDib = pDib;
}//=======================================================
// 函数功能: 析构函数
// 输入参数: 无
// 返回值:   无
//=======================================================CFrequencyFilterDib::~CFrequencyFilterDib(void)
{}//=======================================================
// 函数功能: 傅立叶变换函数
// 输入参数: double * data-时域数据指针
//            int height-图像的高度
//            int width-图像宽度
//            int isign-表示正反变换
// 返回值:   无
//=======================================================void CFrequencyFilterDib::fourier(double * data, int height, int width, int isign)
{int idim;unsigned long i1,i2,i3,i2rev,i3rev,ip1,ip2,ip3,ifp1,ifp2;unsigned long ibit,k1,k2,n,nprev,nrem,ntot,nn[3];double tempi,tempr;double theta,wi,wpi,wpr,wr,wtemp;	ntot=height*width; nn[1]=height;nn[2]=width;nprev=1;for (idim=2;idim>=1;idim--) {n=nn[idim];nrem=ntot/(n*nprev);ip1=nprev << 1;ip2=ip1*n;ip3=ip2*nrem;i2rev=1;for (i2=1;i2<=ip2;i2+=ip1){if (i2 < i2rev) {for (i1=i2;i1<=i2+ip1-2;i1+=2) {for (i3=i1;i3<=ip3;i3+=ip2){i3rev=i2rev+i3-i2;SWAP(data[i3],data[i3rev]);SWAP(data[i3+1],data[i3rev+1]);}}}ibit=ip2 >> 1;while (ibit >= ip1 && i2rev > ibit){i2rev -= ibit;ibit >>= 1;}i2rev += ibit;}ifp1=ip1;while (ifp1 < ip2) {ifp2=ifp1 << 1;theta=isign*pi*2/(ifp2/ip1);wtemp=sin(0.5*theta);wpr = -2.0*wtemp*wtemp;wpi=sin(theta);wr=1.0;wi=0.0;for (i3=1;i3<=ifp1;i3+=ip1){for (i1=i3;i1<=i3+ip1-2;i1+=2) {for (i2=i1;i2<=ip3;i2+=ifp2) {k1=i2;k2=k1+ifp1;tempr=wr*data[k2]-wi*data[k2+1];tempi=wr*data[k2+1]+wi*data[k2];data[k2]=data[k1]-tempr;data[k2+1]=data[k1+1]-tempi;data[k1] += tempr;data[k1+1] += tempi;}}wr=(wtemp=wr)*wpr-wi*wpi+wr;wi=wi*wpr+wtemp*wpi+wi;}ifp1=ifp2;}nprev *= n;}
}//=======================================================
// 函数功能: 理想低通滤波函数
// 输入参数: int u,int v-截止频率的分量值
// 返回值:   无
//=======================================================
void CFrequencyFilterDib::Perfect_Low_Filter(int u,int v)
{LPBYTE	lpSrc;			// 指向原图像当前点的指针long i,j;			//循环变量double d0;  //截止频域变量double max=0.0; //归一化因子double *t;  //空域数据指针double *H;  //传递函数指针LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度 	long lLineBytes=WIDTHBYTES(lWidth*8);//计算图象每行的字节数t=new double [lHeight*lLineBytes*2+1]; //分配空域空间H=new double [lHeight*lLineBytes*2+1]; //分配传递函数空间d0=sqrt((float)(u*u+v*v)) ;  //计算截止频率d0//给空域赋值,并计算传递函数for(j=0;j<lHeight;j++){for(i=0;i<lLineBytes;i++){lpSrc=lpDIBBits+lLineBytes*j+i;//指向第i行第j列象素//给空域赋值t[(2*lLineBytes)*j+2*i+1]=*lpSrc;t[(2*lLineBytes)*j+2*i+2]=0.0;//计算传递函数if((sqrt((float)(i*i+j*j)))<=d0)H[2*i+(2*lLineBytes)*j+1]=1.0;elseH[2*i+(2*lLineBytes)*j+1]=0.0;H[2*i+(2*lLineBytes)*j+2]=0.0;}}//进行傅立叶变换fourier(t,lHeight,lLineBytes,1);//傅立叶变换结果与传递函数进行卷积运算for(j=1;j<lHeight*lLineBytes*2;j+=2){t[j]=t[j]*H[j]-t[j+1]*H[j+1];t[j+1]=t[j]*H[j+1]+t[j+1]*H[j];}//进行傅立叶逆变换fourier(t,lHeight,lLineBytes,-1);//计算归一化因子for(j=0;j<lHeight;j++){for(i=0;i<lLineBytes;i++){t[(2*lLineBytes)*j+2*i+1]=sqrt(t[(2*lLineBytes)*j+2*i+1]*t[(2*lLineBytes)*j+2*i+1]+t[(2*lLineBytes)*j+2*i+2]*t[(2*lLineBytes)*j+2*i+2]);if(max<t[(2*lLineBytes)*j+2*i+1])max=t[(2*lLineBytes)*j+2*i+1];}}//计算结果图像,并保存到原图像数据区for(j=0;j<lHeight;j++){for(i=0;i<lLineBytes;i++){lpSrc=lpDIBBits+lLineBytes*j+i;*lpSrc=(BYTE)(t[(2*lLineBytes)*j+2*i+1]*255.0/max);}}//释放内存空间delete t;delete H;
}//=======================================================
// 函数功能: 理想高通滤波函数
// 输入参数: int u,int v-截止频率的分量值
// 返回值:   无
//=======================================================
void CFrequencyFilterDib::Perfect_High_Filter(int u,int v)
{LPBYTE	lpSrc;			// 指向原图像当前点的指针long i,j;			//循环变量double d0;  //截止频域变量double max=0.0; //归一化因子double *t;  //空域数据指针double *H;  //传递函数指针LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度 	long lLineBytes=WIDTHBYTES(lWidth*8);//计算图象每行的字节数t=new double [lHeight*lLineBytes*2+1]; //分配空域空间H=new double [lHeight*lLineBytes*2+1]; //分配传递函数空间d0=sqrt((float)(u*u+v*v)) ;  //计算截止频率d0//给空域赋值,并计算传递函数for(j=0;j<lHeight;j++){for(i=0;i<lLineBytes;i++){lpSrc=lpDIBBits+lLineBytes*j+i;//指向第i行第j列象素//给空域赋值t[(2*lLineBytes)*j+2*i+1]=*lpSrc;t[(2*lLineBytes)*j+2*i+2]=0.0;//计算传递函数if((sqrt((float)(i*i+j*j)))<=d0)H[2*i+(2*lLineBytes)*j+1]=0.0;elseH[2*i+(2*lLineBytes)*j+1]=1.0;H[2*i+(2*lLineBytes)*j+2]=0.0;}}//进行傅立叶变换fourier(t,lHeight,lLineBytes,1);//傅立叶变换结果与传递函数进行卷积运算for(j=1;j<lHeight*lLineBytes*2;j+=2){t[j]=t[j]*H[j]-t[j+1]*H[j+1];t[j+1]=t[j]*H[j+1]+t[j+1]*H[j];}//进行傅立叶逆变换fourier(t,lHeight,lLineBytes,-1);//计算归一化因子for(j=0;j<lHeight;j++){for(i=0;i<lLineBytes;i++){t[(2*lLineBytes)*j+2*i+1]=sqrt(t[(2*lLineBytes)*j+2*i+1]*t[(2*lLineBytes)*j+2*i+1]+t[(2*lLineBytes)*j+2*i+2]*t[(2*lLineBytes)*j+2*i+2]);if(max<t[(2*lLineBytes)*j+2*i+1])max=t[(2*lLineBytes)*j+2*i+1];}}//计算结果图像for(j=0;j<lHeight;j++){for(i=0;i<lLineBytes;i++){lpSrc=lpDIBBits+lLineBytes*j+i;*lpSrc=(BYTE)(t[(2*lLineBytes)*j+2*i+1]*255.0/max);}}//释放内存空间delete t;delete H;
}

 GrayTransformDib.h

//======================================================================
// 文件: GrayTransformDib.h
// 内容: 图像灰度变换增强函数-头文件
// 功能: (1)线性灰度增强;
//        (2)分段线性灰度增强;
//        (3)对数函数非线性灰度增强;
//        
// 
//======================================================================#pragma once#include "Dib.h"#include "afx.h"class CGrayTransformDib
{
public:// 构造函数,初始化数据成员CGrayTransformDib(CDib *pDib);// 析构函数	~CGrayTransformDib(void);// 线性灰度增强BOOL Linear_Transform( BYTE gMin, BYTE gMax);// 分段线性灰度增强BOOL Seg_Linear_Transform( BYTE gSrc1, BYTE gSrc2,BYTE gDst1, BYTE gDst2);// 对数函数非线性灰度增强BOOL Log_Transform( double a, double b, double c);private:// 数据成员,CDib对象的指针 CDib *m_pDib; };

 GrayTransformDib.cpp

//======================================================================
// 文件: GrayTransformDib.cpp
// 内容: 图像灰度变换增强函数-源文件
// 功能: (1)线性灰度增强;
//        (2)分段线性灰度增强;
//        (3)对数函数非线性灰度增强;
// 
//======================================================================#include "StdAfx.h"
#include "GrayTransformDib.h"
#include<math.h>//=======================================================
// 函数功能: 构造函数,初始化数据成员
// 输入参数: 位图指针
// 返回值:   无
//=======================================================
CGrayTransformDib::CGrayTransformDib(CDib *pDib)
{m_pDib = pDib;
}//=======================================================
// 函数功能: 析构函数
// 输入参数: 无
// 返回值:   无
//=======================================================CGrayTransformDib::~CGrayTransformDib(void)
{}//=======================================================
// 函数功能: 线性灰度增强
// 输入参数: BYTE gMin-变换后目标图像的最小灰度值
//            BYTE gMax-变换后目标图像的最大灰度值
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================BOOL CGrayTransformDib::Linear_Transform( BYTE gMin, BYTE gMax)
{LPBYTE	lpSrc;			// 指向原图像的指针	LPBYTE	lpDst;			// 指向缓存图像的指针	LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	long i,j;			//循环变量BYTE pixel;	//像素值LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0lpDst = (LPBYTE)lpNewDIBBits;memset(lpDst, (BYTE)0, lWidth * lHeight);//逐个扫面图像中的像素点,进行灰度线性变换for(j = 0; j <lHeight; j++){for(i = 0;i <lWidth; i++){// 指向原图像倒数第j行,第i个像素的指针			lpSrc = (LPBYTE)lpDIBBits + lWidth * j + i;// 指向目标图像倒数第j行,第i个像素的指针			lpDst = (LPBYTE)lpNewDIBBits + lWidth * j + i;//取得当前指针处的像素值,注意要转换为BYTE类型pixel = (BYTE)*lpSrc;//根据公式(5-2)求出目标图像中与当前点对应的像素点的灰度值*lpDst = (BYTE)(((float)(gMax-gMin)/255)*pixel+gMin+0.5);}}// 复制变换后的图像memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;}//=======================================================
// 函数功能: 分段线性灰度增强
// 输入参数: BYTE gSrc1, BYTE gSrc2-原图像灰度区间分段点
//            BYTE gDst1, BYTE gDst2-变换后的目标图像灰度区间分段点
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================BOOL CGrayTransformDib::Seg_Linear_Transform( BYTE gSrc1, BYTE gSrc2,BYTE gDst1, BYTE gDst2)
{LPBYTE	lpSrc;			// 指向原图像的指针	LPBYTE	lpDst;			// 指向缓存图像的指针	LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	long i,j;			//循环变量BYTE pixel;	//像素值LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0lpDst = (LPBYTE)lpNewDIBBits;memset(lpDst, (BYTE)0, lWidth * lHeight);//逐个扫面图像中的像素点,进行灰度分段线性变换for(j = 0; j <lHeight; j++){for(i = 0;i <lWidth; i++){// 指向原图像倒数第j行,第i个像素的指针			lpSrc = (LPBYTE)lpDIBBits + lWidth * j + i;// 指向目标图像倒数第j行,第i个像素的指针			lpDst = (LPBYTE)lpNewDIBBits + lWidth * j + i;//取得当前指针处的像素值,注意要转换为BYTE类型pixel = (BYTE)*lpSrc;//根据分段线性灰度变化公式右边上式求出目标图像中与当前点对应的像素点的灰度值if(pixel<gSrc1){*lpDst = (BYTE)(((float)gDst1/gSrc1)*pixel+0.5);}//根据分段线性灰度变化公式公式右边中式求出目标图像中与当前点对应的像素点的灰度值if((pixel>=gSrc1)&&(pixel<=gSrc2)){*lpDst = (BYTE)(((float)(gDst2-gDst1)/(gSrc2-gSrc1))*(pixel-gSrc1)+gDst1+0.5);}//根据分段线性灰度变化公式公式右边下式求出目标图像中与当前点对应的像素点的灰度值if((pixel>gSrc2)&&(pixel<=255)){*lpDst = (BYTE)(((float)(255-gDst2)/(255-gSrc2))*(pixel-gSrc2)+gDst2+0.5);}}}// 复制变换后的图像memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;}//=======================================================
// 函数功能: 对数函数非线性灰度增强
// 输入参数: double a, double b,double c-调整曲线位置和形状的参数
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================
BOOL CGrayTransformDib::Log_Transform( double a, double b, double c)
{LPBYTE	lpSrc;			// 指向原图像的指针	LPBYTE	lpDst;			// 指向缓存图像的指针	LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	long i,j;			//循环变量BYTE pixel;	//像素值LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0lpDst = (LPBYTE)lpNewDIBBits;memset(lpDst, (BYTE)0, lWidth * lHeight);//逐个扫面图像中的像素点,进行对数函数非线性灰度变换for(j = 0; j <lHeight; j++){for(i = 0;i <lWidth; i++){// 指向原图像倒数第j行,第i个像素的指针			lpSrc = (LPBYTE)lpDIBBits + lWidth * j + i;// 指向目标图像倒数第j行,第i个像素的指针			lpDst = (LPBYTE)lpNewDIBBits + lWidth * j + i;//取得当前指针处的像素值,注意要转换为BYTE类型pixel = (BYTE)*lpSrc;//根据公式(5-4)求出目标图像中与当前点对应的像素点的灰度值*lpDst = (BYTE)((log((double)(pixel+1)))/(b*log(c))+a+0.5);}}// 复制变换后的图像memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;}

HistogramDib.h

//======================================================================
// 文件: HistogramDib.h
// 内容: 直方图增强函数-头文件
// 功能: (1)直方图统计函数;
//        (2)直方图均衡化函数;
//        (3)直方图匹配(规定化)函数;
// 
//======================================================================#pragma once#include "Dib.h"#include "afx.h"class CHistogramDib
{
public:// 构造函数,初始化数据成员CHistogramDib(CDib *pDib);// 析构函数	~CHistogramDib(void);// 直方图统计函数void Histogram_Statistic( float *probability);// 直方图均衡化函数BOOL Histogram_Equalization( );// 直方图规定化(匹配)函数BOOL Histogram_Match( BYTE bGray, int *npMap, float *fpPro);private:// 数据成员,CDib对象的指针 CDib *m_pDib; };

HistogramDib.cpp

//======================================================================
// 文件: HistogramDib.cpp
// 内容: 直方图增强函数-源文件
// 功能: (1)直方图统计函数;
//        (2)直方图均衡化函数;
//        (3)直方图匹配(规定化)函数;
// 
//======================================================================#include "StdAfx.h"
#include "HistogramDib.h"//=======================================================
// 函数功能: 构造函数,初始化数据成员
// 输入参数: 位图指针
// 返回值:   无
//=======================================================CHistogramDib::CHistogramDib(CDib *pDib)
{m_pDib = pDib;
}//=======================================================
// 函数功能: 析构函数
// 输入参数: 无
// 返回值:   无
//=======================================================CHistogramDib::~CHistogramDib(void)
{}//=======================================================
// 函数功能: 直方图统计函数
// 输入参数: float *probability -灰度分布概率密度
// 返回值:   无
//=======================================================void CHistogramDib::Histogram_Statistic( float *probability)
{LPBYTE	lpSrc;			// 指向原图像的指针	long i,j;			//循环变量	int gray[256]; // 灰度计数BYTE pixel;	//像素值LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 灰度计数变量初始化memset(gray,0,sizeof(gray));//逐个扫面图像中的像素点,进行灰度计数统计for(j = 0; j <lHeight; j++){for(i = 0;i <lWidth; i++){// 指向原图像倒数第j行,第i个像素的指针			lpSrc = (LPBYTE)lpDIBBits + lWidth * j + i;//取得当前指针处的像素值,注意要转换为BYTE类型pixel = (BYTE)*lpSrc;// 灰度统计计数gray[pixel]++;}}// 计算灰度概率密度for(i=0;i<256;i++){probability[i] = gray[i] / (lHeight * lWidth *1.0f);}}//=======================================================
// 函数功能: 直方图均衡化函数
// 输入参数: 无
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================BOOL CHistogramDib::Histogram_Equalization( )
{LPBYTE	lpSrc;			// 指向原图像的指针	LPBYTE	lpDst;			// 指向缓存图像的指针	LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	long i,j;			//循环变量BYTE pixel;	//像素值//原图像灰度分布概率密度变量float fPro[256];//中间变量float temp[256];int nRst[256];LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0lpDst = (LPBYTE)lpNewDIBBits;memset(lpDst, (BYTE)0, lWidth * lHeight);// 初始化中间变量tempmemset(temp, 0, sizeof(temp));// 获取原图像灰度分布的概率密度Histogram_Statistic(fPro);//进行直方图均衡化处理for(i = 0; i < 256; i++){if(i == 0){temp[0] = fPro[0];	 }else{temp[i] = temp[i-1] + fPro[i];	 }nRst[i] = (int)(255.0f * temp[i] + 0.5f);}	//将直方图均衡化后的结果写到目标图像中for(j = 0; j <lHeight; j++){for(i = 0;i <lWidth; i++){// 指向原图像倒数第j行,第i个像素的指针			lpSrc = (LPBYTE)lpDIBBits + lWidth * j + i;// 指向目标图像倒数第j行,第i个像素的指针			lpDst = (LPBYTE)lpNewDIBBits + lWidth * j + i;//取得当前指针处的像素值,注意要转换为BYTE类型pixel = (BYTE)*lpSrc;*lpDst = (BYTE)(nRst[pixel]);}}// 复制均衡化处理后的图像到原图像中memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;}//=======================================================
// 函数功能: 直方图规定化(匹配)函数
// 输入参数: BYTE bGray -规定直方图的灰度级
//            int *npMap -规定直方图映射关系
//            float *fpPro -规定灰度分布概率
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================BOOL CHistogramDib::Histogram_Match( BYTE bGray, int *npMap, float *fpPro)
{LPBYTE	lpSrc;			// 指向原图像的指针	LPBYTE	lpDst;			// 指向缓存图像的指针	LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	long i,j;			//循环变量BYTE pixel;	//像素值//原图像灰度分布概率密度变量float fPro[256];//中间变量float temp[256];//灰度映射表变量int nMap[256];LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0lpDst = (LPBYTE)lpNewDIBBits;memset(lpDst, (BYTE)0, lWidth * lHeight);// 获取原图像灰度分布的概率密度Histogram_Statistic(fPro);// 计算原图像累计直方图for (i = 0; i < 256; i++){if (i == 0){temp[0] = fPro[0];			 }else{temp[i] = temp[i-1] + fPro[i];			 }fPro[i] = temp[i];}// 计算规定变换后的累计直方图for (i = 0; i < bGray; i++){if (i == 0){temp[0] = fpPro[0];}else{temp[i] = temp[i-1] + fpPro[i];}fpPro[i] = temp[i];}// 确定映射关系for (i = 0; i < 256; i++){// 最接近的规定直方图灰度级int m = 0;// 最小差值float min_value = 1.0f;// 枚举规定直方图各灰度for (j = 0; j < bGray; j++){// 当前差值float now_value = 0.0f;//  差值计算if (fPro[i] - fpPro[j] >= 0.0f)now_value = fPro[i] - fpPro[j];elsenow_value = fpPro[j] - fPro[i];// 寻找最接近的规定直方图灰度级if (now_value < min_value){// 最接近的灰度级m = j;// 最小差值min_value = now_value;}}// 建立灰度映射表nMap[i] = npMap[m];}// 对各像素进行直方图规定化映射处理for (j = 0; j < lHeight; j ++){for (i = 0; i < lWidth; i ++){// 指向原图像倒数第j行,第i个像素的指针			lpSrc = (LPBYTE)lpDIBBits + lWidth * j + i;// 指向目标图像倒数第j行,第i个像素的指针			lpDst = (LPBYTE)lpNewDIBBits + lWidth * j + i;//取得当前指针处的像素值,注意要转换为BYTE类型pixel = (BYTE)*lpSrc;//对目标图像进行映射处理*lpDst = (BYTE)(nMap[pixel]);}}// 复制直方图规定化处理后的图像到原图像中memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;}

 SharpenProcessDib.h

//======================================================================
// 文件: SharpenProcessDib.h
// 内容: 图像锐化处理函数-头文件
// 功能: (1)门限梯度锐化函数;       
//        (2)卷积运算函数;
//        (3)拉普拉斯掩膜锐化函数        
// 
//======================================================================#pragma once#include "Dib.h" 
#include "afx.h"class CSharpenProcessDib
{
public:// 构造函数,初始化数据成员CSharpenProcessDib(CDib *pDib);// 析构函数	~CSharpenProcessDib(void);// 门限梯度锐化函数BOOL GateGrad(BYTE t);//卷积运算函数BOOL Convolution(int tempH, int tempW, int tempMX, int tempMY, float *fpTempArray, float fCoef); // 拉普拉斯眼膜锐化函数void Laplacian( ); private:// 数据成员,CDib对象的指针 CDib *m_pDib; };

SharpenProcessDib.cpp

//======================================================================
// 文件: SharpenProcessDib.cpp
// 内容: 图像锐化处理函数-源文件
// 功能: (1)门限梯度锐化函数;
//        (2)卷积运算
//        (3)拉普拉斯掩膜锐化函数       
// 
//======================================================================#include "StdAfx.h"
#include "SharpenProcessDib.h"
#include<math.h>//=======================================================
// 函数功能: 构造函数,初始化数据成员
// 输入参数: 位图指针
// 返回值:   无
//=======================================================
CSharpenProcessDib::CSharpenProcessDib(CDib *pDib)
{m_pDib = pDib;
}//=======================================================
// 函数功能: 析构函数
// 输入参数: 无
// 返回值:   无
//=======================================================CSharpenProcessDib::~CSharpenProcessDib(void)
{}//=======================================================
// 函数功能: 门限梯度锐化处理函数
// 输入参数: BYTE t -门限值
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================BOOL CSharpenProcessDib::GateGrad(BYTE t)
{LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	long i,j;			//循环变量BYTE temp; //暂存双向一次微分结果LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0  	memset(lpNewDIBBits, (BYTE)0, lWidth * lHeight);//逐个扫描图像中的像素点,进行门限梯度锐化处理for(j=1;j<lHeight-1;j++){for(i=1;i<lWidth-1;i++){//根据双向一次微分公式计算当前像素的灰度值temp=(BYTE)sqrt((float)((lpDIBBits[lWidth*j+i]-lpDIBBits[lWidth*j+(i-1)])*(lpDIBBits[lWidth*j+i]-lpDIBBits[lWidth*j+(i-1)])+(lpDIBBits[lWidth*j+i]-lpDIBBits[lWidth*(j-1)+i])*(lpDIBBits[lWidth*j+i]-lpDIBBits[lWidth*(j-1)+i])));if (temp>=t){   if((temp+100)>255)lpNewDIBBits[lWidth*j+i]=255;else lpNewDIBBits[lWidth*j+i]=temp+100;}if (temp<t)lpNewDIBBits[lWidth*j+i]=lpDIBBits[lWidth*j+i];}}// 复制变换后的图像memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;  
}//=======================================================
// 函数功能: 卷积运算函数
// 输入参数: int tempH:模板高度        
//            int tempW:模板宽度                                   
//            int tempMX:模板的中心元素X坐标               
//            int tempMY:模板的中心元素Y坐标             
//            float *fpTempArray:指向模板数组的指针                      
//            float fCoef:模板系数                                 
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================BOOL CSharpenProcessDib::Convolution(int tempH, int tempW, int tempMX, int tempMY, float *fpTempArray, float fCoef)
{LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	long i,j,k,l;			//循环变量float fResult;    //暂存计算中间结果     LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度	// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0 	memset(lpNewDIBBits, (BYTE)0, lWidth * lHeight);//逐个扫描图像中的像素点,进行卷积运算for(j=tempMY;j<lHeight-tempH+tempMY+1;j++){for(i=tempMX;i<lWidth-tempW+tempMX+1;i++){//计算像素值fResult=0;for(k=0;k<tempH;k++)for(l=0;l<tempW;l++)fResult=fResult+lpDIBBits[(j-tempMY+k)*lWidth+(i-tempMX+l)]*fpTempArray[k*tempW+l];//乘上系数fResult*=fCoef;//取绝对值fResult=(float)fabs(fResult);//判断是否超过255if(fResult>255)//若超过255,直接赋值为255lpNewDIBBits[j*lWidth+i]=255;else//未超过255,赋值为计算结果lpNewDIBBits[j*lWidth+i]=(BYTE)(fResult+0.5);}}// 复制变换后的图像memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;  }//=======================================================
// 函数功能: 拉普拉斯锐化处理函数
// 输入参数: 无
// 返回值:   无
//=======================================================
void CSharpenProcessDib::Laplacian( )
{int tempH;  //模板高度int tempW;  //模板宽度float tempC;  //模板系数int tempMY;   //模板中心元素Y坐标int tempMX;   //模板中心元素X坐标float Template[9];   //模板数组	//设置拉普拉斯模板参数tempW=3;tempH=3;tempC=1.0;tempMY=1;tempMX=1;Template[0]=0.0;Template[1]=1.0;Template[2]=0.0;Template[3]=1.0;Template[4]=-4.0;Template[5]=1.0;Template[6]=0.0;Template[7]=1.0;Template[8]=0.0;//调用卷积函数Convolution(tempH,tempW,tempMX,tempMY,Template,tempC); }

 SmoothProcessDib.h

//======================================================================
// 文件: SmoothProcessDib.h
// 内容: 图像平滑处理函数-头文件
// 功能: (1)邻域平均平滑函数;
//        (2)加权平均平滑函数;
//        (3)选择式掩膜平滑函数;
//        (4)中值滤波平滑函数       
// 
//======================================================================#pragma once#include "Dib.h"#include "afx.h"class CSmoothProcessDib
{
public:// 构造函数,初始化数据成员CSmoothProcessDib(CDib *pDib);// 析构函数	~CSmoothProcessDib(void);// 邻域平均平滑函数BOOL Average_Smooth( );// 加权平均平滑函数BOOL Value_Average_Smooth( int Structure[3][3]);// 选择式掩膜平滑函数BOOL Select_Smooth( );// 中值滤波平滑函数BOOL Middle_Smooth( );private:// 数据成员,CDib对象的指针 CDib *m_pDib; };

SmoothProcessDib.cpp

//======================================================================
// 文件: SmoothProcessDib.cpp
// 内容: 图像平滑处理函数-源文件
// 功能: (1)邻域平均平滑函数;
//        (2)加权平均平滑函数;
//        (3)选择式掩膜平滑函数;
//        (4)中值滤波平滑函数       
// 
//======================================================================
#include "StdAfx.h"
#include "SmoothProcessDib.h"//=======================================================
// 函数功能: 构造函数,初始化数据成员
// 输入参数: 位图指针
// 返回值:   无
//=======================================================
CSmoothProcessDib::CSmoothProcessDib(CDib *pDib)
{m_pDib = pDib;
}//=======================================================
// 函数功能: 析构函数
// 输入参数: 无
// 返回值:   无
//=======================================================CSmoothProcessDib::~CSmoothProcessDib(void)
{}//=======================================================
// 函数功能: 邻域平均平滑函数
// 输入参数: 无
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================
BOOL CSmoothProcessDib::Average_Smooth( )
{LPBYTE	lpDst;			// 指向缓存图像的指针	LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	long i,j;			//循环变量BYTE average;	//领域均值变量LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0lpDst = (LPBYTE)lpNewDIBBits;memset(lpDst, (BYTE)0, lWidth * lHeight);//逐个扫描图像中的像素点,求其邻域均值for(j = 1; j <lHeight-1; j++){for(i = 1;i <lWidth-1; i++){// 指向目标图像第j行,第i个像素的指针			lpDst = (LPBYTE)lpNewDIBBits + lWidth * j + i;//求当前点及其周围8个点的均值average=(BYTE)((float)(lpDIBBits[(j-1)*lWidth+(i-1)]+lpDIBBits[(j-1)*lWidth+i]+lpDIBBits[(j-1)*lWidth+(i+1)]+lpDIBBits[j*lWidth+(i-1)]+lpDIBBits[j*lWidth+i]+lpDIBBits[j*lWidth+i+1]+lpDIBBits[(j+1)*lWidth+(i-1)]+lpDIBBits[(j+1)*lWidth+i]+lpDIBBits[(j+1)*lWidth+i+1])/9+0.5);//将求得的均值赋值给目标图像中与当前点对应的像素点*lpDst = average;}}// 复制变换后的图像memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;}//=======================================================
// 函数功能: 加权平均平滑函数
// 输入参数: int Structure[3][3]-领域加权模板
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================
BOOL CSmoothProcessDib::Value_Average_Smooth(int Structure[3][3])
{LPBYTE	lpDst;			// 指向缓存图像的指针	LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	long i,j,m,n;			//循环变量int sum=0; //模板中各个元素总和BYTE value_average;	//领域加权均值变量LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0lpDst = (LPBYTE)lpNewDIBBits;memset(lpDst, (BYTE)0, lWidth * lHeight);//求模板中各元素权值总和for (m = 0;m < 3;m++ ){for (n = 0;n < 3;n++){sum+=Structure[m][n];		}}			//逐个扫描图像中的像素点,求其邻域加权均值for(j = 1; j <lHeight-1; j++){for(i = 1;i <lWidth-1; i++){// 指向目标图像第j行,第i个像素的指针			lpDst = (LPBYTE)lpNewDIBBits + lWidth * j + i;//求加权均值value_average=(BYTE)((float)(lpDIBBits[(j+1)*lWidth+(i-1)]*Structure[0][0]+lpDIBBits[(j+1)*lWidth+i]*Structure[0][1]+lpDIBBits[(j+1)*lWidth+i+1]*Structure[0][2]+lpDIBBits[j*lWidth+(i-1)]*Structure[1][0]+lpDIBBits[j*lWidth+i]*Structure[1][1]+lpDIBBits[j*lWidth+i+1]*Structure[1][2]+lpDIBBits[(j-1)*lWidth+(i-1)]*Structure[2][0]+lpDIBBits[(j-1)*lWidth+i]*Structure[2][1]+lpDIBBits[(j-1)*lWidth+(i+1)]*Structure[2][2])/sum+0.5); 				//将求得的加权均值赋值给目标图像中与当前点对应的像素点*lpDst = value_average;}}// 复制变换后的图像memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;}//=======================================================
// 函数功能: 选择式掩膜平滑函数
// 输入参数: 无
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================
BOOL CSmoothProcessDib::Select_Smooth( )
{LPBYTE	lpDst;			// 指向缓存图像的指针	LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	int i,j,n;			//循环变量BYTE pixel[9];	//领域各点的像素值float mean[9],var[9],varMin; //邻域均值,邻域方差,方差最小值int nMin; //方差最小时的邻域号     LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0lpDst = (LPBYTE)lpNewDIBBits;memset(lpDst, (BYTE)0, lWidth * lHeight);//求9种邻域的均值与方差for(j=2;j<=lHeight-3;j++){for(i=2;i<=lWidth-3;i++){//第1邻域pixel[0]=lpDIBBits[(j-1)*lWidth+(i-1)];pixel[1]=lpDIBBits[(j-1)*lWidth+i];pixel[2]=lpDIBBits[(j-1)*lWidth+(i+1)];pixel[3]=lpDIBBits[j*lWidth+(i-1)];pixel[4]=lpDIBBits[j*lWidth+i];pixel[5]=lpDIBBits[j*lWidth+(i+1)];pixel[6]=lpDIBBits[(j+1)*lWidth+(i-1)];pixel[7]=lpDIBBits[(j+1)*lWidth+i];pixel[8]=lpDIBBits[(j+1)*lWidth+(i+1)];mean[0]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6]+pixel[7]+pixel[8])/9;var[0]=0;for(n=0;n<=8;n++)var[0]+=pixel[n]*pixel[n]-mean[0]*mean[0];//第2邻域pixel[0]=lpDIBBits[(j-2)*lWidth+(i-1)];pixel[1]=lpDIBBits[(j-2)*lWidth+i];pixel[2]=lpDIBBits[(j-2)*lWidth+(i+1)];pixel[3]=lpDIBBits[(j-1)*lWidth+(i-1)];pixel[4]=lpDIBBits[(j-1)*lWidth+i];pixel[5]=lpDIBBits[(j-1)*lWidth+(i+1)];pixel[6]=lpDIBBits[j*lWidth+i];mean[1]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7;var[1]=0;for(n=0;n<=6;n++)var[1]+=pixel[n]*pixel[n]-mean[1]*mean[1];//第3邻域pixel[0]=lpDIBBits[(j-1)*lWidth+(i-2)];pixel[1]=lpDIBBits[(j-1)*lWidth+(i-1)];pixel[2]=lpDIBBits[j*lWidth+(i-2)];pixel[3]=lpDIBBits[j*lWidth+(i-1)];pixel[4]=lpDIBBits[j*lWidth+i];pixel[5]=lpDIBBits[(j+1)*lWidth+(i-2)];pixel[6]=lpDIBBits[(j+1)*lWidth+(i-1)];mean[2]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7;var[2]=0;for(n=0;n<=6;n++)var[2]+=pixel[n]*pixel[n]-mean[2]*mean[2];//第4邻域pixel[0]=lpDIBBits[j*lWidth+i];pixel[1]=lpDIBBits[(j+1)*lWidth+(i-1)];pixel[2]=lpDIBBits[(j+1)*lWidth+i];pixel[3]=lpDIBBits[(j+1)*lWidth+(i+1)];pixel[4]=lpDIBBits[(j+2)*lWidth+(i-1)];pixel[5]=lpDIBBits[(j+2)*lWidth+i];pixel[6]=lpDIBBits[(j+2)*lWidth+(i+1)];mean[3]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7;var[3]=0;for(n=0;n<=6;n++)var[3]+=pixel[n]*pixel[n]-mean[3]*mean[3];//第5邻域pixel[0]=lpDIBBits[(j-1)*lWidth+(i+1)];pixel[1]=lpDIBBits[(j-1)*lWidth+(i+2)];pixel[2]=lpDIBBits[j*lWidth+i];pixel[3]=lpDIBBits[j*lWidth+(i+1)];pixel[4]=lpDIBBits[j*lWidth+(i+2)];pixel[5]=lpDIBBits[(j+1)*lWidth+(i+1)];pixel[6]=lpDIBBits[(j+1)*lWidth+(i+2)]; mean[4]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7;var[4]=0;for(n=0;n<=6;n++)var[4]+=pixel[n]*pixel[n]-mean[4]*mean[4];	//第6邻域pixel[0]=lpDIBBits[(j-2)*lWidth+(i+1)];pixel[1]=lpDIBBits[(j-2)*lWidth+(i+2)];pixel[2]=lpDIBBits[(j-1)*lWidth+i];pixel[3]=lpDIBBits[(j-1)*lWidth+(i+1)];pixel[4]=lpDIBBits[(j-1)*lWidth+(i+2)];pixel[5]=lpDIBBits[j*lWidth+i];pixel[6]=lpDIBBits[j*lWidth+(i+1)]; mean[5]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7;var[5]=0;for(n=0;n<=6;n++)var[5]+=pixel[n]*pixel[n]-mean[5]*mean[5];//第7邻域pixel[0]=lpDIBBits[(j-2)*lWidth+(i-2)];pixel[1]=lpDIBBits[(j-2)*lWidth+(i-1)];pixel[2]=lpDIBBits[(j-1)*lWidth+(i-2)];pixel[3]=lpDIBBits[(j-1)*lWidth+(i-1)];pixel[4]=lpDIBBits[(j-1)*lWidth+i];pixel[5]=lpDIBBits[j*lWidth+(i-1)];pixel[6]=lpDIBBits[j*lWidth+i];mean[6]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7;var[6]=0;for(n=0;n<=6;n++)var[6]+=pixel[n]*pixel[n]-mean[6]*mean[6];//第8邻域pixel[0]=lpDIBBits[j*lWidth+(i-1)];pixel[1]=lpDIBBits[j*lWidth+i];pixel[2]=lpDIBBits[(j+1)*lWidth+(i-2)];pixel[3]=lpDIBBits[(j+1)*lWidth+(i-1)];pixel[4]=lpDIBBits[(j+1)*lWidth+i];pixel[5]=lpDIBBits[(j+2)*lWidth+(i-2)];pixel[6]=lpDIBBits[(j+2)*lWidth+(i-1)];mean[7]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7;var[7]=0;for(n=0;n<=6;n++)var[7]+=pixel[n]*pixel[n]-mean[7]*mean[7];//第9邻域pixel[0]=lpDIBBits[j*lWidth+i];pixel[1]=lpDIBBits[j*lWidth+(i+1)];pixel[2]=lpDIBBits[(j+1)*lWidth+i];pixel[3]=lpDIBBits[(j+1)*lWidth+(i+1)];pixel[4]=lpDIBBits[(j+1)*lWidth+(i+2)];pixel[5]=lpDIBBits[(j+2)*lWidth+(i+1)];pixel[6]=lpDIBBits[(j+2)*lWidth+(i+2)];mean[8]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7;var[8]=0;for(n=0;n<=6;n++)var[8]+=pixel[n]*pixel[n]-mean[8]*mean[8];//求方差最小的邻域nMinvarMin=var[0];nMin=0;for(n=0;n<=8;n++){if(varMin>var[n]){varMin=var[n];nMin=n;}}// 指向目标图像第j行,第i个像素的指针			lpDst = (LPBYTE)lpNewDIBBits + lWidth * j + i;//将方差最小的邻域均值赋值给目标像素点*lpDst = (BYTE)(mean[nMin]+0.5);  }}// 复制变换后的图像memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;
}//=======================================================
// 函数功能: 中值滤波平滑函数
// 输入参数: 无
// 返回值:   成功返回TRUE,否则返回FALSE
//=======================================================
BOOL CSmoothProcessDib::Middle_Smooth( )
{LPBYTE	lpDst;			// 指向缓存图像的指针	LPBYTE	lpNewDIBBits;	// 指向缓存DIB图像的指针HLOCAL	hNewDIBBits;	int i,j,x,y,m;			//循环变量int flag=1;  //循环标志变量BYTE pixel[9],mid; //窗口像素值及中值BYTE temp;//中间变量LPBYTE lpDIBBits=m_pDib->GetData();//找到原图像的起始位置LONG lWidth=m_pDib->GetWidth();    //获得原图像的宽度LONG lHeight=m_pDib->GetHeight();  //获得原图像的高度// 暂时分配内存,以保存新图像hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);if (hNewDIBBits == NULL){return FALSE;}lpNewDIBBits = (LPBYTE )LocalLock(hNewDIBBits);// 初始化新分配的内存,设定初始值为0lpDst = (LPBYTE)lpNewDIBBits;memset(lpDst, (BYTE)0, lWidth * lHeight); //中值滤波for(j=1;j<lHeight-1;j++){for(i=1;i<lWidth-1;i++){//把3*3屏蔽窗口的所有像素值放入pixel[m]m=0;for(y=j-1;y<=j+1;y++)for(x=i-1;x<=i+1;x++){pixel[m]=lpDIBBits[y*lWidth+x];m++;}//把pixel[m]中的值按降序排序do{flag=0;for(m=0;m<8;m++){if(pixel[m]<pixel[m+1]){temp=pixel[m];pixel[m]=pixel[m+1];pixel[m+1]=temp;flag=1;}}}while(flag==1);//求中值mid				mid=pixel[4];// 指向目标图像第j行,第i个像素的指针			lpDst = (LPBYTE)lpNewDIBBits + lWidth * j + i;//将中值赋给目标图像的当前点*lpDst = (BYTE)mid;}}// 复制变换后的图像memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);//释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);return TRUE;
}

数字图像处理View.h : C数字图像处理View 类的接口


// 数字图像处理View.h : C数字图像处理View 类的接口
//#pragma once
#include "Dib.h"
#include "GrayTransformDib.h"//图像灰度变换增强函数-头文件
#include "HistogramDib.h"//直方图增强函数-头文件
#include "SmoothProcessDib.h"  //图像平滑处理函数 - 头文件
#include "SharpenProcessDib.h"//图像锐化处理函数-头文件
#include "FrequencyFilterDib.h"// 图像频域滤波增强-头文件
#include "ColorEnhanceDib.h"//图像灰度的颜色增强-头文件class C数字图像处理View : public CView
{
protected: // 仅从序列化创建C数字图像处理View();DECLARE_DYNCREATE(C数字图像处理View)// 特性
public:C数字图像处理Doc* GetDocument() const;// 操作
public:// 重写
public:virtual void OnDraw(CDC* pDC);  // 重写以绘制该视图virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);// 实现
public:virtual ~C数字图像处理View();
#ifdef _DEBUGvirtual void AssertValid() const;virtual void Dump(CDumpContext& dc) const;
#endifprotected:// 生成的消息映射函数
protected:DECLARE_MESSAGE_MAP()
public:afx_msg void OnFileOpen();
public:CDib m_PhotoImage;//照片图像BOOL flag;//打开照片图像标记变量  要在默认构造函数中初始化该对象afx_msg void OnOpenPhoto();afx_msg void OnLinearTransform();afx_msg void OnSegLineTransform();afx_msg void OnLogTransform();afx_msg void OnHistogramEqual();afx_msg void OnHistogramMatch();afx_msg void OnAverageSmooth();afx_msg void OnValueAvrgSmooth();afx_msg void OnSelectSmooth();afx_msg void OnMiddleSmooth();afx_msg void OnGateGrad();afx_msg void OnLaplacian();afx_msg void OnPrefectLowFilter();afx_msg void OnPrefectHighFilter();afx_msg void OnPseudoColorEnhance();
};#ifndef _DEBUG  // 数字图像处理View.cpp 中的调试版本
inline C数字图像处理Doc* C数字图像处理View::GetDocument() const{ return reinterpret_cast<C数字图像处理Doc*>(m_pDocument); }
#endif

数字图像处理View.cpp : C数字图像处理View 类的实现


// 数字图像处理View.cpp : C数字图像处理View 类的实现
//#include "stdafx.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "数字图像处理.h"
#endif#include "数字图像处理Doc.h"
#include "数字图像处理View.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif// C数字图像处理ViewIMPLEMENT_DYNCREATE(C数字图像处理View, CView)BEGIN_MESSAGE_MAP(C数字图像处理View, CView)// 标准打印命令ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)ON_COMMAND(ID_FILE_OPEN, &C数字图像处理View::OnFileOpen)ON_COMMAND(ID_OPEN_PHOTO, &C数字图像处理View::OnOpenPhoto)ON_COMMAND(ID_LINEAR_TRANSFORM, &C数字图像处理View::OnLinearTransform)ON_COMMAND(ID_SEG_LINE_TRANSFORM, &C数字图像处理View::OnSegLineTransform)ON_COMMAND(ID_LOG_TRANSFORM, &C数字图像处理View::OnLogTransform)ON_COMMAND(ID_HISTOGRAM_EQUAL, &C数字图像处理View::OnHistogramEqual)ON_COMMAND(ID_HISTOGRAM_MATCH, &C数字图像处理View::OnHistogramMatch)ON_COMMAND(ID_AVERAGE_SMOOTH, &C数字图像处理View::OnAverageSmooth)ON_COMMAND(ID_VALUE_AVRG_SMOOTH, &C数字图像处理View::OnValueAvrgSmooth)ON_COMMAND(ID_SELECT_SMOOTH, &C数字图像处理View::OnSelectSmooth)ON_COMMAND(ID_MIDDLE_SMOOTH, &C数字图像处理View::OnMiddleSmooth)ON_COMMAND(ID_GATE_GRAD, &C数字图像处理View::OnGateGrad)ON_COMMAND(ID_LAPLACIAN, &C数字图像处理View::OnLaplacian)ON_COMMAND(ID_PREFECT_LOW_FILTER, &C数字图像处理View::OnPrefectLowFilter)ON_COMMAND(ID_PREFECT_HIGH_FILTER, &C数字图像处理View::OnPrefectHighFilter)ON_COMMAND(ID_PSEUDO_COLOR_ENHANCE, &C数字图像处理View::OnPseudoColorEnhance)
END_MESSAGE_MAP()// C数字图像处理View 构造/析构C数字图像处理View::C数字图像处理View()
{// TODO:  在此处添加构造代码flag = FALSE;//用于判断是否打开图像标志位
}C数字图像处理View::~C数字图像处理View()
{}BOOL C数字图像处理View::PreCreateWindow(CREATESTRUCT& cs)
{// TODO:  在此处通过修改//  CREATESTRUCT cs 来修改窗口类或样式return CView::PreCreateWindow(cs);
}// C数字图像处理View 绘制void C数字图像处理View::OnDraw(CDC* /*pDC*/)
{C数字图像处理Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// TODO:  在此处为本机数据添加绘制代码
}// C数字图像处理View 打印BOOL C数字图像处理View::OnPreparePrinting(CPrintInfo* pInfo)
{// 默认准备return DoPreparePrinting(pInfo);
}void C数字图像处理View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{// TODO:  添加额外的打印前进行的初始化过程
}void C数字图像处理View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{// TODO:  添加打印后进行的清理过程
}// C数字图像处理View 诊断#ifdef _DEBUG
void C数字图像处理View::AssertValid() const
{CView::AssertValid();
}void C数字图像处理View::Dump(CDumpContext& dc) const
{CView::Dump(dc);
}C数字图像处理Doc* C数字图像处理View::GetDocument() const // 非调试版本是内联的
{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(C数字图像处理Doc)));return (C数字图像处理Doc*)m_pDocument;
}
#endif //_DEBUG// C数字图像处理View 消息处理程序void C数字图像处理View::OnFileOpen()
{// TODO:  在此添加命令处理程序代码MessageBox(_T("123"));
}void C数字图像处理View::OnOpenPhoto()
{// TODO:  在此添加命令处理程序代码// 本函数功能是打开并显示照片图像CString  filename;CFileDialog dlg(TRUE, _T("BMP"), _T("*.BMP"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("位图文件(*.BMP)|*.BMP|"));if (IDOK == dlg.DoModal())filename.Format("%s", dlg.GetPathName());m_PhotoImage.LoadFromFile(filename);//打开照片图像flag = TRUE;//照片图像打开后,将标记变量置为真//显示图像CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);
}// 此函数实现灰度线性增强处理
void C数字图像处理View::OnLinearTransform()
{// TODO:  在此添加命令处理程序代码// 此函数实现灰度线性增强处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像CGrayTransformDib GrayTransform(&m_PhotoImage);//创建一个CGrayTransformDib对象BYTE min, max;  //设置变换后的灰度区间min = 100;max = 200;GrayTransform.Linear_Transform(min, max);  //调用灰度线性变换增强函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}// 此函数实现分段线性增强处理
void C数字图像处理View::OnSegLineTransform()
{// TODO:  在此添加命令处理程序代码// 此函数实现分段线性增强处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像CGrayTransformDib GrayTransform(&m_PhotoImage); //创建一个CGrayTransformDib对象BYTE gSrc1, gSrc2, gDst1, gDst2;  //设置分段点gSrc1 = 100;gSrc2 = 150;gDst1 = 50;gDst2 = 200;GrayTransform.Seg_Linear_Transform(gSrc1, gSrc2, gDst1, gDst2);//调用分段线性变换增强函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像}// 此函数实现对数函数非线性变换增强处理
void C数字图像处理View::OnLogTransform()
{// TODO:  在此添加命令处理程序代码// 此函数实现对数函数非线性变换增强处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像CGrayTransformDib GrayTransform(&m_PhotoImage);//创建一个CGrayTransformDib对象double a, b, c;  //对数函数变换参数设置a = 50.0;b = 0.8;c = 1.05;GrayTransform.Log_Transform(a, b, c);  //调用对数函数非线性变换增强函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}// 此函数实现直方图均衡化增强处理
void C数字图像处理View::OnHistogramEqual()
{//ID_HISTOGRAM_EQUAL// TODO:  在此添加命令处理程序代码// 此函数实现直方图均衡化增强处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像CHistogramDib Histgram(&m_PhotoImage);//创建一个CHistogramDib对象Histgram.Histogram_Equalization();   //调用直方图均衡化处理函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}// 此函数实现直方图规定化增强处理
void C数字图像处理View::OnHistogramMatch()
{//ID_HISTOGRAM_MATCH// TODO:  在此添加命令处理程序代码// 此函数实现直方图规定化增强处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像CHistogramDib Histgram(&m_PhotoImage);//创建一个CHistogramDib对象int nu[64];  //规定直方图映射关系,这里规定直方图的灰度级为64float pu[64]; //规定灰度分布概率float a = 1.0f / (32.0f*63.0f);for (int i = 0; i<64; i++){nu[i] = i * 4;pu[i] = a*i;}Histgram.Histogram_Match(64, nu, pu); //调用直方图规定化函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图
}// 此函数实现邻域均值平滑处理
void C数字图像处理View::OnAverageSmooth()
{//ID_AVERAGE_SMOOTH// TODO:  在此添加命令处理程序代码// 此函数实现邻域均值平滑处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像CSmoothProcessDib Smooth(&m_PhotoImage);//创建一个CSmoothProcessDib对象         Smooth.Average_Smooth();  //调用邻域平均平滑函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}// 此函数实现邻域加权均值平滑处理
void C数字图像处理View::OnValueAvrgSmooth()
{//ID_VALUE_AVRG_SMOOTH// TODO:  在此添加命令处理程序代码// 此函数实现邻域加权均值平滑处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像CSmoothProcessDib Smooth(&m_PhotoImage);//创建一个CSmoothProcessDib对象         int Structure[3][3] = { 1, 2, 1, 2, 4, 2, 1, 2, 1 };//定义加权模板Smooth.Value_Average_Smooth(Structure); //调用邻域加权平均平滑函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}// 此函数实现选择式掩膜平滑处理
void C数字图像处理View::OnSelectSmooth()
{//ID_SELECT_SMOOTH// TODO:  在此添加命令处理程序代码// 此函数实现选择式掩膜平滑处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像CSmoothProcessDib Smooth(&m_PhotoImage);//创建一个CSmoothProcessDib对象         Smooth.Select_Smooth();  //调用选择式掩膜平滑函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}// 此函数实现中值滤波平滑处理
void C数字图像处理View::OnMiddleSmooth()
{//ID_MIDDLE_SMOOTH// TODO:  在此添加命令处理程序代码// 此函数实现中值滤波平滑处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像CSmoothProcessDib Smooth(&m_PhotoImage);//创建一个CSmoothProcessDib对象         Smooth.Middle_Smooth(); //调用中值滤波平滑函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}// 此函数实现门限梯度锐化处理
void C数字图像处理View::OnGateGrad()
{//ID_GATE_GRAD// TODO:  在此添加命令处理程序代码// 此函数实现门限梯度锐化处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像CSharpenProcessDib Sharpen(&m_PhotoImage);//创建一个CSharpenProcessDib对象BYTE t = 30;Sharpen.GateGrad(t);   //调用门限梯度锐化处理函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像     
}// 此函数实现拉普拉斯锐化处理
void C数字图像处理View::OnLaplacian()
{//ID_LAPLACIAN// TODO:  在此添加命令处理程序代码// 此函数实现拉普拉斯锐化处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);    //绘制处理前的图像CSharpenProcessDib Sharpen(&m_PhotoImage);//创建一个CSharpenProcessDib对象         Sharpen.Laplacian();   //调用拉普拉斯锐化处理函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}// 此函数实现理想低通滤波处理
void C数字图像处理View::OnPrefectLowFilter()
{//ID_PREFECT_LOW_FILTER// TODO:  在此添加命令处理程序代码// 此函数实现理想低通滤波处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);    //绘制处理前的图像CFrequencyFilterDib FrequencyFilter(&m_PhotoImage);// 创建一个CFrequencyFilterDib对象//设置截止频域分量参数int u = 152;int v = 152;FrequencyFilter.Perfect_Low_Filter(u, v); //调用理想低通滤波函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}// 此函数实现理想高通滤波处理
void C数字图像处理View::OnPrefectHighFilter()
{//ID_PREFECT_HIGH_FILTER// TODO:  在此添加命令处理程序代码// 此函数实现理想高通滤波处理//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);    //绘制处理前的图像CFrequencyFilterDib FrequencyFilter(&m_PhotoImage);// 创建一个CFrequencyFilterDib对象//设置截止频域分量参数int u = 100;int v = 100;FrequencyFilter.Perfect_High_Filter(u, v); //调用理想高通滤波函数CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}// 此函数实现伪彩色图像处理
void C数字图像处理View::OnPseudoColorEnhance()
{// 此函数实现伪彩色图像处理//ID_PSEUDO_COLOR_ENHANCE// TODO:  在此添加命令处理程序代码//如果之前没加载图像,将在这里提示if (flag == FALSE){AfxMessageBox("请先加载要处理的照片图像!");return;}CPoint point;CSize size;point.x = 0;point.y = 0;LONG lWidth = m_PhotoImage.GetWidth();    //获得灰度图像的宽度LONG lHeight = m_PhotoImage.GetHeight();  //获得灰度图像的高度size.cx = lWidth;size.cy = lHeight;CDC *pDC = GetDC();m_PhotoImage.Draw(pDC, point, size);    //绘制处理前的图像CColorEnhanceDib ColorEnhance(&m_PhotoImage);// 创建一个CColorEnhanceDib对象BYTE *bpColorsTable;// 伪彩色编码表BYTE ColorsTable[256 * 4] = {0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 15, 0, 0, 0, 23, 0, //40, 0, 31, 0, 0, 0, 39, 0, 0, 0, 47, 0, 0, 0, 55, 0, //80, 0, 63, 0, 0, 0, 71, 0, 0, 0, 79, 0, 0, 0, 87, 0, //120, 0, 85, 0, 0, 0, 103, 0, 0, 0, 111, 0, 0, 0, 119, 0, //160, 0, 127, 0, 0, 0, 135, 0, 0, 0, 143, 0, 0, 0, 151, 0, //200, 0, 159, 0, 0, 0, 167, 0, 0, 0, 175, 0, 0, 0, 183, 0, //240, 0, 191, 0, 0, 0, 199, 0, 0, 0, 207, 0, 0, 0, 215, 0, //280, 0, 223, 0, 0, 0, 231, 0, 0, 0, 239, 0, 0, 0, 247, 0, //320, 0, 255, 0, 0, 8, 255, 0, 0, 16, 255, 0, 0, 24, 255, 0, //360, 32, 255, 0, 0, 40, 255, 0, 0, 48, 255, 0, 0, 56, 255, 0, //400, 64, 255, 0, 0, 72, 255, 0, 0, 80, 255, 0, 0, 88, 255, 0, //440, 96, 255, 0, 0, 104, 255, 0, 0, 112, 255, 0, 0, 120, 255, 0, //480, 128, 255, 0, 0, 136, 255, 0, 0, 144, 255, 0, 0, 152, 255, 0, //520, 160, 255, 0, 0, 168, 255, 0, 0, 176, 255, 0, 0, 184, 255, 0, //560, 192, 255, 0, 0, 200, 255, 0, 0, 208, 255, 0, 0, 216, 255, 0, //600, 224, 255, 0, 6, 232, 255, 0, 0, 240, 255, 0, 0, 248, 255, 0, //640, 255, 255, 0, 0, 255, 247, 0, 0, 255, 239, 0, 0, 255, 231, 0, //680, 255, 223, 0, 0, 255, 215, 0, 0, 255, 207, 0, 0, 255, 199, 0, //720, 255, 191, 0, 0, 255, 183, 0, 0, 255, 175, 0, 0, 255, 167, 0, //760, 255, 159, 0, 0, 255, 151, 0, 0, 255, 143, 0, 0, 255, 135, 0, //800, 255, 127, 0, 0, 255, 119, 0, 0, 255, 111, 0, 0, 255, 103, 0, //840, 255, 95, 0, 0, 255, 87, 0, 0, 255, 79, 0, 0, 255, 71, 0, //880, 255, 63, 0, 0, 255, 55, 0, 0, 255, 47, 0, 0, 255, 39, 0, //920, 255, 31, 0, 0, 255, 23, 0, 0, 255, 15, 0, 0, 255, 7, 0, //960, 255, 0, 0, 8, 255, 0, 0, 16, 255, 0, 0, 24, 255, 0, 0, //10032, 255, 0, 0, 40, 255, 0, 0, 48, 255, 0, 0, 56, 255, 0, 0, //10464, 255, 0, 0, 72, 255, 0, 0, 80, 255, 0, 0, 88, 255, 0, 0, //10896, 255, 0, 0, 104, 255, 0, 0, 112, 255, 0, 0, 120, 255, 0, 0, //112128, 255, 0, 0, 136, 255, 0, 0, 144, 255, 0, 0, 152, 255, 0, 0, //116160, 255, 0, 0, 168, 255, 0, 0, 176, 255, 0, 0, 184, 255, 0, 0, //120192, 255, 0, 0, 200, 255, 0, 0, 208, 255, 0, 0, 216, 255, 0, 0, //124224, 255, 0, 0, 232, 255, 0, 0, 240, 255, 0, 0, 248, 255, 0, 0, //128255, 255, 0, 0, 255, 251, 0, 0, 255, 247, 0, 0, 255, 243, 0, 0, //132255, 239, 0, 0, 255, 235, 0, 0, 255, 231, 0, 0, 255, 227, 0, 0, //136255, 223, 0, 0, 255, 219, 0, 0, 255, 215, 0, 0, 255, 211, 0, 0, //140255, 207, 0, 0, 255, 203, 0, 0, 255, 199, 0, 0, 255, 195, 0, 0, //144255, 191, 0, 0, 255, 187, 0, 0, 255, 183, 0, 0, 255, 179, 0, 0, //148255, 175, 0, 0, 255, 171, 0, 0, 255, 167, 0, 0, 255, 163, 0, 0, //152255, 159, 0, 0, 255, 155, 0, 0, 255, 151, 0, 0, 255, 147, 0, 0, //156255, 143, 0, 0, 255, 139, 0, 0, 255, 135, 0, 0, 255, 131, 0, 0, //160255, 127, 0, 0, 255, 123, 0, 0, 255, 119, 0, 0, 255, 115, 0, 0, //164255, 111, 0, 0, 255, 107, 0, 0, 255, 103, 0, 0, 255, 99, 0, 0, //168255, 95, 0, 0, 255, 91, 0, 0, 255, 87, 0, 0, 255, 83, 0, 0, //172255, 79, 0, 0, 255, 75, 0, 0, 255, 71, 0, 0, 255, 67, 0, 0, //176255, 63, 0, 0, 255, 59, 0, 0, 255, 55, 0, 0, 255, 51, 0, 0, //180255, 47, 0, 0, 255, 43, 0, 0, 255, 39, 0, 0, 255, 35, 0, 0, //184255, 31, 0, 0, 255, 27, 0, 0, 255, 23, 0, 0, 255, 19, 0, 0, //188255, 15, 0, 0, 255, 11, 0, 0, 255, 7, 0, 0, 255, 3, 0, 0, //192255, 0, 0, 0, 255, 4, 4, 0, 255, 8, 8, 0, 255, 12, 12, 0, //196255, 16, 16, 0, 255, 20, 20, 0, 255, 24, 24, 0, 255, 28, 28, 0, //200255, 32, 32, 0, 255, 36, 36, 0, 255, 40, 40, 0, 255, 44, 44, 0, //204255, 48, 48, 0, 255, 52, 52, 0, 255, 56, 56, 0, 255, 60, 60, 0, //208255, 64, 64, 0, 255, 68, 68, 0, 255, 72, 72, 0, 255, 76, 76, 0, //212255, 80, 80, 0, 255, 84, 84, 0, 255, 88, 88, 0, 255, 92, 92, 0, //216255, 96, 96, 0, 255, 100, 100, 0, 255, 104, 104, 0, 255, 108, 108, 0, //220255, 112, 112, 0, 255, 116, 116, 0, 255, 120, 120, 0, 255, 124, 124, 0, //224255, 128, 128, 0, 255, 132, 132, 0, 255, 136, 136, 0, 255, 140, 140, 0, //228255, 144, 144, 0, 255, 148, 148, 0, 255, 152, 152, 0, 255, 156, 156, 0, //232255, 160, 160, 0, 255, 164, 164, 0, 255, 168, 168, 0, 255, 172, 172, 0, //236255, 176, 176, 0, 255, 180, 180, 0, 255, 184, 184, 0, 255, 188, 188, 0, //240255, 192, 192, 0, 255, 196, 196, 0, 255, 200, 200, 0, 255, 204, 204, 0, //244255, 208, 208, 0, 255, 212, 212, 0, 255, 216, 216, 0, 255, 220, 220, 0, //248255, 224, 224, 0, 255, 228, 228, 0, 255, 232, 232, 0, 255, 236, 236, 0, //252255, 240, 240, 0, 255, 244, 244, 0, 255, 248, 248, 0, 255, 252, 252, 0   //256};bpColorsTable = ColorsTable;ColorEnhance.Pseudo_Color_Enhance(bpColorsTable);CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/876584.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

甄选范文“论软件测试中缺陷管理及其应用”软考高级论文,系统架构设计师论文

论文真题 软件缺陷指的是计算机软件或程序中存在的某种破坏正常运行能力的问题、错误,或者隐藏的功能缺陷。缺陷的存在会导致软件产品在某种程度上不能满足用户的需要。在目前的软件开发过程中,缺陷是不可避免的。软件测试是发现缺陷的主要手段,其核心目标就是尽可能多地找…

Bouncy Castle实现SM2

Bouncy Castle 是一个广泛使用的开源加密库&#xff0c;它为Java平台提供了丰富的密码学算法实现&#xff0c;包括对称加密、非对称加密、哈希算法、数字签名等。在Bouncy Castle中&#xff0c;SM2作为一种非对称加密算法也得到了支持。 SM2算法简介 SM2是一种由中国国家密码…

动手学深度学习55 循环神经网络 RNN 的实现

动手学深度学习55 循环神经网络 RNN 的实现 从零开始实现简洁实现QA 课件&#xff1a;https://zh-v2.d2l.ai/chapter_recurrent-neural-networks/rnn-scratch.html 从零开始实现 %matplotlib inline import math import torch from torch import nn from torch.nn import fun…

数据结构篇

7.查找 查找效率 顺序查找&#xff0c;折半查找和分块查找 折半查找 分块查找 二插排序树 删除操作 二叉排序树前驱&#xff1a;从该节点向左&#xff0c;一路找到他的最右节点&#xff1b; 二叉排序树后继&#xff1a;从该节点向右&#xff0c;一路找到他的最左节点&#x…

1. Vue3入门

文章目录 使用create-vue创建项目关键文件<script setup>语法糖组合式API - reactive和ref函数组合式API - computed组合式API - watch组合式API - 生命周期函数组合式API - 父子通信组合式API - 模版引用组合式API - provide和inject综合案例 使用create-vue创建项目 n…

DataX 本地调试配置

简要说明 根据自己的开发需求&#xff0c;完成了reader、writer、transformer开发后&#xff0c;在ide内通过Engine入口&#xff0c;调试自己的插件和job的json。 前置条件 已在系统安装了datax&#xff0c;本例子是在windows环境下&#xff0c;安装包地址https://github.co…

<数据集>玉米地杂草识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;9900张 标注数量(xml文件个数)&#xff1a;9900 标注数量(txt文件个数)&#xff1a;9900 标注类别数&#xff1a;2 标注类别名称&#xff1a;[Maize, Weed] 序号类别名称图片数框数1Maize8439125142Weed959231048…

【Linux网络】应用层协议:HTTP 与 HTTPS

本篇博客整理了 TCP/IP 分层模型中应用层的 HTTP 协议和 HTTPS协议&#xff0c;旨在让读者更加深入理解网络协议栈的设计和网络编程。 目录 一、协议是什么 1&#xff09;结构化数据的传输 2&#xff09;序列化和反序列化 补&#xff09;网络版计算器 .1- 协议定制 .2- …

CSS(三)——CSS 背景

CSS 背景 CSS 背景属性用于定义HTML元素的背景。 CSS 背景属性 Property描述background简写属性&#xff0c;作用是将背景属性设置在一个声明中。background-attachment背景图像是否固定或者随着页面的其余部分滚动。background-color设置元素的背景颜色。background-image把…

数据结构系列-插入排序和希尔排序

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 排序的概念 常见的排序算法&#xff1a; 插入排序 直接插入排序是一种简单的插入排序法&#xff0c;其基本思想是&#xff1a; 把待排序的记录按其关键码值的大小逐个插入到…

API 技术开发分享:连接电商平台数据获取的桥梁

在当今数字化的时代&#xff0c;API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;技术成为了实现不同系统之间通信和数据交换的关键。它就像是一座无形的桥梁&#xff0c;使得各种应用能够相互协作&#xff0c;共享资源&#xff0c;…

react.16+

1、函数式组件 在vite脚手架中执行&#xff1a; app.jsx: import { useState } from react import reactLogo from ./assets/react.svg import viteLogo from /vite.svg import ./App.cssfunction App() {console.log(this)return <h2>我是函数式组件</h2> }exp…

请你谈谈:vue的渲染机制(render)- 1 原理讲解

Vue 是如何将一份模板转换为真实的 DOM 节点的&#xff0c;又是如何高效地更新这些节点的呢&#xff1f;我们接下来就将尝试通过深入研究 Vue 的内部渲染机制来解释这些问题。 1 虚拟 DOM <template><div id"app">this is son component</div> &…

《javaEE篇》--阻塞队列详解

阻塞队列 阻塞队列概述 阻塞队列也是一种队列&#xff0c;和普通队列一样遵循先进先出的原则&#xff0c;但是阻塞队列相较于普通队列多了两项功能阻塞添加和阻塞移除&#xff0c;使得阻塞队列成为一种线程安全的数据结构 阻塞添加&#xff1a;当队列满的时候继续入队就会阻…

UE4 UnrealPak加密功能(配置AES encrypt key)

本文的重点在于如何使用UnrealPak的加密功能&#xff0c;以及相关的UE4源代码学习。本文参考了&#xff1a;https://www.cnblogs.com/shiroe/p/14803859.html 。 设置密钥 在编辑、项目设置中找到下面栏目&#xff0c;并点击“生成新的加密密钥”&#xff0c;就可以为Unreal P…

unity2D游戏开发10生命条脚本

HitPoints 在ScriptableObjects文件夹中创建新的脚本,叫HitPoint using System.Collections; using System.Collections.Generic; using UnityEngine;//创建条目,方便轻松创建HitPoints的实例 [CreateAssetMenu(menuName ="HitPoints")] public class HitPoints :…

锅总介绍CNCF主要目标、全景图及发展历史

一、CNCF简介 云原生计算基金会&#xff08;Cloud Native Computing Foundation&#xff0c;简称 CNCF&#xff09;是一个成立于 2015 年的非营利性组织&#xff0c;隶属于 Linux 基金会。CNCF 的主要目标是通过开源软件推动云原生计算技术的发展和普及&#xff0c;帮助企业更…

四、使用renren-generator生成基本代码

1、打开generator.properties配置文件&#xff0c;修改配置 主要修改包名、模块名、前缀信息 2、修改application.yml配置文件中的数据库信息 3、启动项目 直接访问代码生成器 http://localhost/#generator选择表&#xff0c;点击生成代码即可

怎么使用github上传XXX内所有文件

要将 目录中的所有文件上传到 GitHub&#xff0c;你可以按照以下步骤进行&#xff1a; 创建一个新的 GitHub 仓库 登录到你的 GitHub 账户。 点击右上角的加号&#xff08;&#xff09;&#xff0c;选择 “New repository”。 输入仓库名称&#xff08;例如&#xff1a;202407…

滑动窗口练习6-找到字符串中所有字母异位词

题目链接&#xff1a;**. - 力扣&#xff08;LeetCode&#xff09;** 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#…