目录
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大于0
if (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特征值赋给p
j = 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; //浮点参数变量1
float varFloat2; //浮点参数变量2
LPSTR 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结构的指针
// 分配内存,以保存缩放后的DIB
HGLOBAL 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;// 进行付立叶变换的宽度和高度,初始化为1
double 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;// 进行付立叶变换的宽度和高度,初始化为1
double 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 / nCount
double 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];
// 将需要反变换的数据写入工作空间pCWork
memcpy(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);
// 求时域点的共轭,求得最终结果
// 根据傅立叶变换原理,利用这样的方法求得的结果和实际的时域数据
// 相差一个系数nCount
for(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还是IDWT
if (!nInv)
{ // DWT
Index1=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;
}
}
// 否则进行IDWT
else
{ // IDWT
Index1 = 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还是IDWT
if (!nInv)
{
int i = 0;
// 对行进行一维DWT
for (i=0; i<CurH; i++)
if (!DWTStep_1D(pDbSrc+(int)i*W*nStep, nCurWLevel, nInv, nStep, nSupp)) return FALSE;
// 对列进行一维DWT
for (i=0; i<CurW; i++)
if (!DWTStep_1D(pDbSrc+i*nStep, nCurHLevel, nInv, W*nStep, nSupp)) return FALSE;
}
// 否则进行IDWT
else
{
// 计算当前变换的图像的长度和宽度
CurW <<= 1;
CurH <<= 1;
int i = 0;
// 对列进行IDWT
for (i=0; i<CurW; i++)
if (!DWTStep_1D(pDbSrc+i*nStep, nCurHLevel, nInv, W*nStep, nSupp)) return FALSE;
// 对行进行IDWT
for (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);
else
if (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;
// 如果是反变换,则当前层数减1
if (nInv)
m_nDWTCurDepth --;
// 否则加1
else
m_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]);
else
pBits[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);
// 插值1
f12 = (unsigned char) (f1 + (x - i1) * (f2 - f1));
// 插值2
f34 = (unsigned char) (f3 + (x - i1) * (f4 - f3));
// 插值3
return ((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));
// 分配内存,以保存新DIB
hDIB = (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 DIB
lpbmi->biWidth = lNewWidth;
lpbmi->biHeight = lNewHeight;
}
else
{
// 对于其它格式的DIB
lpbmc->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); //转换后的字节数GetRequireByteWidth
HGLOBAL 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();
// 为位图文件头分配空间,并初始化为0
m_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)
{
// 是位图文件
// 计算除位图文件头的空间大小,分配空间并初始化为0
DWORD 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;
}
// 申请缓冲区,初始化为0
DWORD 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;
// 如果位图指针为空,则返回FALSE
if(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;
// 为灰度位图分配空间,并初始化为0
LPBYTE 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;
// 为彩色位图分配空间,并初始化为0
LPBYTE 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);// 锁定DIB
lpbminfo = (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;
else
H[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;
else
H[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);
// 初始化新分配的内存,设定初始值为0
lpDst = (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);
// 初始化新分配的内存,设定初始值为0
lpDst = (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);
// 初始化新分配的内存,设定初始值为0
lpDst = (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);
// 初始化新分配的内存,设定初始值为0
lpDst = (LPBYTE)lpNewDIBBits;
memset(lpDst, (BYTE)0, lWidth * lHeight);
// 初始化中间变量temp
memset(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);
// 初始化新分配的内存,设定初始值为0
lpDst = (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];
else
now_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);
//判断是否超过255
if(fResult>255)
//若超过255,直接赋值为255
lpNewDIBBits[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);
// 初始化新分配的内存,设定初始值为0
lpDst = (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);
// 初始化新分配的内存,设定初始值为0
lpDst = (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);
// 初始化新分配的内存,设定初始值为0
lpDst = (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];
//求方差最小的邻域nMin
varMin=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);
// 初始化新分配的内存,设定初始值为0
lpDst = (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 _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnFileOpen();
public:
CDib m_PhotoImage;//照片图像
BOOL flag;//打开照片图像标记变量 要在默认构造函数中初始化该对象
afx_msg void OnOpenPhoto();
afx_msg void OnLinearTransform();
afx_msg void OnSegLineTransform();
afx_msg void OnLogTransform();
afx_msg void OnHistogramEqual();
afx_msg void OnHistogramMatch();
afx_msg void OnAverageSmooth();
afx_msg void OnValueAvrgSmooth();
afx_msg void OnSelectSmooth();
afx_msg void OnMiddleSmooth();
afx_msg void OnGateGrad();
afx_msg void OnLaplacian();
afx_msg void OnPrefectLowFilter();
afx_msg void OnPrefectHighFilter();
afx_msg void OnPseudoColorEnhance();
};
#ifndef _DEBUG // 数字图像处理View.cpp 中的调试版本
inline C数字图像处理Doc* C数字图像处理View::GetDocument() const
{ return reinterpret_cast<C数字图像处理Doc*>(m_pDocument); }
#endif
数字图像处理View.cpp : C数字图像处理View 类的实现
// 数字图像处理View.cpp : C数字图像处理View 类的实现
//
#include "stdafx.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "数字图像处理.h"
#endif
#include "数字图像处理Doc.h"
#include "数字图像处理View.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// C数字图像处理View
IMPLEMENT_DYNCREATE(C数字图像处理View, CView)
BEGIN_MESSAGE_MAP(C数字图像处理View, CView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
ON_COMMAND(ID_FILE_OPEN, &C数字图像处理View::OnFileOpen)
ON_COMMAND(ID_OPEN_PHOTO, &C数字图像处理View::OnOpenPhoto)
ON_COMMAND(ID_LINEAR_TRANSFORM, &C数字图像处理View::OnLinearTransform)
ON_COMMAND(ID_SEG_LINE_TRANSFORM, &C数字图像处理View::OnSegLineTransform)
ON_COMMAND(ID_LOG_TRANSFORM, &C数字图像处理View::OnLogTransform)
ON_COMMAND(ID_HISTOGRAM_EQUAL, &C数字图像处理View::OnHistogramEqual)
ON_COMMAND(ID_HISTOGRAM_MATCH, &C数字图像处理View::OnHistogramMatch)
ON_COMMAND(ID_AVERAGE_SMOOTH, &C数字图像处理View::OnAverageSmooth)
ON_COMMAND(ID_VALUE_AVRG_SMOOTH, &C数字图像处理View::OnValueAvrgSmooth)
ON_COMMAND(ID_SELECT_SMOOTH, &C数字图像处理View::OnSelectSmooth)
ON_COMMAND(ID_MIDDLE_SMOOTH, &C数字图像处理View::OnMiddleSmooth)
ON_COMMAND(ID_GATE_GRAD, &C数字图像处理View::OnGateGrad)
ON_COMMAND(ID_LAPLACIAN, &C数字图像处理View::OnLaplacian)
ON_COMMAND(ID_PREFECT_LOW_FILTER, &C数字图像处理View::OnPrefectLowFilter)
ON_COMMAND(ID_PREFECT_HIGH_FILTER, &C数字图像处理View::OnPrefectHighFilter)
ON_COMMAND(ID_PSEUDO_COLOR_ENHANCE, &C数字图像处理View::OnPseudoColorEnhance)
END_MESSAGE_MAP()
// C数字图像处理View 构造/析构
C数字图像处理View::C数字图像处理View()
{
// TODO: 在此处添加构造代码
flag = FALSE;//用于判断是否打开图像标志位
}
C数字图像处理View::~C数字图像处理View()
{
}
BOOL C数字图像处理View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return CView::PreCreateWindow(cs);
}
// C数字图像处理View 绘制
void C数字图像处理View::OnDraw(CDC* /*pDC*/)
{
C数字图像处理Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
}
// C数字图像处理View 打印
BOOL C数字图像处理View::OnPreparePrinting(CPrintInfo* pInfo)
{
// 默认准备
return DoPreparePrinting(pInfo);
}
void C数字图像处理View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加额外的打印前进行的初始化过程
}
void C数字图像处理View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加打印后进行的清理过程
}
// C数字图像处理View 诊断
#ifdef _DEBUG
void C数字图像处理View::AssertValid() const
{
CView::AssertValid();
}
void C数字图像处理View::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
C数字图像处理Doc* C数字图像处理View::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(C数字图像处理Doc)));
return (C数字图像处理Doc*)m_pDocument;
}
#endif //_DEBUG
// C数字图像处理View 消息处理程序
void C数字图像处理View::OnFileOpen()
{
// TODO: 在此添加命令处理程序代码
MessageBox(_T("123"));
}
void C数字图像处理View::OnOpenPhoto()
{
// TODO: 在此添加命令处理程序代码
// 本函数功能是打开并显示照片图像
CString filename;
CFileDialog dlg(TRUE, _T("BMP"), _T("*.BMP"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("位图文件(*.BMP)|*.BMP|"));
if (IDOK == dlg.DoModal())
filename.Format("%s", dlg.GetPathName());
m_PhotoImage.LoadFromFile(filename);//打开照片图像
flag = TRUE;//照片图像打开后,将标记变量置为真
//显示图像
CPoint point;
CSize size;
point.x = 0;
point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
size.cx = lWidth;
size.cy = lHeight;
CDC *pDC = GetDC();
m_PhotoImage.Draw(pDC, point, size);
}
// 此函数实现灰度线性增强处理
void C数字图像处理View::OnLinearTransform()
{
// TODO: 在此添加命令处理程序代码
// 此函数实现灰度线性增强处理
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
CPoint point;
CSize size;
point.x = 0;
point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
size.cx = lWidth;
size.cy = lHeight;
CDC *pDC = GetDC();
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
CGrayTransformDib GrayTransform(&m_PhotoImage);//创建一个CGrayTransformDib对象
BYTE min, max; //设置变换后的灰度区间
min = 100;
max = 200;
GrayTransform.Linear_Transform(min, max); //调用灰度线性变换增强函数
CPoint point1;
point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
point1.y = 0;
m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}
// 此函数实现分段线性增强处理
void C数字图像处理View::OnSegLineTransform()
{
// TODO: 在此添加命令处理程序代码
// 此函数实现分段线性增强处理
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
CPoint point;
CSize size;
point.x = 0;
point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
size.cx = lWidth;
size.cy = lHeight;
CDC *pDC = GetDC();
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
CGrayTransformDib GrayTransform(&m_PhotoImage); //创建一个CGrayTransformDib对象
BYTE gSrc1, gSrc2, gDst1, gDst2; //设置分段点
gSrc1 = 100;
gSrc2 = 150;
gDst1 = 50;
gDst2 = 200;
GrayTransform.Seg_Linear_Transform(gSrc1, gSrc2, gDst1, gDst2);//调用分段线性变换增强函数
CPoint point1;
point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
point1.y = 0;
m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}
// 此函数实现对数函数非线性变换增强处理
void C数字图像处理View::OnLogTransform()
{
// TODO: 在此添加命令处理程序代码
// 此函数实现对数函数非线性变换增强处理
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
CPoint point;
CSize size;
point.x = 0;
point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
size.cx = lWidth;
size.cy = lHeight;
CDC *pDC = GetDC();
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
CGrayTransformDib GrayTransform(&m_PhotoImage);//创建一个CGrayTransformDib对象
double a, b, c; //对数函数变换参数设置
a = 50.0;
b = 0.8;
c = 1.05;
GrayTransform.Log_Transform(a, b, c); //调用对数函数非线性变换增强函数
CPoint point1;
point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
point1.y = 0;
m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}
// 此函数实现直方图均衡化增强处理
void C数字图像处理View::OnHistogramEqual()
{
//ID_HISTOGRAM_EQUAL
// TODO: 在此添加命令处理程序代码
// 此函数实现直方图均衡化增强处理
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
CPoint point;
CSize size;
point.x = 0;
point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
size.cx = lWidth;
size.cy = lHeight;
CDC *pDC = GetDC();
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
CHistogramDib Histgram(&m_PhotoImage);//创建一个CHistogramDib对象
Histgram.Histogram_Equalization(); //调用直方图均衡化处理函数
CPoint point1;
point1.x = lWidth + 20; //+20是为了让两个图像显示时有个间隙
point1.y = 0;
m_PhotoImage.Draw(pDC, point1, size);//绘制处理后的图像
}
// 此函数实现直方图规定化增强处理
void C数字图像处理View::OnHistogramMatch()
{
//ID_HISTOGRAM_MATCH
// TODO: 在此添加命令处理程序代码
// 此函数实现直方图规定化增强处理
//如果之前没加载图像,将在这里提示
if (flag == FALSE)
{
AfxMessageBox("请先加载要处理的照片图像!");
return;
}
CPoint point;
CSize size;
point.x = 0;
point.y = 0;
LONG lWidth = m_PhotoImage.GetWidth(); //获得灰度图像的宽度
LONG lHeight = m_PhotoImage.GetHeight(); //获得灰度图像的高度
size.cx = lWidth;
size.cy = lHeight;
CDC *pDC = GetDC();
m_PhotoImage.Draw(pDC, point, size);//绘制处理前的图像
CHistogramDib Histgram(&m_PhotoImage);//创建一个CHistogramDib对象
int nu[64]; //规定直方图映射关系,这里规定直方图的灰度级为64
float 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, //4
0, 0, 31, 0, 0, 0, 39, 0, 0, 0, 47, 0, 0, 0, 55, 0, //8
0, 0, 63, 0, 0, 0, 71, 0, 0, 0, 79, 0, 0, 0, 87, 0, //12
0, 0, 85, 0, 0, 0, 103, 0, 0, 0, 111, 0, 0, 0, 119, 0, //16
0, 0, 127, 0, 0, 0, 135, 0, 0, 0, 143, 0, 0, 0, 151, 0, //20
0, 0, 159, 0, 0, 0, 167, 0, 0, 0, 175, 0, 0, 0, 183, 0, //24
0, 0, 191, 0, 0, 0, 199, 0, 0, 0, 207, 0, 0, 0, 215, 0, //28
0, 0, 223, 0, 0, 0, 231, 0, 0, 0, 239, 0, 0, 0, 247, 0, //32
0, 0, 255, 0, 0, 8, 255, 0, 0, 16, 255, 0, 0, 24, 255, 0, //36
0, 32, 255, 0, 0, 40, 255, 0, 0, 48, 255, 0, 0, 56, 255, 0, //40
0, 64, 255, 0, 0, 72, 255, 0, 0, 80, 255, 0, 0, 88, 255, 0, //44
0, 96, 255, 0, 0, 104, 255, 0, 0, 112, 255, 0, 0, 120, 255, 0, //48
0, 128, 255, 0, 0, 136, 255, 0, 0, 144, 255, 0, 0, 152, 255, 0, //52
0, 160, 255, 0, 0, 168, 255, 0, 0, 176, 255, 0, 0, 184, 255, 0, //56
0, 192, 255, 0, 0, 200, 255, 0, 0, 208, 255, 0, 0, 216, 255, 0, //60
0, 224, 255, 0, 6, 232, 255, 0, 0, 240, 255, 0, 0, 248, 255, 0, //64
0, 255, 255, 0, 0, 255, 247, 0, 0, 255, 239, 0, 0, 255, 231, 0, //68
0, 255, 223, 0, 0, 255, 215, 0, 0, 255, 207, 0, 0, 255, 199, 0, //72
0, 255, 191, 0, 0, 255, 183, 0, 0, 255, 175, 0, 0, 255, 167, 0, //76
0, 255, 159, 0, 0, 255, 151, 0, 0, 255, 143, 0, 0, 255, 135, 0, //80
0, 255, 127, 0, 0, 255, 119, 0, 0, 255, 111, 0, 0, 255, 103, 0, //84
0, 255, 95, 0, 0, 255, 87, 0, 0, 255, 79, 0, 0, 255, 71, 0, //88
0, 255, 63, 0, 0, 255, 55, 0, 0, 255, 47, 0, 0, 255, 39, 0, //92
0, 255, 31, 0, 0, 255, 23, 0, 0, 255, 15, 0, 0, 255, 7, 0, //96
0, 255, 0, 0, 8, 255, 0, 0, 16, 255, 0, 0, 24, 255, 0, 0, //100
32, 255, 0, 0, 40, 255, 0, 0, 48, 255, 0, 0, 56, 255, 0, 0, //104
64, 255, 0, 0, 72, 255, 0, 0, 80, 255, 0, 0, 88, 255, 0, 0, //108
96, 255, 0, 0, 104, 255, 0, 0, 112, 255, 0, 0, 120, 255, 0, 0, //112
128, 255, 0, 0, 136, 255, 0, 0, 144, 255, 0, 0, 152, 255, 0, 0, //116
160, 255, 0, 0, 168, 255, 0, 0, 176, 255, 0, 0, 184, 255, 0, 0, //120
192, 255, 0, 0, 200, 255, 0, 0, 208, 255, 0, 0, 216, 255, 0, 0, //124
224, 255, 0, 0, 232, 255, 0, 0, 240, 255, 0, 0, 248, 255, 0, 0, //128
255, 255, 0, 0, 255, 251, 0, 0, 255, 247, 0, 0, 255, 243, 0, 0, //132
255, 239, 0, 0, 255, 235, 0, 0, 255, 231, 0, 0, 255, 227, 0, 0, //136
255, 223, 0, 0, 255, 219, 0, 0, 255, 215, 0, 0, 255, 211, 0, 0, //140
255, 207, 0, 0, 255, 203, 0, 0, 255, 199, 0, 0, 255, 195, 0, 0, //144
255, 191, 0, 0, 255, 187, 0, 0, 255, 183, 0, 0, 255, 179, 0, 0, //148
255, 175, 0, 0, 255, 171, 0, 0, 255, 167, 0, 0, 255, 163, 0, 0, //152
255, 159, 0, 0, 255, 155, 0, 0, 255, 151, 0, 0, 255, 147, 0, 0, //156
255, 143, 0, 0, 255, 139, 0, 0, 255, 135, 0, 0, 255, 131, 0, 0, //160
255, 127, 0, 0, 255, 123, 0, 0, 255, 119, 0, 0, 255, 115, 0, 0, //164
255, 111, 0, 0, 255, 107, 0, 0, 255, 103, 0, 0, 255, 99, 0, 0, //168
255, 95, 0, 0, 255, 91, 0, 0, 255, 87, 0, 0, 255, 83, 0, 0, //172
255, 79, 0, 0, 255, 75, 0, 0, 255, 71, 0, 0, 255, 67, 0, 0, //176
255, 63, 0, 0, 255, 59, 0, 0, 255, 55, 0, 0, 255, 51, 0, 0, //180
255, 47, 0, 0, 255, 43, 0, 0, 255, 39, 0, 0, 255, 35, 0, 0, //184
255, 31, 0, 0, 255, 27, 0, 0, 255, 23, 0, 0, 255, 19, 0, 0, //188
255, 15, 0, 0, 255, 11, 0, 0, 255, 7, 0, 0, 255, 3, 0, 0, //192
255, 0, 0, 0, 255, 4, 4, 0, 255, 8, 8, 0, 255, 12, 12, 0, //196
255, 16, 16, 0, 255, 20, 20, 0, 255, 24, 24, 0, 255, 28, 28, 0, //200
255, 32, 32, 0, 255, 36, 36, 0, 255, 40, 40, 0, 255, 44, 44, 0, //204
255, 48, 48, 0, 255, 52, 52, 0, 255, 56, 56, 0, 255, 60, 60, 0, //208
255, 64, 64, 0, 255, 68, 68, 0, 255, 72, 72, 0, 255, 76, 76, 0, //212
255, 80, 80, 0, 255, 84, 84, 0, 255, 88, 88, 0, 255, 92, 92, 0, //216
255, 96, 96, 0, 255, 100, 100, 0, 255, 104, 104, 0, 255, 108, 108, 0, //220
255, 112, 112, 0, 255, 116, 116, 0, 255, 120, 120, 0, 255, 124, 124, 0, //224
255, 128, 128, 0, 255, 132, 132, 0, 255, 136, 136, 0, 255, 140, 140, 0, //228
255, 144, 144, 0, 255, 148, 148, 0, 255, 152, 152, 0, 255, 156, 156, 0, //232
255, 160, 160, 0, 255, 164, 164, 0, 255, 168, 168, 0, 255, 172, 172, 0, //236
255, 176, 176, 0, 255, 180, 180, 0, 255, 184, 184, 0, 255, 188, 188, 0, //240
255, 192, 192, 0, 255, 196, 196, 0, 255, 200, 200, 0, 255, 204, 204, 0, //244
255, 208, 208, 0, 255, 212, 212, 0, 255, 216, 216, 0, 255, 220, 220, 0, //248
255, 224, 224, 0, 255, 228, 228, 0, 255, 232, 232, 0, 255, 236, 236, 0, //252
255, 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);//绘制处理后的图像
}