当前位置: 首页 > news >正文

基于单文档的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();afx_msg void OnMirror();afx_msg void On32791();
};#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"function.h"//注意 此头文件所放位置#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)ON_COMMAND(ID_MIRROR, &C数字图像处理View::OnMirror)ON_COMMAND(32791, &C数字图像处理View::On32791)
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);//绘制处理后的图像
}//水平镜像
void C数字图像处理View::OnMirror()
{// TODO:  在此添加命令处理程序代码// TODO:  在此添加命令处理程序代码C数字图像处理Doc* pDoc = GetDocument();						// 获取文档//https://www.cnblogs.com/marshhu/archive/2013/04/09/3009567.html#:~:text=%E5%9C%A8%E8%A7%86%E5%9B%BE%E7%B1%BBCDrawView%E7%9A%84%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E4%B8%AD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E4%BB%A5%E4%B8%8B%E4%BB%A3%E7%A0%81%E8%B0%83%E7%94%A8GetDocument%20%28%29%E5%87%BD%E6%95%B0%E4%BB%A5%E5%BE%97%E5%88%B0%E5%BD%93%E5%89%8D%E6%96%87%E6%A1%A3%E7%B1%BB%E5%AF%B9%E8%B1%A1%E6%8C%87%E9%92%88%E3%80%82%20CDrawDoc%2A%20pDoc%20%3D,GetDocument%20%28%29%3B%20ASSERT_VALID%20%28pDoc%29%3B%20%E5%BE%97%E5%88%B0%E6%8C%87%E5%90%91%E5%BD%93%E5%89%8D%E6%96%87%E6%A1%A3%E7%B1%BB%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%8C%87%E9%92%88pDoc%E5%90%8E%EF%BC%8C%E4%B8%8E%E4%BD%BF%E7%94%A8%E6%99%AE%E9%80%9A%E7%9A%84C%2B%2B%E7%B1%BB%E7%9A%84%E6%8C%87%E9%92%88%E4%B8%80%E6%A0%B7%EF%BC%8C%E5%8F%AF%E4%BB%A5%E8%B0%83%E7%94%A8%E6%96%87%E6%A1%A3%E7%B1%BB%E7%9A%84%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%E5%92%8C%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%20%28%E5%8F%AA%E8%83%BD%E8%B0%83%E7%94%A8%E5%85%B1%E6%9C%89%E5%9E%8B%E7%9A%84%29%E3%80%82//如果之前没加载图像,将在这里提示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);    //绘制处理前的图像/*************************************/long lSrcLineBytes;		//图像每行的字节数long	lSrcWidth;      //图像的宽度和高度long	lSrcHeight;LPSTR	lpSrcDib;		//指向源图像的指针	LPSTR	lpSrcStartBits;	//指向源像素的指针//lpSrcDib = (LPSTR) ::GlobalLock((HGLOBAL)pDoc->GetHObject());// 锁定DIB//https://zhidao.baidu.com/question/277781947.html//if (pDoc->m_dib.GetColorNum(lpSrcDib) != 256)// 判断是否是8-bpp位图//{//	AfxMessageBox(_T("对不起,不是256色位图!"));// 警告				//	::GlobalUnlock((HGLOBAL)pDoc->GetHObject());// 解除锁定		//	return;									//返回//}											//判断是否是8-bpp位图,不是则返回if (m_PhotoImage.GetNumOfColor() != 256)//判断是否是8-bpp位图,不是则返回{AfxMessageBox(_T("对不起,不是256色位图!"));// 警告return;									//返回}lpSrcStartBits = (LPSTR)m_PhotoImage.GetData();//lpSrcStartBits = pDoc->m_dib.GetBits(lpSrcDib);			// 找到DIB图像像素起始位置//lSrcWidth = pDoc->m_dib.GetWidth(lpSrcDib);					// 获取图像的宽度lSrcWidth = m_PhotoImage.GetWidth();//lSrcHeight = pDoc->m_dib.GetHeight(lpSrcDib);					// 获取图像的高度lSrcHeight = m_PhotoImage.GetHeight();//lSrcLineBytes = pDoc->m_dib.GetReqByteWidth(lSrcWidth * 8);		// 计算图像每行的字节数lSrcLineBytes = m_PhotoImage.GetReqByteWidth(lSrcWidth * 8);/if (Mirror(lpSrcStartBits, lSrcWidth, lSrcHeight, lSrcLineBytes))// 调用Mirror()函数水平镜像DIB{pDoc->SetModifiedFlag(TRUE);								// 设置脏标记		//pDoc->UpdateAllViews(NULL);									// 更新视图		//::GlobalUnlock((HGLOBAL)pDoc->GetHObject());					// 解除锁定}else{AfxMessageBox(_T("分配内存失败!"));return;}// 警告/*************************************/CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像/*************************************///lpSrcDib = NULL;//lpSrcStartBits = NULL;
}//竖直镜像
void C数字图像处理View::On32791()
{// TODO:  在此添加命令处理程序代码//C数字图像处理Doc* pDoc = GetDocument();						// 获取文档//https://www.cnblogs.com/marshhu/archive/2013/04/09/3009567.html#:~:text=%E5%9C%A8%E8%A7%86%E5%9B%BE%E7%B1%BBCDrawView%E7%9A%84%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E4%B8%AD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87%E4%BB%A5%E4%B8%8B%E4%BB%A3%E7%A0%81%E8%B0%83%E7%94%A8GetDocument%20%28%29%E5%87%BD%E6%95%B0%E4%BB%A5%E5%BE%97%E5%88%B0%E5%BD%93%E5%89%8D%E6%96%87%E6%A1%A3%E7%B1%BB%E5%AF%B9%E8%B1%A1%E6%8C%87%E9%92%88%E3%80%82%20CDrawDoc%2A%20pDoc%20%3D,GetDocument%20%28%29%3B%20ASSERT_VALID%20%28pDoc%29%3B%20%E5%BE%97%E5%88%B0%E6%8C%87%E5%90%91%E5%BD%93%E5%89%8D%E6%96%87%E6%A1%A3%E7%B1%BB%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%8C%87%E9%92%88pDoc%E5%90%8E%EF%BC%8C%E4%B8%8E%E4%BD%BF%E7%94%A8%E6%99%AE%E9%80%9A%E7%9A%84C%2B%2B%E7%B1%BB%E7%9A%84%E6%8C%87%E9%92%88%E4%B8%80%E6%A0%B7%EF%BC%8C%E5%8F%AF%E4%BB%A5%E8%B0%83%E7%94%A8%E6%96%87%E6%A1%A3%E7%B1%BB%E7%9A%84%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%E5%92%8C%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%20%28%E5%8F%AA%E8%83%BD%E8%B0%83%E7%94%A8%E5%85%B1%E6%9C%89%E5%9E%8B%E7%9A%84%29%E3%80%82//如果之前没加载图像,将在这里提示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);    //绘制处理前的图像/*************************************/long lSrcLineBytes;		//图像每行的字节数long	lSrcWidth;      //图像的宽度和高度long	lSrcHeight;LPSTR	lpSrcDib;		//指向源图像的指针	LPSTR	lpSrcStartBits;	//指向源像素的指针//lpSrcDib = (LPSTR) ::GlobalLock((HGLOBAL)pDoc->GetHObject());// 锁定DIB//if (pDoc->m_dib.GetColorNum(lpSrcDib) != 256)// 判断是否是8-bpp位图//{//	AfxMessageBox(_T("对不起,不是256色位图!"));// 警告				//	::GlobalUnlock((HGLOBAL)pDoc->GetHObject());// 解除锁定		//	return;									//返回//}											//判断是否是8-bpp位图,不是则返回if (m_PhotoImage.GetNumOfColor() != 256)//判断是否是8-bpp位图,不是则返回{AfxMessageBox(_T("对不起,不是256色位图!"));// 警告//	::GlobalUnlock((HGLOBAL)pDoc->GetHObject());// 解除锁定	return;									//返回}//lpSrcStartBits = pDoc->m_dib.GetBits(lpSrcDib);			// 找到DIB图像像素起始位置	//lSrcWidth = pDoc->m_dib.GetWidth(lpSrcDib);					// 获取图像的宽度		//lSrcHeight = pDoc->m_dib.GetHeight(lpSrcDib);					// 获取图像的高度		//lSrcLineBytes = pDoc->m_dib.GetReqByteWidth(lSrcWidth * 8);		// 计算图像每行的字节数lpSrcStartBits = (LPSTR)m_PhotoImage.GetData();//lpSrcStartBits = pDoc->m_dib.GetBits(lpSrcDib);			// 找到DIB图像像素起始位置//lSrcWidth = pDoc->m_dib.GetWidth(lpSrcDib);					// 获取图像的宽度lSrcWidth = m_PhotoImage.GetWidth();//lSrcHeight = pDoc->m_dib.GetHeight(lpSrcDib);					// 获取图像的高度lSrcHeight = m_PhotoImage.GetHeight();//lSrcLineBytes = pDoc->m_dib.GetReqByteWidth(lSrcWidth * 8);		// 计算图像每行的字节数lSrcLineBytes = m_PhotoImage.GetReqByteWidth(lSrcWidth * 8);/if (Mirror2(lpSrcStartBits, lSrcWidth, lSrcHeight, lSrcLineBytes))// 调用Mirror2()函数水平镜像DIB{//pDoc->SetModifiedFlag(TRUE);								// 设置脏标记		//pDoc->UpdateAllViews(NULL);									// 更新视图		//	::GlobalUnlock((HGLOBAL)pDoc->GetHObject());					// 解除锁定}else{AfxMessageBox(_T("分配内存失败!"));return;}// 警告//Mirror2(lpSrcStartBits, lSrcWidth, lSrcHeight, lSrcLineBytes);/*************************************/CPoint point1;point1.x = lWidth + 20;  //+20是为了让两个图像显示时有个间隙point1.y = 0;m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像/*************************************/
}

相关文章:

基于单文档的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 Sm…...

云计算实训13——DNS域名解析、ntp时间服务器配置、主从DNS配置、多区域DNS搭建

一、DNS域名解析 1.正向解析 将域名解析为IP地址 DNS正向解析核心配置 (1)安装bind [rootdns ~]# yum -y install bind (2)编辑配置文件 编辑named.conf文件&#xff0c;限定访问权限 [rootdns ~]# vim /etc/named.conf 编辑named.rfc文件&#xff0c;指定要访问的域名 [ro…...

【C#】Visual Studio2022打包依赖第三方库的winForm程序为exe

0.简介 IDE&#xff1a;VS2022 平台&#xff1a;C# .NetFramework4.7.2 WinForm界面 有GDAL、EEplus第三方库的依赖&#xff0c;所以在其他未安装环境的电脑中功能无法使用。 1. 安装 1.1 运行文件输出 在VS扩展中选择管理扩展&#xff0c;安装&#xff1a;Microsoft Visua…...

《算法笔记》总结No.11——数字处理(上)欧拉筛选

机试中存在部分涉及到较复杂数字的问题&#xff0c;这是编码的基本功&#xff0c;各位一定要得心应手。 目录 一.最大公约数和最小公倍数 1.最大公约数 2.最小公倍数 二.素数 1.判断指定数 2.输出所有素数 3.精进不休——埃拉托斯特尼筛法 4.达到更优&#xff01;——…...

DP学习——享元模式

学而时习之&#xff0c;温故而知新。 享元模式 名词解析 有必要解释下“享元”两字&#xff0c;英文原文是flyweight pattern——轻量级模式&#xff0c;但是翻译过来的“享元”两字太牛逼了——褒贬不一&#xff0c;翻译的他妈都不认识。 享元的高雅在于: 享:共享/共用 元:…...

无人机10公里WiFi图传摄像模组,飞睿智能超清远距离无线监控,智能安防新潮流

在这个科技日新月异的时代&#xff0c;我们对影像的捕捉和传播有了更高的要求。从传统的有线传输到无线WiFi图传&#xff0c;每一次技术的飞跃都为我们带来了全新的视觉体验。今天&#xff0c;我们要探讨的&#xff0c;正是一款具有划时代意义的科技产品——飞睿智能10公里WiFi…...

SAP S/4HANA Cloud Public Edition

即装即用的云ERP软件。借助SaaS模式为企业提供完备、现代化的ERP 云套件&#xff0c;为企业带来新的技术突破&#xff0c;如自动化的业务流程与基于数据的商业分析。企业可选择这款智能云ERP软件&#xff0c;快速实现自身价值。 什么是 SAP S/4HANA Cloud Public Edition&#…...

LabVIEW汽车动态信号模拟系统

随着汽车工业的快速发展&#xff0c;对汽车电子控制单元&#xff08;ECU&#xff09;的测试与仿真需求日益增加。开发了一种基于LabVIEW软件开发的汽车动态信号模拟系统&#xff0c;该系统能有效模拟ECU在实车环境下的工作状态&#xff0c;为ECU的开发和测试提供了一个高效、经…...

chrome 插件:content-script 部分逻辑在页面无法生效,可考虑插入 script 到页面上

背景: 某页面有个输入框, 用的应该是什么库里的组件, 直接修改内容不生效/机制不明确, 于是使用 paste event 粘贴到输入框, 结果发现也不行 定位: 使用 mutationObserver , 发现事件确实触发了, 输入框内容变了, 但马上又变回来了, 于是怀疑是输入框组件有做 mutationObers…...

【前端 10】初探BOM

初探BOM&#xff1a;浏览器对象模型 在JavaScript的广阔世界中&#xff0c;BOM&#xff08;Browser Object Model&#xff0c;浏览器对象模型&#xff09;扮演着举足轻重的角色。它为我们提供了一套操作浏览器窗口及其组成部分的接口&#xff0c;让我们能够通过编写JavaScript…...

PostgreSQL入门与进阶学习,体系化的SQL知识,完成终极目标高可用与容灾,性能优化与架构设计,以及安全策略

​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 文章目录 概述基础篇初级篇进阶篇…...

ODBC+FreeTDS从Linux访问Windows SqlServer数据库

提示 \color{red}{提示} 提示&#xff1a; 《Linux系统上编译安装FreeTDS库文件》中讲述了如何编译FreeTDS源码&#xff0c;并安装。 本文部分内容会在上述文章的基础上深入。 本文内容所使用的环境 Windows系统&#xff1a;Windows 10 企业版 64位操作系统&#xff1b;IP&a…...

Chainlit一个快速构建成式AI应用的Python框架,无缝集成与多平台部署

概述 Chainlit 是一个开源 Python 包&#xff0c;用于构建和部署生成式 AI 应用的开源框架。它提供了一种简单的方法来创建交互式的用户界面&#xff0c;这些界面可以与 LLM&#xff08;大型语言模型&#xff09;驱动的应用程序进行通信。Chainlit 旨在帮助开发者快速构建基于…...

leetcode日记(51)不同路径Ⅱ

和上一道题&#xff08;无障碍物的最短路径&#xff09;很像&#xff0c;但事实上比上一题多了优化方法 根据上一题改的代码如下&#xff0c;添加了对障碍物的判定&#xff0c;如果有障碍物则将数组值设为0。 class Solution { public:int uniquePathsWithObstacles(vector&l…...

图解分布式事务中的2PC与Seata方案

文章目录 文章导图什么是2PC解决传统2PC方案XA方案DTP模型举例&#xff1a;新用户注册送积分总结&#xff1a; Seata方案设计思想执行流程举例&#xff1a;新用户注册送积分 Seata实现2PC事务&#xff08;AT模式&#xff09;前提整体机制写隔离读隔离实际案例理解要点说明核心代…...

数据结构(Java):Map集合Set集合哈希表

目录 1、介绍 1.1 Map和Set 1.2 模型 2、Map集合 2.1 Map集合说明 2.2 Map.Entry<K&#xff0c;V> 2.3 Map常用方法 2.4 Map注意事项及实现类 3、Set集合 3.1 Set集合说明 3.2 Set常用方法 3.3 Set注意事项及其实现类 4、TreeMap&TreeSet 4.1 集合类TreeM…...

网络战时代的国家安全:策略、技术和国际合作

网络战时代的国家安全涉及到策略、技术和国际合作等多个方面。以下是对这些问题的简要概述&#xff1a; 网络战策略 网络战策略是指在现代战争中&#xff0c;通过网络技术进行的信息收集、处理、分析、调度和指挥等一系列行动&#xff0c;旨在同时影响和干扰对方的网络系统&am…...

【elasticsearch实现优先展示连词并按某个字段折叠显示最新一条】

elasticsearch实现优先展示连词并按某个字段折叠显示最新一条 前言match_phrase 顺序前缀 boost 权重collapse 折叠基本用法高级功能排序 前言 场景要求&#xff1a; 优先展示关键词连词的商品按照某个字段折叠相同字段&#xff0c;并按指定排序字段选择第一个 match_phras…...

Golang | Leetcode Golang题解之第284题窥视迭代器

题目&#xff1a; 题解&#xff1a; type PeekingIterator struct {iter *Iterator_hasNext bool_next int }func Constructor(iter *Iterator) *PeekingIterator {return &PeekingIterator{iter, iter.hasNext(), iter.next()} }func (it *PeekingIterator) hasNe…...

C语言中的结构体

文章目录 前言一、结构体是什么&#xff1f;二、结构体的定义三、结构体的初始化四、结构体的嵌套五、结构体数组 1结构体数组的定义&#xff1a;六、结构体指针 一、结构体是什么&#xff1f; 我们知道一群类型相同的数据组合到一起是数组&#xff0c;那一群不同类型的数据组…...

3.qml与c++模块化开发

目录 模块化开发封装c模块并使用封装qml模块并使用 模块化开发 什么是模块化开发呢&#xff1f; 举个例子&#xff1a; 我们有一台台式电脑&#xff0c;我们台式电脑有显卡&#xff0c;内存&#xff0c;磁盘&#xff0c;cpu&#xff0c;键盘&#xff0c;鼠标等 你可以将这些部…...

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

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

合作伙伴中心Partner Center中添加了Copilot预览版

目录 一、引言 二、Copilot 功能概述 2.1 Copilot 简介 2.2 Copilot 的核心功能 2.3 Copilot 的访问和使用 三、Copilot 的使用方法 3.1 Copilot 功能区域 3.2 Copilot 使用示例 3.2.1 编写有效提示 3.2.2 使用反馈循环 四、负责任的人工智能 4.1 Copilot 结果的可…...

Navidrome音乐服务器 + 音流APP = 释放你的手机空间

20240727 By wdhuag 目录 前言&#xff1a; 参考&#xff1a; Navidrome音乐服务器 Demo试用&#xff1a; 支持多平台&#xff1a; 下载&#xff1a; 修改配置&#xff1a; 设置用NSSM成服务启动&#xff1a; 服务器本地访问网址&#xff1a; 音流 歌词封面API&am…...

Prometheus安装部署

文章目录 1.Prometheus(普罗米修斯)安装部署1.1部署环境准备1.2部署prometheus1.3主机数据展示 2.Grafana安装部署2.1部署Grafana2.2配置Grafana数据源2.2配置Grafana仪表板 3.AlertManager安装部署3.1部署alertmanager3.2告警邮件发送配置3.3测试邮件告警效果3.4自定义邮件告警…...

算法(查找算法---二分查找/索引查找/哈希表查找)

二、查找算法 什么是查找算法&#xff1a; 在一个数据序列中&#xff0c;查找某个数据是否存在或存在的位置&#xff0c;在实际开发过程中使用的频率非常高&#xff0c;例如对数据常见的操作有增、删、改、查&#xff0c;增加数据时需要查询新增加的数据是否重复&#xff0c;…...

SQL labs-SQL注入(二)

环境搭建参考 SQL注入&#xff08;一&#xff09; 一&#xff0c;SQL labs-less2。 http://192.168.61.206:8001/Less-2/?id-1 union select 1,2,group_concat(username , password) from users-- 与第一关没什么太大的不同&#xff0c;唯一区别就是闭合方式为数字型。 二…...

go 语言踏出第一步

1、下载Go语言安装包&#xff1a;在官方网站&#xff08;https://golang.org/dl/&#xff09;上下载适合你操作系统的Go语言安装包。选择一个tar.gz格式的包。 2、解压安装包&#xff1a;打开终端&#xff0c;进入下载目录&#xff0c;并使用以下命令解压安装包&#xff1a; ta…...

SpringBoot-21 SpringBoot微服务的发布与部署(3种方式)

基于 SpringBoot 的微服务开发完成之后&#xff0c;现在到了把它们发布并部署到相应的环境去运行的时候了。 SpringBoot 框架只提供了一套基于可执行 jar 包&#xff08;executable jar&#xff09;格式的标准发布形式&#xff0c;但并没有对部署做过多的界定&#xff0c;而且为…...

在occluded Person Re-ID中,选择clip还是ViT作为backbone?

在遮挡行人再识别&#xff08;Occluded Person Re-Identification, Occluded Person Re-ID&#xff09;任务中&#xff0c;使用CLIP&#xff08;Contrastive Language-Image Pre-Training&#xff09;作为backbone和使用Vision Transformer&#xff08;ViT&#xff09;作为back…...

Linuxnat网络配置

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ☁️运维工程师的职责&#xff1a;监…...

77.WEB渗透测试-信息收集-框架组件识别利用(1)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;76.WEB渗透测试-信息收集- WAF、框架组件识别&#xff08;16&#xff09; java&#xff…...

ExcelJS:轻松实现Excel文件的读取、操作与写入

文章目录 发现宝藏1. 简介2. 安装3. 创建工作簿4. 设置工作簿属性5. 添加工作表6.删除工作表7.访问工作表8. 列操作9. 行操作10. 单元格操作 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【宝…...

Java 多线程技术详解

文章目录 Java 多线程技术详解目录引言多线程的概念为什么使用多线程&#xff1f;多线程的特征多线程的挑战 多线程的实现方式3.1 继承 Thread 类示例代码&#xff1a; 3.2 实现 Runnable 接口示例代码&#xff1a; 3.3 使用 Executor 框架示例代码&#xff1a; 3.4 使用 Calla…...

一份简单实用的MATLAB M语言编码风格指南

MATLAB M语言编码风格指南 1. 文件命名2. 函数命名3. 注释4. 变量命名5. 布局、注释和文档6. 代码结构7. 错误处理8. 性能优化9. 格式化输出 MATLAB M文件的编码规范对于确保代码的可读性、可维护性和一致性非常重要。下面是一份MATLAB M语言编码规范的建议&#xff0c;可以作为…...

ubuntu 环境下soc 使用qemu

构建vexpress-a9的linux内核 安装依赖的软件 sudo apt install u-boot-tools sudo apt install gcc-arm-linux-gnueabi sudo apt install g-arm-linux-gnueabi sudo apt install gcc#编译内核 下载 linux-5.10.14 linux-5.10.148.tar.gz 配置 sudo tar -xvf linux-5.10.1…...

Centos安装、迁移gitlab

Centos安装迁移gitlab 一、下载安装二、配置rb修改&#xff0c;起服务。三、访问web&#xff0c;个人偏好设置。四、数据迁移1、查看当前GitLab版本2、备份旧服务器的文件3、将上述备份文件拷贝到新服务器同一目录下&#xff0c;恢复GitLab4、停止新gitlab数据连接服务5、恢复备…...

【Python机器学习】朴素贝叶斯——使用Python进行文本分类

目录 准备文本&#xff1a;从文本中构建词向量 训练算法&#xff1a;从词向量计算概率 测试算法&#xff1a;根据现实情况修改分类器 准备数据&#xff1a;文档词袋模型 要从文本中获取特征&#xff0c;需要先拆分文本。这里的特征是来自文本的词条&#xff0c;一个词条是字…...

【linux】Shell脚本三剑客之grep和egrep命令的详细用法攻略

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…...

Spring条件装配:灵活配置你的应用

文章目录 摘要1. 条件装配概述1.1 什么是条件装配1.2 为什么需要条件装配 2. 使用Conditional注解2.1 Conditional注解简介2.2 编写自定义条件类2.3 应用Conditional注解 3. 内置的条件注解3.1 ConditionalOnClass3.2 ConditionalOnMissingBean3.3 ConditionalOnProperty 4. 使…...

【前端 08】简单学习js字符串

JavaScript中的String对象详解 在JavaScript中&#xff0c;字符串&#xff08;String&#xff09;是一种非常基础且常用的数据类型&#xff0c;用于表示文本数据。虽然JavaScript中的字符串是原始数据类型&#xff0c;但它们的行为类似于对象&#xff0c;因为JavaScript为字符…...

【LLM】-07-提示工程-聊天机器人

目录 1、给定身份 1.1、基础代码 1.2、聊天机器人 2、构建上下文 3、订餐机器人 3.1、窗口可视化 3.2、构建机器人 3.3、创建JSON摘要 利用会话形式&#xff0c;与具有个性化特性&#xff08;或专门为特定任务或行为设计&#xff09;的聊天机器人进行深度对话。 在 Ch…...

AvaloniaUI的学习

相关网站 github:https://github.com/AvaloniaUI/Avalonia 官方中文文档&#xff1a;https://docs.avaloniaui.net/zh-Hans/docs/welcome IDE选择 VS2022VSCodeRider 以上三种我都尝试过&#xff0c;体验Rider最好。VS2022的提示功能不好&#xff0c;VSCode太慢&#xff0c…...

刷题——快速排序

【全网最清晰快速排序&#xff0c;看完快排思想和代码全部通透&#xff0c;不通透你打我&#xff01;-哔哩哔哩】 https://b23.tv/8GxEKIk 代码详解如上 #include <iostream> using namespace std;int getPort(int* a, int low, int high) {int port a[low];while(low…...

VPN,实时数据显示,多线程,pip,venv

VPN和翻墙在本质上是不同的。想要真正实现翻墙&#xff0c;需要选择部署在墙外的VPN服务。VPN也能隐藏用户的真实IP地址 要实现Python对网页数据的定时实时采集和输出&#xff0c;可以使用Python的定时任务调度模块。其中一个常用的库是APScheduler。您可以编写一个函数&#…...

自然语言处理(NLP)

自然语言处理&#xff08;NLP&#xff09;是计算机科学与人工智能领域的一个重要研究方向&#xff0c;它致力于让计算机能够理解、分析、处理和生成人类语言。在NLP领域&#xff0c;存在着许多常见的任务&#xff0c;这些任务通常对应着不同的算法和技术。以下将详细列举几个NL…...

Spring Boot集成Spire.doc实现对word的操作

1.什么是spire.doc? Spire.Doc for Java 是一款专业的 Java Word 组件&#xff0c;开发人员使用它可以轻松地将 Word 文档创建、读取、编辑、转换和打印等功能集成到自己的 Java 应用程序中。作为一款完全独立的组件&#xff0c;Spire.Doc for Java 的运行环境无需安装 Micro…...

在Spring Boot中优化if-else语句

在Spring Boot中&#xff0c;优化if-else语句是提升代码质量、增强可读性和可维护性的重要手段。过多的if-else语句不仅会使代码变得复杂难懂&#xff0c;还可能导致代码难以扩展和维护。以下将介绍七种在Spring Boot中优化if-else语句的实战方法&#xff0c;每种方法都将结合示…...

【Django】开源前端库bootstrap,常用

文章目录 下载bootstrap源文件到本地项目引入bootstrap文件 官网&#xff1a;https://www.bootcss.com/V4版本入口&#xff1a;https://v4.bootcss.com/V5版本入口&#xff1a;https://v5.bootcss.com/ 这里使用成熟的V4版本&#xff0c;中文文档地址&#xff1a;https://v4.b…...

2024后端开发面试题总结

一、前言 上一篇离职贴发布之后仿佛登上了热门&#xff0c;就连曾经阿里的师兄都看到了我的分享&#xff0c;这波流量真是受宠若惊&#xff01; 回到正题&#xff0c;文章火之后&#xff0c;一些同学急切想要让我分享一下面试内容&#xff0c;回忆了几个晚上顺便总结一下&#…...