妙妙小豆子

胆子大一点,想开一点。长风破浪会有时,直挂云帆济沧海

常见图像处理的演示 银牌收录

程序简介

这个程序包括了一些常见图像处理的演示,并提供了一些按钮来改变参数。有旋转,均衡化,分割,填充,锐化,模糊,滤波,变换和一个分裂图小游戏。

我的理解是,图像变换就是基于某个规则对图像中像素点的处理,可以是统一处理,也可以分类处理。
程序的初始化函数 initialization 中默认加载了三张所使用的图片,第一张是大部分图像处理所用图片,第二张是滤波处理所用图片,第三张是分裂图所用图片。也可以通过输入图片相对位置及名称来使用自己的图片。
FFT 变换和低通滤波时间较长,展示时需要等待较长时间才能完成,谨慎使用。

图像处理演示列表:
1. 图像旋转
2. 直方图均衡化
3. 图像分割
4. 伪色彩填充
5. 图像锐化
6. 图像模糊
7. Arnold 变换
8. DCT 变换
9. Haar 变换
10. 均值滤波
11. 中值滤波
12. FFT 变换
13. 低通滤波
14. 分裂图

第一次更新:
1. 界面和图片的统一调整,重复变量的删减。
2. 分裂图一开始不会展示使用的图片,保留悬念。

第二次更新:
1. 程序现在可以通过 VC2010 的编译了。
原代码从 VC6.0 迁移到 VC2010 会出现 3 个错误,sqrt 函数参数错误,pow 函数参数错误,sscanf 函数参数错误。前两个问题可以强制转换,我在报错的地方加上 double 来解决;第三个问题可以进入 VC2010 的项目,属性,配置,属性,常规,字符集:“使用 Unicode 字符集”改为“使用多字节字符集”来解决。
2. 程序开头的注释中,将“编译环境:Visual C++ 6.0/2010”改为“编译环境:Visual C++ 6.0”。
老师要求程序不能有警告,通过 VC2010 的编译后,虽然没有报错,但有大量警告,基本是变量类型需要强制转换的问题,这些都是 VC6.0 没有的警告。看到评论的同学提出的问题后,我意识到,我暂时没有办法解决变量类型强制转换后带来的位移问题,所以我不能随便强制转换,只能先减少编译环境了,谢谢评论的大同学。

第三次更新:
1. 图片更新,减小边框
2. 代码更新,现在兼容 vc2010,不兼容 vc6.0
vc2010:_stscanf_s,vc6.0:_stscanf
vc2010:_stprintf_s,vc6.0:_stprintf
列表框箭头坐标偏移的问题,建议直接删除箭头,只采用滑条即可。这个程序 debug 没问题,release 有问题,暂时不要使用 release。

程序执行效果

所用素材

t0.png t1.png t2.png

完整源代码

////////////////////////////////////////
// 程序:常见图像处理的演示
// 作者:Gary
// 编译环境:Visual C++ 2010,EasyX_20211109
// 编写日期:2021-5-11

# include <math.h>
# include <graphics.h>
# include <string>

static double pi = acos (-1.0);			// 圆周率 π
static HWND hOut;						// 画布


// 定义一个结构体,按钮
struct Node1
{
	int posx1, posy1, posx2, posy2;		// 坐标
	int type;							// 按钮激活状态
	COLORREF color;						// 颜色
	LPTSTR text;						// 文字
};

// 定义一个结构体,列表框
struct Node2
{
	int posx1, posy1, posx2, posy2;		// 坐标
	double every_text_num;				// 列表框每次展示文本数量
	double all_text_num;				// 列表框所有文本数量
	int flag_text_num;					// 列表框当前选定文本编号
	Node1 box_button[20];				// 按钮,预制
};

// 定义一个结构体,FFT 变换相关
struct Node3
{
	double Re;							// 实部
	double Im;							// 虚部
};

// 定义一个结构体,FFT 变换相关
struct Node4
{
	double Re;							// 实部
	double Im;							// 虚部
};

// 定义一个结构体,Arnold 变换相关
struct Node5
{
	int posx, posy;						// 坐标
	COLORREF color;						// 颜色
};

// 定义一个结构体,分裂图相关
struct Node6
{
	int posx, posy;						// 坐标
	COLORREF color;						// 颜色
	double k1, k2, k3, R;				// 颜色和半径
	int num, boxnum[5];					// 自己的编号,和分裂后小圆的编号
};

// 定义一个结构体,分裂图相关
struct Node7
{
	int num;							// 自己的编号
	int boxnum;							// 所存圆的编号
};

// 定义一个结构体,分裂图相关
struct Node8
{
	COLORREF k1, k2, k3;				// 颜色暂存
};

// 放类内,默认空间不够
Node3 Xn[512][512];
Node4 Xm[512][512];
Node5 boxm[512][512];
Node6 boxb[22000];
Node7 eatb[22000];
Node8 boxb1[600][600];

// 定义一个类
class Gary
{
public:
	void carry ();						// 主进程
	void initialization ();				// 初始化
	void initialization_image ();		// 图像处理初始化
	void move ();						// 窗口主视角
	void draw_scene ();					// 绘制界面函数
	void draw_image ();					// 图像处理绘制函数
	Node1 box_button[20];				// 按钮,预制
	Node2 box_list[1];					// 列表框,预制
	int exit_carry;						// 主循函数控制参数
	int exit_move;						// 开始界面控制参数
	int num_button;						// 按钮数量参数
	int num_list;						// 数量参数
	int A, B;							// 临时变量
	int mod;							// 模式选择参数
	double T;							// 临时变量
	int G;								// 灰度值变量
	int flag, flag1;					// 总数存储变量
	IMAGE img[3];						// 两张图片,图像处理使用
};


// 定义一些数组变量,图像处理相关
int g[256];							// 灰度值数组,画直方图所用
double g1[256];						// 灰度值数组,画直方图所用
double eat[512][512];
double eat2[512][512];
double box[512][512];
double box1[512][512];

// 按钮初始化函数
void Gary::initialization_image ()
{
	int i;

	// 矩形按钮
	for (i = 0; i < num_button; i++)
	{
		box_button[i].type = 0;
	}

	box_button[2].text = _T ("动画演示");	box_button[2].type = 1;

	// 按钮初始化
	switch (box_list[0].flag_text_num)
	{
		// 图像旋转
	case 3:
	{
		box_button[0].text = _T ("角度");	box_button[0].type = 1;
		break;
	}
	// 直方图均衡化
	case 4:
	{
		box_button[0].text = _T ("灰度数量");	box_button[0].type = 1;
		box_button[3].text = _T ("最低灰度");	box_button[3].type = 1;
		box_button[6].text = _T ("灰度范围");	box_button[6].type = 1;
		break;
	}
	// 图像分割
	case 5:
	{
		box_button[0].text = _T ("间隔");	box_button[0].type = 1;
		break;
	}
	// 伪色彩填充
	case 6:
	{
		break;
	}
	// 图像锐化
	case 7:
	{
		box_button[0].text = _T ("锐化阈值");	box_button[0].type = 1;
		box_button[1].text = _T ("锐化方式");	box_button[1].type = 1;
		break;
	}
	// 图像模糊
	case 8:
	{
		box_button[0].text = _T ("宽度");	box_button[0].type = 1;
		break;
	}
	// Arnold 变换
	case 9:
	{
		box_button[0].text = _T ("变换次数");	box_button[0].type = 1;
		box_button[3].text = _T ("密钥一");	box_button[3].type = 1;
		box_button[6].text = _T ("密钥二");	box_button[6].type = 1;
		break;
	}
	// DCT 变换
	case 10:
	{
		box_button[0].text = _T ("宽度");	box_button[0].type = 1;
		break;
	}
	// Haar 变换
	case 11:
	{
		break;
	}
	// 均值滤波
	case 12:
	{
		box_button[0].text = _T ("均值");	box_button[0].type = 1;
		box_button[1].text = _T ("高斯");	box_button[1].type = 1;

		box_button[3].text = _T ("左上权值");	box_button[3].type = 1;
		box_button[4].text = _T ("正上权值");	box_button[4].type = 1;
		box_button[5].text = _T ("右上权值");	box_button[5].type = 1;
		box_button[6].text = _T ("正左权值");	box_button[6].type = 1;
		box_button[7].text = _T ("中心权值");	box_button[7].type = 1;
		box_button[8].text = _T ("正右权值");	box_button[8].type = 1;
		box_button[9].text = _T ("左下权值");	box_button[9].type = 1;
		box_button[10].text = _T ("正下权值");	box_button[10].type = 1;
		box_button[11].text = _T ("右下权值");	box_button[11].type = 1;
		break;
	}
	// 中值滤波
	case 13:
	{
		box_button[0].text = _T ("取值宽度");	box_button[0].type = 1;
		break;
	}
	// FFT 变换
	case 14:
	{
		break;
	}
	// 低通滤波
	case 15:
	{
		box_button[0].text = _T ("截止频率");	box_button[0].type = 1;
		box_button[1].text = _T ("滤波器");	box_button[1].type = 1;
		break;
	}
	// 分裂图
	case 16:
	{
		box_button[0].text = _T ("最小半径");	box_button[0].type = 1;
		box_button[1].text = _T ("结束游戏");	box_button[1].type = 1;
		break;
	}
	default:break;
	}
}

// 图像处理绘制函数
void Gary::draw_image ()
{
	int i, j, k, t;
	int m, n, flag1, x, y;
	double k1, k2, k3;
	int posx, posy;
	TCHAR s[25];

	// 框框范围绘制
	setfillcolor (WHITE);
	setlinecolor (BLACK);
	setlinestyle (PS_SOLID, 2);

	// 被处理图像
	putimage (20, 30, &img[0]);
	FlushBatchDraw ();

	// 暂时退出绘制缓存
	EndBatchDraw ();

	// 参数初始化
	switch (box_list[0].flag_text_num)
	{
		// 图像旋转
	case 3:
	{
		// 彩图
		// 计算旋转后中心点距离画布中心的坐标差
		j = 320 + 128 - int ((cos (T * pi / 180.0) * (128.0) + sin (T * pi / 180.0) * 128.0));
		k = 30 + 128 - int ((-sin (T * pi / 180.0) * (128.0) + cos (T * pi / 180.0) * 128.0));
		// 对图像做旋转矩阵变换
		for (i = 0; i < 256 * 256; i++)
		{
			// 计算原像旋转后坐标
			k1 = cos (T * pi / 180.0) * (i % 256) + sin (T * pi / 180.0) * i / 256;
			k2 = -sin (T * pi / 180.0) * (i % 256) + cos (T * pi / 180.0) * i / 256;
			putpixel (int (k1 + j), int (k2 + k), getpixel (i % 256 + 20, i / 256 + 30));
			// 针对旋转后出现的部分像素点缺失进行简单的补充
			if (getpixel (int (k1) + j + 1, int (k2) + k) <= 0 || getpixel (int (k1) + j + 1, int (k2) + k) > 255) { putpixel (int (k1) + j + 1, int (k2) + k, getpixel (i % 256 + 20, i / 256 + 30)); }
		}
		FlushBatchDraw ();
		break;
	}
	// 直方图均衡化
	case 4:
	{
		// 灰度图
		outtextxy (110, 5, _T ("灰度图像"));
		outtextxy (410, 5, _T ("灰度直方图"));
		outtextxy (110, 305, _T ("均衡直方图"));
		outtextxy (410, 305, _T ("均衡结果"));
		// 取第一部分灰度值,在第一部分绘制灰白图
		for (i = 0; i < 256; i++)
		{
			g[i] = 0;
		}
		for (i = 0; i < 256 * 256; i++)
		{
			j = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256 / 256;
			// 灰度调整
			j = int (A + double (B) / 255.0 * double (j));
			g[j]++;
			putpixel (i % 256 + 20, i / 256 + 30, RGB (j, j, j));
		}
		FlushBatchDraw ();
		// 在第二部分绘制直方图
		setlinestyle (PS_SOLID, 1);
		setlinecolor (BLACK);
		G = 0;
		for (i = 0; i < 256; i++)
		{
			if (G < g[i])G = g[i];
		}
		for (i = 0; i < 256; i++)
		{
			line (320 + i, 290, 320 + i, int (290 - 200.0 * double (g[i]) / double (G)));
		}
		FlushBatchDraw ();
		// 第三部分计算均衡直方图
		// 累计概率
		g1[0] = double (g[0]) / 256.0 / 256.0;
		for (i = 1; i < 256; i++)
		{
			g1[i] = double (g[i]) / 256.0 / 256.0 + g1[i - 1];
		}
		// 均衡化
		j = 0;
		for (i = 0; i < 256; i++)
		{
			if (g1[i] >= double (j) / T && g1[i]<double (j + 1) / T)
			{
				g1[i] = j;
			}
			else
			{
				i--;
				j++;
			}
		}
		// 在第四部分画出来
		for (i = 0; i < 256; i++)
		{
			g[i] = 0;
		}
		for (i = 0; i < 256 * 256; i++)
		{
			j = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256 / 256;
			putpixel (i % 256 + 320, i / 256 + 330, RGB (g1[j] * 256.0 / T, g1[j] * 256.0 / T, g1[j] * 256.0 / T));
			g[int (g1[j])]++;

		}
		FlushBatchDraw ();
		// 在第三部分绘制直方图
		G = 0;
		for (i = 0; i<int (T); i++)
		{
			if (G < g[i])G = g[i];
		}
		for (i = 0; i<int (T); i++)
		{
			line (int (20 + double (i) / int (T) * 256.0), 590, int (20 + double (i) / int (T) * 256.0), int (590 - 200.0 * double (g[i]) / double (G)));
		}
		line (20, 590, 276, 590);
		FlushBatchDraw ();
		break;
	}
	// 图像分割
	case 5:
	{
		// 灰度图
		outtextxy (410, 5, _T ("灰度图像"));
		outtextxy (110, 305, _T ("直方图"));
		outtextxy (410, 305, _T ("分割结果"));
		// 取第一部分灰度值,在第二部分绘制灰白图
		for (i = 0; i < 256; i++)
		{
			g[i] = 0;
		}
		for (i = 0; i < 256 * 256; i++)
		{
			j = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256 / 256;
			g[j]++;
			putpixel (i % 256 + 320, i / 256 + 30, RGB (j, j, j));
		}
		FlushBatchDraw ();
		// 在第三部分绘制直方图
		setlinestyle (PS_SOLID, 1);
		setlinecolor (BLACK);
		G = 0;
		for (i = 0; i < 256; i++)
		{
			if (G < g[i])G = g[i];
		}
		for (i = 0; i < 256; i++)
		{
			line (int (20 + double (i) / 256.0 * 256.0), 590, int (20 + double (i) / 256.0 * 256.0), int (590 - 200.0 * double (g[i]) / double (G)));
		}
		setlinestyle (PS_DASH, 1);
		setlinecolor (RED);
		for (i = 0; i < 256; i += int (T))
		{
			line (int (20 + double (i) / 256.0 * 256.0), 590, int (20 + double (i) / 256.0 * 256.0), 590 - 256);
		}
		FlushBatchDraw ();
		// 在第四部分根据阈值绘制分割结果
		for (i = 0; i < 256 * 256; i++)
		{
			for (j = 0; j < 256; j += int (T))
			{
				k = RGBtoGRAY (getpixel (i % 256 + 320, i / 256 + 30)) / 256 / 256;
				if (k >= j && k < j + T)
				{
					putpixel (i % 256 + 320, i / 256 + 330, RGB ((j + T) / 2, (j + T) / 2, (j + T) / 2));
				}
			}
		}
		FlushBatchDraw ();
		break;
	}
	// 伪色彩填充
	case 6:
	{
		// 灰度图
		outtextxy (410, 5, _T ("灰度图像"));
		outtextxy (110, 305, _T ("直方图"));
		outtextxy (410, 305, _T ("填充结果"));
		// 取第一部分灰度值,在第二部分绘制灰白图
		for (i = 0; i < 256; i++)
		{
			g[i] = 0;
		}
		for (i = 0; i < 256 * 256; i++)
		{
			j = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256 / 256;
			g[j]++;
			putpixel (i % 256 + 320, i / 256 + 30, RGB (j, j, j));
		}
		FlushBatchDraw ();
		// 在第三部分绘制直方图
		setlinestyle (PS_SOLID, 1);
		setlinecolor (BLACK);
		G = 0;
		for (i = 0; i < 256; i++)
		{
			if (G < g[i])G = g[i];
		}
		for (i = 0; i < 256; i++)
		{
			line (int (20 + double (i) / 256.0 * 256.0), 590, int (20 + double (i) / 256.0 * 256.0), int (590 - 200.0 * double (g[i]) / double (G)));
		}
		FlushBatchDraw ();
		// 在第四部分绘制伪色彩填充结果
		for (i = 0; i < 256 * 256; i++)
		{
			k = RGBtoGRAY (getpixel (i % 256 + 320, i / 256 + 30)) / 256 / 256;
			if (k < 256.0 / 4.0)
			{
				k1 = k * 255.0 / 256.0 * 4.0;
				k2 = 255;
				k3 = 0;
			}
			else if (k < 256.0 / 2.0)
			{
				k1 = 255;
				k2 = 510 - k * 255.0 / 256.0 * 4.0;
				k3 = 0;
			}
			else if (k < 256.0 / 4.0 * 3.0)
			{
				k1 = 255;
				k2 = 0;
				k3 = -510 + k * 255.0 / 256.0 * 4.0;
			}
			else
			{
				k1 = 1020 - k * 255.0 / 256.0 * 4.0;
				k2 = 0;
				k3 = 255;
			}
			putpixel (i % 256 + 320, i / 256 + 330, RGB (k1, k2, k3));
		}
		FlushBatchDraw ();
		break;
	}
	// 图像锐化
	case 7:
	{
		// 灰度图
		outtextxy (410, 5, _T ("灰度图像"));
		outtextxy (110, 305, _T ("梯度图像"));
		outtextxy (410, 305, _T ("分割结果"));
		// 取第一部分灰度值,在第二部分绘制灰白图
		for (i = 0; i < 256 * 256; i++)
		{
			j = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256 / 256;
			putpixel (i % 256 + 320, i / 256 + 30, RGB (j, j, j));
		}
		FlushBatchDraw ();
		// 在第三部分绘制梯度图
		if (mod == 0)
		{
			// 四近邻
			for (i = 0; i < 254 * 254; i++)
			{
				j = getpixel (i % 254 + 1 + 320, i / 254 + 1 + 30 - 1) / 256 / 256 - getpixel (i % 254 + 1 + 320, i / 254 + 1 + 30 + 1) / 256 / 256;
				k = getpixel (i % 254 + 1 + 320 + 1, i / 254 + 1 + 30) / 256 / 256 - getpixel (i % 254 + 1 + 320 - 1, i / 254 + 1 + 30) / 256 / 256;
				// 因为理论最大值会是 255 的根号 2 倍,除以 2 保证灰度值范围
				j = int (sqrt (double (j * j + k * k)) / 2);
				putpixel (i % 254 + 20 + 1, i / 254 + 330 + 1, RGB (j, j, j));
			}
		}
		else if (mod == 1)
		{
			// 八近邻
			for (i = 0; i < 254 * 254; i++)
			{
				j = getpixel (i % 254 + 1 + 320, i / 254 + 1 + 30 - 1) / 256 / 256 - getpixel (i % 254 + 1 + 320, i / 254 + 1 + 30 + 1) / 256 / 256;
				k = getpixel (i % 254 + 1 + 320 + 1, i / 254 + 1 + 30) / 256 / 256 - getpixel (i % 254 + 1 + 320 - 1, i / 254 + 1 + 30) / 256 / 256;
				n = int (2 * sqrt (double (j * j + k * k)));
				j = getpixel (i % 254 + 1 + 320 - 1, i / 254 + 1 + 30 - 1) / 256 / 256 - getpixel (i % 254 + 1 + 320 + 1, i / 254 + 1 + 30 + 1) / 256 / 256;
				k = getpixel (i % 254 + 1 + 320 + 1, i / 254 + 1 + 30 - 1) / 256 / 256 - getpixel (i % 254 + 1 + 320 - 1, i / 254 + 1 + 30 + 1) / 256 / 256;
				n += int (sqrt (double (j * j + k * k)));
				// 因为理论最大值会是 255 的根号 10 倍,除以 3 保证灰度值范围
				n /= 3;
				putpixel (i % 254 + 20 + 1, i / 254 + 330 + 1, RGB (n, n, n));
			}
		}
		FlushBatchDraw ();
		// 在第四部分根据阈值绘制分割结果
		for (i = 0; i < 254 * 254; i++)
		{
			if (RGBtoGRAY (getpixel (i % 254 + 1 + 20, i / 254 + 1 + 330)) / 256 / 256 <= T)
			{
				putpixel (i % 254 + 1 + 320, i / 254 + 1 + 330, BLACK);
			}
			else {}
		}
		FlushBatchDraw ();
		break;
	}
	// 图像模糊
	case 8:
	{
		// 彩图
		outtextxy (410, 5, _T ("平均图像"));
		// 取第一部分颜色值,在第二部分绘制像素平均值
		for (i = 20; i < 276; i += int (T))
		{
			for (j = 30; j < 286; j += int (T))
			{
				k1 = 0; k2 = 0; k3 = 0;
				for (x = i; x < i + T; x++)
				{
					for (y = j; y < j + T; y++)
					{
						k1 += GetBValue (getpixel (x, y));
						k2 += GetGValue (getpixel (x, y));
						k3 += GetRValue (getpixel (x, y));
					}
				}
				k1 /= (T * T); k2 /= (T * T); k3 /= (T * T);
				for (x = i; x < i + T; x++)
				{
					for (y = j; y < j + T; y++)
					{
						putpixel (x + 300, y, RGB (k3, k2, k1));
					}
				}
			}
		}
		FlushBatchDraw ();
		break;
	}
	// Arnold 变换
	case 9:
	{
		// 彩图
		outtextxy (410, 5, _T ("Arnold 正变换"));
		outtextxy (110, 305, _T ("Arnold 反变换"));
		// 在第二部分绘制原图
		for (i = 0; i < 256; i++)
		{
			for (j = 0; j < 256; j++)
			{
				putpixel (i + 320, j + 30, getpixel (i + 20, j + 30));
			}
		}
		FlushBatchDraw ();
		Sleep (100);
		// 在第二部分进行 Arnold 正变换
		for (t = 0; t < T; t++)
		{
			// 变换
			for (i = 0; i < 256; i++)
			{
				for (j = 0; j < 256; j++)
				{
					x = (i + B * j) % 256;
					y = (A * i + (A * B + 1) * j) % 256;
					boxm[i][j].color = getpixel (i + 320, j + 30);
					boxm[i][j].posx = x;
					boxm[i][j].posy = y;

				}
			}
			// 绘制
			for (i = 0; i < 256; i++)
			{
				for (j = 0; j < 256; j++)
				{
					putpixel (boxm[i][j].posx + 320, boxm[i][j].posy + 30, boxm[i][j].color);
				}
			}
			FlushBatchDraw ();
			Sleep (500);
		}
		// 在第三部分绘制第二部分结果
		for (i = 0; i < 256; i++)
		{
			for (j = 0; j < 256; j++)
			{
				putpixel (i + 20, j + 330, getpixel (i + 320, j + 30));
			}
		}
		FlushBatchDraw ();
		Sleep (500);
		// 在第三部分进行 Arnold 反变换
		for (t = 0; t < T; t++)
		{
			// 变换
			for (i = 0; i < 256; i++)
			{
				for (j = 0; j < 256; j++)
				{
					x = (i + B * j) % 256;
					y = (A * i + (A * B + 1) * j) % 256;
					boxm[i][j].color = getpixel (x + 20, y + 330);
					boxm[i][j].posx = i;
					boxm[i][j].posy = j;

				}
			}

			// 绘制
			for (i = 0; i < 256; i++)
			{
				for (j = 0; j < 256; j++)
				{
					putpixel (boxm[i][j].posx + 20, boxm[i][j].posy + 330, boxm[i][j].color);
				}
			}
			FlushBatchDraw ();
			Sleep (500);
		}
		break;
	}
	// DCT 变换
	case 10:
	{
		// 灰度图
		outtextxy (410, 5, _T ("灰度图像"));
		outtextxy (110, 305, _T ("DCT 正变换"));
		outtextxy (410, 305, _T ("DCT 反变换"));
		// 取第一部分灰度值,在第二部分绘制灰度图
		for (i = 0; i < 256 * 256; i++)
		{
			// 存储二维像素值
			box[i % 256][i / 256] = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256.0 / 256.0;
			// 在第二部分绘制结果
			putpixel (i % 256 + 320, i / 256 + 30, RGB (box[i % 256][i / 256], box[i % 256][i / 256], box[i % 256][i / 256]));
		}
		FlushBatchDraw ();
		// DCT 正变换
		// 大图分割成小图
		for (posx = 0; posx < 256; posx += int (T))
		{
			for (posy = 0; posy < 256; posy += int (T))
			{
				// 小图分割成格子
				for (m = posx; m < posx + T; m++)
				{
					for (n = posy; n < posy + T; n++)
					{
						// 变换
						box1[m][n] = 0;
						for (i = 0; i < T; i++)
						{
							for (j = 0; j < T; j++)
							{
								box1[m][n] += box[posx + i][posy + j] * cos (double ((2 * i + 1) * (m - posx)) * pi / (2 * T)) * cos (double ((2 * j + 1) * (n - posy)) * pi / (2 * T)) / T * ((m - posx) != 0 ? sqrt (2.0) : 1.0) * ((n - posy) != 0 ? sqrt (2.0) : 1.0);
							}
						}
						// 在第三部分绘制结果
						putpixel (m + 20, n + 330, RGB (box1[m][n], box1[m][n], box1[m][n]));
					}
				}
			}
		}
		FlushBatchDraw ();
		// DCT 反变换
		// 大图分割成小图
		for (posx = 0; posx < 256; posx += int (T))
		{
			for (posy = 0; posy < 256; posy += int (T))
			{
				// 小图分割成格子
				for (m = posx; m < posx + T; m++)
				{
					for (n = posy; n < posy + T; n++)
					{
						// 变换
						box[m][n] = 0;
						for (i = 0; i < T; i++)
						{
							for (j = 0; j < T; j++)
							{
								box[m][n] += box1[posx + i][posy + j] * cos (double ((2 * (m - posx) + 1) * i) * pi / (2 * T)) * cos (double ((2 * (n - posy) + 1) * j) * pi / (2 * T)) / T * (i != 0 ? sqrt (2.0) : 1.0) * (j != 0 ? sqrt (2.0) : 1.0);
							}
						}
						// 在第四部分绘制结果
						putpixel (m + 320, n + 330, RGB (box[m][n], box[m][n], box[m][n]));
					}
				}
			}
		}
		FlushBatchDraw ();
		break;
	}
	// Haar 小波变换
	case 11:
	{
		// 灰度图
		outtextxy (410, 5, _T ("灰度图像"));
		outtextxy (110, 305, _T ("小波正变换"));
		outtextxy (410, 305, _T ("小波反变换"));
		// 取第一部分灰度值
		for (i = 0; i < 256 * 256; i++)
		{
			// 存储二维像素值
			box[i % 256][i / 256] = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256.0 / 256.0;
			// 在第二部分绘制结果
			putpixel (i % 256 + 320, i / 256 + 30, RGB (box[i % 256][i / 256], box[i % 256][i / 256], box[i % 256][i / 256]));
		}
		FlushBatchDraw ();
		// 临时储存
		for (i = 0; i < 256; i++)
		{
			for (j = 0; j < 256; j++)
			{
				eat2[i][j] = box[i][j];
			}
		}
		// 在第三部分小波变换
		// 每一级降一半
		for (k = 256; k >= 256 / 2; k = k / 2)
		{
			// 变换
			for (j = 0; j <= k; j++)
			{
				for (i = 0; i <= k / 2; i++)
				{
					eat[i][j] = (eat2[i * 2][j] + eat2[i * 2 + 1][j]) / 2.0;
				}
				for (i = k / 2 + 1; i <= k; i++)
				{
					eat[i][j] = (eat2[(i - (k / 2 + 1)) * 2][j] - eat2[(i - (k / 2 + 1)) * 2 + 1][j]) / 2.0;
				}
				for (i = 0; i <= k; i++)
				{
					eat2[i][j] = eat[i][j];
				}
			}
			for (i = 0; i <= k; i++)
			{
				for (j = 0; j <= k / 2; j++)
				{
					eat[i][j] = (eat2[i][j * 2] + eat2[i][j * 2 + 1]) / 2.0;
				}
				for (j = k / 2 + 1; j <= k; j++)
				{
					eat[i][j] = (eat2[i][(j - (k / 2 + 1)) * 2] - eat2[i][(j - (k / 2 + 1)) * 2 + 1]) / 2.0;
				}
				for (j = 0; j <= k; j++)
				{
					eat2[i][j] = eat[i][j];
				}
			}
		}
		// 在第三部分绘制结果
		for (i = 0; i < 256; i++)
		{
			for (j = 0; j < 256; j++)
			{
				putpixel (i + 20, j + 330, RGB (eat2[i][j], eat2[i][j], eat2[i][j]));
			}
		}
		FlushBatchDraw ();
		// 在第四部分小波反变换
		// 每一级降一半
		for (k = 256 / 2; k <= 256; k = k * 2)
		{
			// 变换
			for (i = 0; i <= k; i++)
			{
				for (j = 0; j <= k / 2; j++)
				{
					eat[i][j * 2] = eat2[i][j] + eat2[i][j + k / 2 + 1];
					eat[i][j * 2 + 1] = eat2[i][j] - eat2[i][j + k / 2 + 1];
				}
				for (j = 0; j <= k; j++)
				{
					eat2[i][j] = eat[i][j];
				}
			}
			for (j = 0; j <= k; j++)
			{
				for (i = 0; i <= k / 2; i++)
				{
					eat[i * 2][j] = eat2[i][j] + eat2[i + k / 2 + 1][j];
					eat[i * 2 + 1][j] = eat2[i][j] - eat2[i + k / 2 + 1][j];
				}
				for (i = 0; i <= k; i++)
				{
					eat2[i][j] = eat[i][j];
				}
			}
		}
		// 在第四部分绘制结果
		for (i = 0; i < 256; i++)
		{
			for (j = 0; j < 256; j++)
			{
				putpixel (i + 320, j + 330, RGB (eat2[i][j], eat2[i][j], eat2[i][j]));
			}
		}
		FlushBatchDraw ();
		break;
	}
	// 均值滤波
	case 12:
	{
		// 被处理图像
		putimage (20, 30, &img[1]);
		FlushBatchDraw ();
		// 灰度图
		outtextxy (410, 5, _T ("灰度图像"));
		outtextxy (410, 305, _T ("平滑结果"));
		// 取第一部分灰度值,在第二部分绘制灰白图
		for (i = 0; i < 256; i++)
		{
			g[i] = 0;
		}
		for (i = 0; i < 256 * 256; i++)
		{
			j = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256 / 256;
			g[j]++;
			putpixel (i % 256 + 320, i / 256 + 30, RGB (j, j, j));
		}
		FlushBatchDraw ();
		// 在第四部分平滑图图
		for (i = 0; i < 256 * 256; i++)
		{
			if (i % 256 != 0 && i / 256 != 0)
			{
				if (mod == 0)
				{
					// 八近邻平均值
					k = (getpixel (i % 256 + 320 - 1, i / 256 + 30 - 1) / 256 / 256 +
						getpixel (i % 256 + 320 - 1, i / 256 + 30) / 256 / 256 +
						getpixel (i % 256 + 320 - 1, i / 256 + 30 + 1) / 256 / 256 +
						getpixel (i % 256 + 320, i / 256 + 30 - 1) / 256 / 256 +
						getpixel (i % 256 + 320, i / 256 + 30) / 256 / 256 +
						getpixel (i % 256 + 320, i / 256 + 30 + 1) / 256 / 256 +
						getpixel (i % 256 + 320 + 1, i / 256 + 30 - 1) / 256 / 256 +
						getpixel (i % 256 + 320 + 1, i / 256 + 30) / 256 / 256 +
						getpixel (i % 256 + 320 + 1, i / 256 + 30 + 1) / 256 / 256)
						/ 8;
				}
				else if (mod == 1)
				{
					// 高斯系数
					k = (1 * getpixel (i % 256 + 320 - 1, i / 256 + 30 - 1) / 256 / 256 +
						2 * getpixel (i % 256 + 320 - 1, i / 256 + 30) / 256 / 256 +
						1 * getpixel (i % 256 + 320 - 1, i / 256 + 30 + 1) / 256 / 256 +
						2 * getpixel (i % 256 + 320, i / 256 + 30 - 1) / 256 / 256 +
						4 * getpixel (i % 256 + 320, i / 256 + 30) / 256 / 256 +
						2 * getpixel (i % 256 + 320, i / 256 + 30 + 1) / 256 / 256 +
						1 * getpixel (i % 256 + 320 + 1, i / 256 + 30 - 1) / 256 / 256 +
						2 * getpixel (i % 256 + 320, i / 256 + 30) / 256 / 256 +
						1 * getpixel (i % 256 + 320 + 1, i / 256 + 30 + 1) / 256 / 256)
						/ 16;
				}
				if (k > 255)k = 255;
				// 绘制
				putpixel (i % 256 + 320, i / 256 + 330, RGB (k, k, k));
			}
			else {}
		}
		FlushBatchDraw ();
		break;
	}
	// 中值滤波
	case 13:
	{
		// 被处理图像
		putimage (20, 30, &img[1]);
		FlushBatchDraw ();
		// 灰度图
		outtextxy (410, 5, _T ("灰度图像"));
		outtextxy (410, 305, _T ("平滑结果"));
		// 取第一部分灰度值,在第二部分绘制灰白图
		for (i = 0; i < 256; i++)
		{
			g[i] = 0;
		}
		for (i = 0; i < 256 * 256; i++)
		{
			j = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256 / 256;
			g[j]++;
			putpixel (i % 256 + 320, i / 256 + 30, RGB (j, j, j));
		}
		FlushBatchDraw ();
		// 在第四部分中值滤波结果
		for (i = 0; i < 256 * 256; i++)
		{
			t = 0;
			// 取 (2*T+1)^2 格的像素值
			for (j = -int (T); j <= T; j++)
			{
				for (k = -int (T); k <= T; k++)
				{
					g[t] = getpixel (i % 256 + 320 + j, i / 256 + 30 + k) / 256 / 256;
					t++;
				}
			}
			// 冒泡排序
			for (j = 0; j < pow (2 * T + 1, 2) - 1; j++)
			{
				for (k = int (pow (2 * T + 1, 2) - 1); k > j; k--)
				{
					if (g[k] < g[k - 1])
					{
						t = g[k];
						g[k] = g[k - 1];
						g[k - 1] = t;
					}
				}
			}
			// 取中值作为新像素值并绘制
			putpixel (i % 256 + 320, i / 256 + 330, RGB (g[13], g[13], g[13]));
		}
		FlushBatchDraw ();
		break;
	}
	// FFT 变换
	case 14:
	{
		// 灰度图
		outtextxy (410, 5, _T ("灰度图像"));
		outtextxy (110, 305, _T ("傅里叶变换"));
		outtextxy (410, 305, _T ("傅里叶反变换"));
		// 取第一部分灰度值,在第二部分绘制灰度图
		for (i = 0; i < 256 * 256; i++)
		{
			// 存储二维像素值
			box[i % 256][i / 256] = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256 / 256;
			putpixel (i % 256 + 320, i / 256 + 30, RGB (box[i % 256][i / 256], box[i % 256][i / 256], box[i % 256][i / 256]));
			if ((i % 256 + i / 256) % 2 == 1)
			{
				// 调整傅里叶结果中心点
				box[i % 256][i / 256] *= -1;
			}
		}
		FlushBatchDraw ();
		// 在第三部分绘制傅里叶变换
		for (m = 0; m < 256; m++)
		{
			for (n = 0; n < 256; n++)
			{
				Xn[m][n].Re = 0;
				Xn[m][n].Im = 0;
				for (i = 0; i < 256; i++)
				{
					// 傅里叶变换
					for (j = 0; j < 256; j++)
					{
						Xn[m][n].Re = Xn[m][n].Re + box[i][j] * cos (2.0 * pi * double (m * i + n * j) / 256);
						Xn[m][n].Im = Xn[m][n].Im - box[i][j] * sin (2.0 * pi * double (m * i + n * j) / 256);
					}
				}
				// 将傅里叶结果做对数使其易于观察
				eat[m][n] = log (1 + sqrt (Xn[m][n].Re * Xn[m][n].Re + Xn[m][n].Im * Xn[m][n].Im)) / log (1.05);
				// 将傅里叶中心直流分量过大导致黑色的点变更为白色,0 是黑色,1 是白色
				if (eat[m][n] > 255) { eat[m][n] = 255; }
				putpixel (m + 20, n + 330, RGB (eat[m][n], eat[m][n], eat[m][n]));
			}
		}
		FlushBatchDraw ();
		// 在第四部分反傅里叶变换
		for (m = 0; m < 256; m++)
		{
			for (n = 0; n < 256; n++)
			{
				Xm[m][n].Re = 0;
				Xm[m][n].Im = 0;
				for (i = 0; i < 256; i++)
				{
					for (j = 0; j < 256; j++)
					{
						// 傅里叶反变换,不加虚部会出现斜的虚边
						Xm[m][n].Re = Xm[m][n].Re + Xn[i][j].Re * cos (2.0 * pi * double (m * i + n * j) / 256) - Xn[i][j].Im * sin (2.0 * pi * double (m * i + n * j) / 256);
						Xm[m][n].Im = Xm[m][n].Im + Xn[i][j].Re * sin (2.0 * pi * double (m * i + n * j) / 256) + Xn[i][j].Im * cos (2.0 * pi * double (m * i + n * j) / 256);
					}
				}
				// 结果取模
				box[m][n] = sqrt (Xm[m][n].Re * Xm[m][n].Re + Xm[m][n].Im * Xm[m][n].Im) / 256 / 256;
				if (box[m][n] > 255) { box[m][n] = 255; }
				putpixel (m + 320, n + 330, RGB (box[m][n], box[m][n], box[m][n]));
			}
		}
		FlushBatchDraw ();
		break;
	}
	// 低通滤波
	case 15:
	{
		// 被处理图像
		putimage (20, 30, &img[1]);
		FlushBatchDraw ();
		// 灰度图
		outtextxy (110, 5, _T ("灰度图像"));
		outtextxy (410, 5, _T ("傅里叶变换"));
		outtextxy (110, 305, _T ("滤波"));
		outtextxy (410, 305, _T ("傅里叶反变换"));
		// 取第一部分灰度值,在第一部分绘制灰度图像
		for (i = 0; i < 256 * 256; i++)
		{
			// 存储二维像素值
			box[i % 256][i / 256] = RGBtoGRAY (getpixel (i % 256 + 20, i / 256 + 30)) / 256 / 256;
			putpixel (i % 256 + 20, i / 256 + 30, RGB (box[i % 256][i / 256], box[i % 256][i / 256], box[i % 256][i / 256]));
			// 调整傅里叶结果中心点
			if ((i % 256 + i / 256) % 2 == 1)
			{
				box[i % 256][i / 256] *= -1;
			}
		}
		FlushBatchDraw ();
		// 在第二部分绘制傅里叶变换
		for (m = 0; m < 256; m++)
		{
			for (n = 0; n < 256; n++)
			{
				Xn[m][n].Re = 0;
				Xn[m][n].Im = 0;
				// 傅里叶变换
				for (i = 0; i < 256; i++)
				{
					for (j = 0; j < 256; j++)
					{
						Xn[m][n].Re = Xn[m][n].Re + box[i][j] * cos (2.0 * pi * double (m * i + n * j) / 256);
						Xn[m][n].Im = Xn[m][n].Im - box[i][j] * sin (2.0 * pi * double (m * i + n * j) / 256);
					}
				}
				// 将傅里叶结果做对数使其易于观察
				eat[m][n] = log (1 + sqrt (Xn[m][n].Re * Xn[m][n].Re + Xn[m][n].Im * Xn[m][n].Im)) / log (1.05);
				// 将傅里叶中心直流分量过大导致黑色的点变更为白色,0 是黑色,1 是白色
				if (eat[m][n] > 255) { eat[m][n] = 255; }
				putpixel (m + 320, n + 30, RGB (eat[m][n], eat[m][n], eat[m][n]));
			}
		}
		FlushBatchDraw ();
		// 在第三部分滤波
		if (mod == 0)
		{
			// 理想
			for (m = 0; m < 256; m++)
			{
				for (n = 0; n < 256; n++)
				{
					if (pow (double (m - 128), 2) + pow (double (n - 128), 2) > T * T)
					{
						Xn[m][n].Re = 0;
						Xn[m][n].Im = 0;
					}
				}
			}
		}
		else if (mod == 1)
		{
			// 高斯
			for (m = 0; m < 256; m++)
			{
				for (n = 0; n < 256; n++)
				{
					Xn[m][n].Re = Xn[m][n].Re * exp (-pow (sqrt (double ((m - 128) * (m - 128) + (n - 128) * (n - 128))), 2) / 2 / T / T);
					Xn[m][n].Im = Xn[m][n].Im * exp (-pow (sqrt (double ((m - 128) * (m - 128) + (n - 128) * (n - 128))), 2) / 2 / T / T);
				}
			}
		}
		else if (mod == 2)
		{
			// 巴特沃斯
			for (m = 0; m < 256; m++)
			{
				for (n = 0; n < 256; n++)
				{
					Xn[m][n].Re = Xn[m][n].Re / (1 + pow (sqrt (double ((m - 128) * (m - 128) + (n - 128) * (n - 128))) / T, 2));
					Xn[m][n].Im = Xn[m][n].Im / (1 + pow (sqrt (double ((m - 128) * (m - 128) + (n - 128) * (n - 128))) / T, 2));
				}
			}
		}
		// 在第三部分绘制滤波结果
		for (m = 0; m < 256; m++)
		{
			for (n = 0; n < 256; n++)
			{
				eat[m][n] = log (1 + sqrt (Xn[m][n].Re * Xn[m][n].Re + Xn[m][n].Im * Xn[m][n].Im)) / log (1.05);
				if (eat[m][n] > 255) { eat[m][n] = 255; }
				putpixel (m + 20, n + 330, RGB (eat[m][n], eat[m][n], eat[m][n]));
			}
		}
		FlushBatchDraw ();
		// 在第四部分反傅里叶变换
		for (m = 0; m < 256; m++)
		{
			for (n = 0; n < 256; n++)
			{
				Xm[m][n].Re = 0;
				Xm[m][n].Im = 0;
				for (i = 0; i < 256; i++)
				{
					for (j = 0; j < 256; j++)
					{
						// 傅里叶反变换,不加虚部会出现斜的虚边
						Xm[m][n].Re = Xm[m][n].Re + Xn[i][j].Re * cos (2.0 * pi * double (m * i + n * j) / 256) - Xn[i][j].Im * sin (2.0 * pi * double (m * i + n * j) / 256);
						Xm[m][n].Im = Xm[m][n].Im + Xn[i][j].Re * sin (2.0 * pi * double (m * i + n * j) / 256) + Xn[i][j].Im * cos (2.0 * pi * double (m * i + n * j) / 256);
					}
				}
				// 结果取模
				box[m][n] = sqrt (Xm[m][n].Re * Xm[m][n].Re + Xm[m][n].Im * Xm[m][n].Im) / 256 / 256;
				if (box[m][n] > 255) { box[m][n] = 255; }
				putpixel (m + 320, n + 330, RGB (box[m][n], box[m][n], box[m][n]));
			}
		}
		FlushBatchDraw ();
		break;
	}
	// 分裂图
	case 16:
	{
		// 重新回到绘制缓存
		BeginBatchDraw ();
		// 彩图
		// 被处理图像
		setfillcolor (WHITE);
		fillrectangle (0, 0, 600, 600);
		FlushBatchDraw ();

		putimage (300 - 256, 300 - 256, &img[2]);
		// 临时存储
		for (i = 300 - 256; i < 300 + 256; i++)
		{
			for (j = 300 - 256; j < 300 + 256; j++)
			{
				boxb1[i][j].k1 = GetRValue (getpixel (i, j));
				boxb1[i][j].k2 = GetGValue (getpixel (i, j));
				boxb1[i][j].k3 = GetBValue (getpixel (i, j));
			}
		}

		// 暂时退出绘制缓存
		EndBatchDraw ();
		// 清屏
		setfillcolor (WHITE);
		fillrectangle (0, 0, 600, 600);
		FlushBatchDraw ();

		flag = 1;
		// 初始点
		boxb[0].posx = 300;
		boxb[0].posy = 300;
		boxb[0].R = 256;
		boxb[0].num = 0;

		// 圆圈的分裂,直至阈值宽度
		for (i = 0; i < flag; i++)
		{
			if (boxb[i].R > T)
			{
				boxb[flag].R = boxb[i].R / 2;
				boxb[flag].posx = int (boxb[i].posx - boxb[i].R / 2);
				boxb[flag].posy = int (boxb[i].posy - boxb[i].R / 2);
				boxb[flag].num = flag;

				boxb[flag + 1].R = boxb[i].R / 2;
				boxb[flag + 1].posx = int (boxb[i].posx + boxb[i].R / 2);
				boxb[flag + 1].posy = int (boxb[i].posy - boxb[i].R / 2);
				boxb[flag + 1].num = flag + 1;

				boxb[flag + 2].R = boxb[i].R / 2;
				boxb[flag + 2].posx = int (boxb[i].posx - boxb[i].R / 2);
				boxb[flag + 2].posy = int (boxb[i].posy + boxb[i].R / 2);
				boxb[flag + 2].num = flag + 2;

				boxb[flag + 3].R = boxb[i].R / 2;
				boxb[flag + 3].posx = int (boxb[i].posx + boxb[i].R / 2);
				boxb[flag + 3].posy = int (boxb[i].posy + boxb[i].R / 2);
				boxb[flag + 3].num = flag + 3;

				boxb[i].boxnum[0] = flag;
				boxb[i].boxnum[1] = flag + 1;
				boxb[i].boxnum[2] = flag + 2;
				boxb[i].boxnum[3] = flag + 3;

				// 一变四
				flag += 4;
			}
			// 进度展示
			_stprintf_s (s, _T ("%0.1d"), i);	outtextxy (box_button[4].posx1 + 2, box_button[4].posy1 + 2, s);
		}

		// 圆圈颜色的处理
		for (k = 0; k < flag; k++)
		{
			boxb[k].k1 = 0;
			boxb[k].k2 = 0;
			boxb[k].k3 = 0;
			// 圆范围的值求和
			for (i = int (boxb[k].posx - boxb[k].R); i < int (boxb[k].posx + boxb[k].R); i++)
			{
				for (j = int (boxb[k].posy - boxb[k].R); j < int (boxb[k].posy + boxb[k].R); j++)
				{
					boxb[k].k1 += boxb1[i][j].k1;
					boxb[k].k2 += boxb1[i][j].k2;
					boxb[k].k3 += boxb1[i][j].k3;
				}
			}
			// 圆范围的值取平均
			boxb[k].k1 /= (4.0 * boxb[k].R * boxb[k].R);
			boxb[k].k2 /= (4.0 * boxb[k].R * boxb[k].R);
			boxb[k].k3 /= (4.0 * boxb[k].R * boxb[k].R);
			// 进度展示
			_stprintf_s (s, _T ("%0.1d"), k);	outtextxy (box_button[5].posx1 + 2, box_button[5].posy1 + 2, s);
		}

		flag1 = 1;
		eatb[0].boxnum = 0;

		// 画初始圆
		setfillcolor (RGB (boxb[eatb[0].boxnum].k1, boxb[eatb[0].boxnum].k2, boxb[eatb[0].boxnum].k3));
		solidcircle (boxb[eatb[0].boxnum].posx, boxb[eatb[0].boxnum].posy, int (boxb[eatb[0].boxnum].R));
		FlushBatchDraw ();

		// 进程控制参数定义
		int exit2 = 0;
		// 鼠标定义
		ExMessage m;

		while (exit2 == 0)
		{
			if (peekmessage (&m, EM_MOUSE | EM_KEY))
			{
				// 鼠标移动判断
				if (m.message == WM_MOUSEMOVE)
				{
					// 是否移动到一个可分裂圆之上
					for (i = 0; i < flag1; i++)
					{
						// 移动到了
						if (pow (double (m.x - boxb[eatb[i].boxnum].posx), 2) + pow (double (m.y - boxb[eatb[i].boxnum].posy), 2)
							<= boxb[eatb[i].boxnum].R * boxb[eatb[i].boxnum].R && boxb[eatb[i].boxnum].R > T)
						{
							// 清空该圆所在区域
							setfillcolor (WHITE);
							clearcircle (boxb[eatb[i].boxnum].posx, boxb[eatb[i].boxnum].posy, int (boxb[eatb[i].boxnum].R));
							// 画分裂之后的新四个小圆,有点像四叉树
							// 小圆参数添加
							eatb[flag1 + 2].boxnum = boxb[eatb[i].boxnum].boxnum[3];
							eatb[flag1 + 1].boxnum = boxb[eatb[i].boxnum].boxnum[2];
							eatb[flag1].boxnum = boxb[eatb[i].boxnum].boxnum[1];
							eatb[flag1 + 3].boxnum = boxb[eatb[i].boxnum].boxnum[0];
							k = 0;
							for (j = 0; j < flag1; j++)
							{
								if (j != i)
								{
									eatb[k].boxnum = boxb[eatb[j].boxnum].num;
									k++;
								}
							}
							eatb[flag1 - 1].boxnum = eatb[flag1 + 3].boxnum;
							// 总数多三个
							flag1 += 3;
							// 绘制
							for (j = flag1 - 4; j < flag1; j++)
							{
								setfillcolor (RGB (boxb[eatb[j].boxnum].k1, boxb[eatb[j].boxnum].k2, boxb[eatb[j].boxnum].k3));
								solidcircle (boxb[eatb[j].boxnum].posx, boxb[eatb[j].boxnum].posy, int (boxb[eatb[j].boxnum].R));
							}
							FlushBatchDraw ();
							break;
						}
					}
				}
				// 点击退出按钮
				else if (m.message == WM_LBUTTONDOWN && (m.x > box_button[1].posx1 && m.y > box_button[1].posy1 && m.x < box_button[1].posx2 && m.y < box_button[1].posy2))
				{
					exit2 = 1;
					// 清屏
					draw_scene ();
				}
			}
		}
		break;
	}
	default:break;
	}
	FlushBatchDraw ();
	// 重新回到绘制缓存
	BeginBatchDraw ();
	FlushBatchDraw ();
}

// 界面绘制函数
void Gary::draw_scene ()
{
	POINT pts[3];
	TCHAR s[25];
	int i, j, k;
	// 背景绘制
	setbkcolor (WHITE);
	cleardevice ();

	// 框框范围绘制
	setfillcolor (WHITE);
	setlinecolor (BLACK);
	setlinestyle (PS_SOLID, 2);
	fillrectangle (0, 0, 903, 600);
	fillrectangle (0, 0, 600, 600);

	// 列表框绘制
	for (k = 0; k < num_list; k++)
	{
		// 清理区域
		setfillcolor (RGB (128, 128, 128));
		setlinecolor (RGB (128, 254, 0));
		setlinestyle (PS_SOLID, 2);
		fillrectangle (box_list[k].posx1, box_list[k].posy1, box_list[k].posx2, box_list[k].posy2);
		line (box_list[k].posx2 - 40, box_list[k].posy1, box_list[k].posx2 - 40, box_list[k].posy2);


		// 三角箭头的绘制
		setfillcolor (RGB (128, 254, 0));
		setlinecolor (RGB (35, 33, 168));

		i = 0;
		pts[0].x = box_list[k].box_button[i].posx1;			pts[0].y = box_list[k].box_button[i].posy2;
		pts[1].x = box_list[k].box_button[i].posx2;			pts[1].y = box_list[k].box_button[i].posy2;
		pts[2].x = box_list[k].box_button[i].posx1 + 19;	pts[2].y = box_list[k].box_button[i].posy1;
		fillpolygon (pts, 3);

		i = 1;
		pts[0].x = box_list[k].box_button[i].posx1;			pts[0].y = box_list[k].box_button[i].posy1;
		pts[1].x = box_list[k].box_button[i].posx2;			pts[1].y = box_list[k].box_button[i].posy1;
		pts[2].x = box_list[k].box_button[i].posx1 + 19;	pts[2].y = box_list[k].box_button[i].posy2;
		fillpolygon (pts, 3);

		// 滑条的绘制
		setfillcolor (RGB (128, 254, 0));
		i = 2;
		fillrectangle (box_list[k].box_button[i].posx1,
			box_list[k].box_button[i].posy1,
			box_list[k].box_button[i].posx2,
			box_list[k].box_button[i].posy2);

		double size = 38;
		// 文本绘制
		// 参数设置,填充透明
		setbkmode (TRANSPARENT);
		settextstyle (int (size), int (size / 5 * 2), _T ("Consolas"));
		settextcolor (RGB (35, 33, 168));

		j = int (
			(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
			((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
				(box_list[k].all_text_num - box_list[k].every_text_num + 1))
			);

		for (i = 0; i < box_list[k].every_text_num; i++)
		{
			if (i + 3 + j == box_list[k].flag_text_num)
			{
				fillrectangle (box_list[k].box_button[i + 3].posx1,
					box_list[k].box_button[i + 3].posy1,
					box_list[k].box_button[i + 3].posx2,
					box_list[k].box_button[i + 3].posy2);
			}
			outtextxy (box_list[k].box_button[i + 3].posx1,
				box_list[k].box_button[i + 3].posy1,
				box_list[k].box_button[i + 3 + j].text);
		}
		// 恢复填充
		setbkmode (OPAQUE);
	}

	// 设置参数
	setlinecolor (RGB (125, 125, 125));
	setbkcolor (WHITE);
	settextcolor (BLACK);
	settextstyle (25, 9, _T ("Consolas"));
	setlinestyle (PS_SOLID, 2);

	// 根据按钮数量,按钮类型参数绘制
	for (i = 0; i < num_button; i++)
	{
		setfillcolor (WHITE);
		// 边框
		fillrectangle (box_button[i].posx1, box_button[i].posy1, box_button[i].posx2, box_button[i].posy2);
		// 矩形激活按钮
		if (box_button[i].type == 1)
		{
			// 文字
			outtextxy (box_button[i].posx1 + (box_button[i].posx2 - box_button[i].posx1) / 2 - textwidth (box_button[i].text) / 2, box_button[i].posy1 + 6, box_button[i].text);
		}
	}

	// 界面绘制
	fillrectangle (0, 0, 300, 300);
	fillrectangle (300, 0, 600, 300);
	fillrectangle (0, 300, 300, 600);
	fillrectangle (300, 300, 600, 600);
	outtextxy (110, 5, _T ("原始图像"));

	// 原图加载
	putimage (20, 30, &img[0]);

	// 参数绘制
	i = 24; j = 30;

	// 按钮绘制
	switch (box_list[0].flag_text_num)
	{
		// 图像旋转
	case 3:
	{
		_stprintf_s (s, _T ("%0.1f"), T);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		break;
	}
	// 直方图均衡化
	case 4:
	{
		_stprintf_s (s, _T ("%0.0f"), T);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		_stprintf_s (s, _T ("%0.1d"), A);	outtextxy (box_button[3].posx1 + i, box_button[3].posy1 + j, s);
		_stprintf_s (s, _T ("%0.1d"), B);	outtextxy (box_button[6].posx1 + i, box_button[6].posy1 + j, s);
		break;
	}
	// 图像分割
	case 5:
	{
		_stprintf_s (s, _T ("%0.0f"), T);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		break;
	}
	// 伪色彩填充
	case 6:
	{
		break;
	}
	// 图像锐化
	case 7:
	{
		_stprintf_s (s, _T ("%0.1f"), T);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		if (mod == 0) { outtextxy (box_button[1].posx1 + i - 15, box_button[1].posy1 + j, _T ("四近邻")); }
		else if (mod == 1) { outtextxy (box_button[1].posx1 + i - 15, box_button[1].posy1 + j, _T ("八近邻")); }
		break;
	}
	// 图像模糊
	case 8:
	{
		_stprintf_s (s, _T ("%0.1f"), T);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		break;
	}
	// Arnold 变换
	case 9:
	{
		_stprintf_s (s, _T ("%0.1f"), T);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		_stprintf_s (s, _T ("%0.1d"), A);	outtextxy (box_button[3].posx1 + i, box_button[3].posy1 + j, s);
		_stprintf_s (s, _T ("%0.1d"), B);	outtextxy (box_button[6].posx1 + i, box_button[6].posy1 + j, s);
		break;
	}
	// DCT 变换
	case 10:
	{
		_stprintf_s (s, _T ("%0.0f"), T);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		break;
	}
	// Haar 变换
	case 11:
	{
		break;
	}
	// 均值滤波
	case 12:
	{
		outtextxy (box_button[mod].posx1 + i, box_button[mod].posy1 + j, _T ("是"));
		if (mod == 0)
		{
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[3].posx1 + i, box_button[3].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[4].posx1 + i, box_button[4].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[5].posx1 + i, box_button[5].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[6].posx1 + i, box_button[6].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[7].posx1 + i, box_button[7].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[8].posx1 + i, box_button[8].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[9].posx1 + i, box_button[9].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[10].posx1 + i, box_button[10].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[11].posx1 + i, box_button[11].posy1 + j, s);
		}
		else if (mod == 1)
		{
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[3].posx1 + i, box_button[3].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 2);	outtextxy (box_button[4].posx1 + i, box_button[4].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[5].posx1 + i, box_button[5].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 2);	outtextxy (box_button[6].posx1 + i, box_button[6].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 4);	outtextxy (box_button[7].posx1 + i, box_button[7].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 2);	outtextxy (box_button[8].posx1 + i, box_button[8].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[9].posx1 + i, box_button[9].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 2);	outtextxy (box_button[10].posx1 + i, box_button[10].posy1 + j, s);
			_stprintf_s (s, _T ("%0.1d"), 1);	outtextxy (box_button[11].posx1 + i, box_button[11].posy1 + j, s);
		}
		break;
	}
	// 中值滤波
	case 13:
	{
		_stprintf_s (s, _T ("%0.0f"), T);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		break;
	}
	// FFT 变换
	case 14:
	{
		break;
	}
	// 低通滤波
	case 15:
	{
		_stprintf_s (s, _T ("%0.1f"), T);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		if (mod == 0) { outtextxy (box_button[1].posx1 + i, box_button[1].posy1 + j, _T ("理想")); }
		else if (mod == 1) { outtextxy (box_button[1].posx1 + i, box_button[1].posy1 + j, _T ("高斯")); }
		else if (mod == 2) { outtextxy (box_button[1].posx1 + i - 20, box_button[1].posy1 + j, _T ("巴特沃斯")); }
		break;
	}
	// 分裂图
	case 16:
	{
		_stprintf_s (s, _T ("%0.0f"), T);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		break;
	}
	default:break;
	}
	FlushBatchDraw ();
}

// 初始化函数
void Gary::initialization ()
{
	int i, j;
	TCHAR ss[25];

	// 背景绘制
	setbkcolor (WHITE);
	cleardevice ();
	FlushBatchDraw ();

	// 图片初始化
	i = MessageBox (hOut, _T ("是否使用默认图片"), _T ("来自小豆子的提醒"), MB_YESNO);
	if (i == 6)
	{
		// 大部分图像处理所用图片
		loadimage (&img[0], _T ("t0.png"), 256, 256);
		// 滤波处理所用图片
		loadimage (&img[1], _T ("t1.png"), 256, 256);
		// 分裂图所用图片
		loadimage (&img[2], _T ("t2.png"), 512, 512);
	}
	else if (i == 7)
	{
		InputBox (ss, 10, _T ("输入图片相对位置及名称"));
		// 大部分图像处理所用图片
		loadimage (&img[0], ss, 256, 256);
		// 滤波处理所用图片
		loadimage (&img[1], ss, 256, 256);
		// 分裂图所用图片
		loadimage (&img[2], ss, 512, 512);
	}

	// 列表框数量
	num_list = 1;

	// 列表框初始化

	// 每个列表框的不同之处
	j = 0;
	// 列表框范围坐标
	box_list[j].posx1 = 602;
	box_list[j].posy1 = 2;
	box_list[j].posx2 = 902;
	box_list[j].posy2 = 302;
	// 每次展示数量
	box_list[j].every_text_num = 7;
	// 之后的文本按钮
	// 数量
	box_list[j].all_text_num = 14;
	// 内容
	box_list[j].box_button[3].text = _T ("图像旋转");
	box_list[j].box_button[4].text = _T ("直方图均衡化");
	box_list[j].box_button[5].text = _T ("图像分割");
	box_list[j].box_button[6].text = _T ("伪色彩填充");
	box_list[j].box_button[7].text = _T ("图像锐化");
	box_list[j].box_button[8].text = _T ("图像模糊");
	box_list[j].box_button[9].text = _T ("Arnold 变换");
	box_list[j].box_button[10].text = _T ("DCT 变化");
	box_list[j].box_button[11].text = _T ("Haar 小波变换 ");
	box_list[j].box_button[12].text = _T ("均值滤波");
	box_list[j].box_button[13].text = _T ("中值滤波");
	box_list[j].box_button[14].text = _T ("FFT 变换");
	box_list[j].box_button[15].text = _T ("低通滤波");
	box_list[j].box_button[16].text = _T ("分裂图");

	// 每个列表框的共同之处
	for (j = 0; j < num_list; j++)
	{
		// 前三个按钮是固定的
		box_list[j].box_button[0].posx1 = box_list[j].posx2 - 40 + 2;
		box_list[j].box_button[0].posy1 = box_list[j].posy1 + 2;
		box_list[j].box_button[0].posx2 = box_list[j].posx2 - 2;
		box_list[j].box_button[0].posy2 = box_list[j].posy1 + 50 - 2;

		box_list[j].box_button[1].posx1 = box_list[j].posx2 - 40 + 2;
		box_list[j].box_button[1].posy1 = box_list[j].posy2 - 50 + 2;
		box_list[j].box_button[1].posx2 = box_list[j].posx2 - 2;
		box_list[j].box_button[1].posy2 = box_list[j].posy2 - 2;

		box_list[j].box_button[2].posx1 = box_list[j].posx2 - 40 + 2;
		box_list[j].box_button[2].posy1 = box_list[j].box_button[0].posy2 + 2;
		box_list[j].box_button[2].posx2 = box_list[j].posx2 - 2;
		box_list[j].box_button[2].posy2 = box_list[j].box_button[0].posy2 + 60 - 2;

		// 文本按钮参数设置
		for (i = 0; i < box_list[j].every_text_num; i++)
		{
			box_list[j].box_button[i + 3].posx1 = box_list[j].posx1 + 2;
			box_list[j].box_button[i + 3].posy1 = int (box_list[j].posy1 + i * (box_list[j].posy2 - box_list[j].posy1) / box_list[j].every_text_num + 2);
			box_list[j].box_button[i + 3].posx2 = box_list[j].posx2 - 40 - 2;
			box_list[j].box_button[i + 3].posy2 = int (box_list[j].box_button[i + 3].posy1 + (box_list[j].posy2 - box_list[j].posy1) / box_list[j].every_text_num - 5);
		}

		// 初始选定文本编号初始化
		box_list[j].flag_text_num = 3;
	}

	// 分形参数初始化
	initialization_image ();

	// 按钮的初始化
	num_button = 12;

	// 矩形按钮
	for (i = 0; i < num_button; i++)
	{
		box_button[i].posx1 = 610 + i % 3 * 100;
		box_button[i].posy1 = 320 + i / 3 * 70;
		box_button[i].posx2 = 690 + i % 3 * 100;
		box_button[i].posy2 = 380 + i / 3 * 70;
		box_button[i].type = 0;
	}

	// 初始化
	T = 30;
	box_button[0].text = _T ("角度");		box_button[0].type = 1;
	box_button[1].text = _T ("");
	box_button[2].text = _T ("动画演示");	box_button[2].type = 1;
	box_button[3].text = _T ("");
	box_button[4].text = _T ("");
	box_button[5].text = _T ("");
	box_button[6].text = _T ("");
	box_button[7].text = _T ("");
	box_button[8].text = _T ("");
	box_button[9].text = _T ("");
	box_button[10].text = _T ("");
	box_button[11].text = _T ("");

	// 绘制
	draw_scene ();
}

// 窗口主视角函数,获取用户操作
void Gary::move ()
{
	// 鼠标定义
	ExMessage m;
	TCHAR ss[25];
	int i, k;
	float j;
	// 控制参数置零
	exit_move = 0;

	while (exit_move == 0)
	{
		if (peekmessage (&m, EM_MOUSE | EM_KEY))
		{
			// 左键单击判断
			if (m.message == WM_LBUTTONDOWN)
			{
				// 判断是否点击了列表框
				for (k = 0; k < num_list; k++)
				{
					// 列表框范围
					if (m.x > box_list[k].posx1 && m.y > box_list[k].posy1 && m.x < box_list[k].posx2 && m.y < box_list[k].posy2)
					{
						break;
					}
				}
				// 点击了列表框
				if (k < num_list)
				{
					// 滑条点击
					if (m.x > box_list[k].box_button[2].posx1 && m.x<box_list[k].box_button[2].posx2 && m.y>box_list[k].box_button[2].posy1 && m.y < box_list[k].box_button[2].posy2)
					{
						while (m.message != WM_LBUTTONUP)
						{
							if (peekmessage (&m, EM_MOUSE | EM_KEY))
							{
								j = float (m.y > box_list[k].posy1 + 50 + 30 - 4 ? m.y : box_list[k].posy1 + 50 + 30 - 4);
								j = float (m.y < box_list[k].posy2 - 50 - 30 + 4 ? j : box_list[k].posy2 - 50 - 30 + 4);
								box_list[k].box_button[2].posy1 = int (j - 30 + 2);
								box_list[k].box_button[2].posy2 = int (j + 30 - 2);
								draw_scene ();
							}
						}
						// 第一次绘制
						draw_scene ();
					}
					// 箭头点击
					else if (m.x > box_list[k].box_button[0].posx1 && m.x<box_list[k].box_button[0].posx2 && m.y>box_list[k].box_button[0].posy1 && m.y < box_list[k].box_button[0].posy2)
					{
						if (box_list[k].flag_text_num > 3)
						{
							box_list[k].flag_text_num--;
							// 滑条相对位置编号
							i = int (
								(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
								((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
									(box_list[k].all_text_num - box_list[k].every_text_num + 1))
								);
							// 到顶了,向上需要自动移动滑块
							if (i + 2 >= box_list[k].flag_text_num)
							{
								// 滑条相对位置编号
								j = float (
									(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
									((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
										(box_list[k].all_text_num - box_list[k].every_text_num + 1))
									);
								// 滑条相对位置编号变更
								j--;
								// 滑条相对位置变更
								j = float(
									box_list[k].posy1 + 50 + 30 + j * (
										(box_list[k].posy2 - 100 - box_list[k].posy1 - 50) /
										(box_list[k].all_text_num - box_list[k].every_text_num + 1)
										));
								box_list[k].box_button[2].posy1 = int (j - 30 + 2);
								box_list[k].box_button[2].posy2 = int (j + 30 - 2);
							}
							goto A;
						}
					}
					else if (m.x > box_list[k].box_button[1].posx1 && m.x<box_list[k].box_button[1].posx2 && m.y>box_list[k].box_button[1].posy1 && m.y < box_list[k].box_button[1].posy2)
					{
						if (box_list[k].flag_text_num < box_list[k].all_text_num + 2)
						{
							box_list[k].flag_text_num++;
							// 滑条相对位置编号
							i = int (
								(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
								((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
									(box_list[k].all_text_num - box_list[k].every_text_num + 1))
								);
							// 到底了,向下需要自动移动滑块
							if (i + 10 <= box_list[k].flag_text_num)
							{
								// 滑条相对位置编号
								j = float (
									(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
									((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
										(box_list[k].all_text_num - box_list[k].every_text_num + 1))
									);
								// 滑条相对位置编号变更
								j++;
								// 滑条相对位置变更
								j = float (
									box_list[k].posy1 + 50 + 30 + j * (
										(box_list[k].posy2 - 100 - box_list[k].posy1 - 50) /
										(box_list[k].all_text_num - box_list[k].every_text_num + 1)
										));
								box_list[k].box_button[2].posy1 = int (j - 30 + 2);
								box_list[k].box_button[2].posy2 = int (j + 30 - 2);
							}
							goto A;
						}
					}
					// 按钮点击
					else if (m.x > box_list[k].posx1 && m.x<box_list[k].posx2 - 40 && m.y>box_list[k].posy1 && m.y < box_list[k].posy2)
					{
						// 滑条相对位置编号
						j = float (
							(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
							((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
								(box_list[k].all_text_num - box_list[k].every_text_num + 1))
							);
						// 按钮相对位置编号
						i = int (
							(m.y - box_list[k].posy1) /
							((box_list[k].posy2 - box_list[k].posy1) /
								(box_list[k].every_text_num))
							);
						box_list[k].flag_text_num = int (i + 3 + j);
						goto A;

					A:
						// 图像处理参数初始化,都是可调参数,与可调按钮一一对应
						switch (box_list[0].flag_text_num)
						{
						case 3: {T = 30;					break; }// 图像旋转
						case 4: {T = 256; A = 0; B = 255;	break; }// 直方图均衡化
						case 5: {T = 100;					break; }// 图像分割
						case 6: {							break; }// 伪色彩填充
						case 7: {T = 50; mod = 1;			break; }// 图像锐化
						case 8: {T = 5;						break; }// 图像模糊
						case 9: {T = 10; A = 2; B = 3;		break; }// Arnold 变换
						case 10: {T = 8;					break; }// DCT 变换
						case 11: {							break; }// Haar 变换
						case 12: {mod = 1;					break; }// 均值滤波
						case 13: {T = 2;					break; }// 中值滤波
						case 14: {							break; }// FFT 变换
						case 15: {T = 50; mod = 0;			break; }// 低通滤波
						case 16: {T = 2;					break; }// 分裂图
						default:break;
						}

						// 图像处理按钮初始化
						initialization_image ();

						// 第一次绘制
						draw_scene ();
					}
				}

				// 判断是否点击了自制按钮
				for (i = 0; i < num_button; i++)
				{
					// 矩形按钮
					if (m.x > box_button[i].posx1 && m.y > box_button[i].posy1 && m.x < box_button[i].posx2 && m.y < box_button[i].posy2)
					{
						break;
					}
				}
				// 按钮为激活状态
				if (box_button[i].type == 1)
				{
					// 动画演示按钮
					if (i == 2)
					{
						// 图像处理初始化
						initialization_image ();

						// 绘制
						draw_scene ();
						draw_image ();
					}

					// 与分形参数有关的其他按钮
					else
					{
						switch (box_list[0].flag_text_num)
						{
							// 图像旋转
						case 3:
						{
							// T
							// 旋转角度
							if (i == 0)
							{
								InputBox (ss, 10, _T ("输入角度(-180 ~ 180)"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= -180 && i <= 180) { T = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }

							}
							break;
						}
						// 直方图均衡化
						case 4:
						{
							// T
							// 灰度数量
							if (i == 0)
							{
								InputBox (ss, 10, _T ("输入灰度数量(2 ~ 256),均衡化后的灰度值总个数"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 2 && i <= 256) { T = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// A
							// 最低灰度
							else if (i == 3)
							{
								InputBox (ss, 10, _T ("输入最低灰度(0 ~ 125),将会把原图灰度最低值提升到此值"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 0 && i <= 125) { A = i; B = 255 - A; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// B
							// 灰度范围
							else if (i == 6)
							{
								InputBox (ss, 10, _T ("输入灰度范围(20 ~ 255 - 最低灰度),将会把原图灰度值限制在这个范围内"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 20 && i <= 255 - A) { B = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							break;
						}
						// 图像分割
						case 5:
						{
							// T
							// 分割间隔
							if (i == 0)
							{
								InputBox (ss, 10, _T ("输入分割间隔(20 ~ 125)"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 20 && i <= 125) { T = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							break;
						}
						// 伪色彩填充
						case 6:
						{
							break;
						}
						// 图像锐化
						case 7:
						{
							// T
							// 锐化阈值
							if (i == 0)
							{
								InputBox (ss, 10, _T ("输入锐化阈值(-1 ~ 400),-1 将小于所有像素梯度,结果为纯白"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= -1 && i <= 400) { T = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// mod
							// 锐化模式
							if (i == 1)
							{
								mod = (mod == 1 ? 0 : 1);
							}
							break;
						}
						// 图像模糊
						case 8:
						{
							// T
							// 像素宽度
							if (i == 0)
							{
								InputBox (ss, 10, _T ("输入像素宽度(2 ~ 128),建议是 2 的整数幂,或者是 256 的约数"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 2 && i <= 128) { T = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							break;
						}
						// Arnold 变换
						case 9:
						{
							// T
							// 变换次数
							if (i == 0)
							{
								InputBox (ss, 10, _T ("输入变换次数(1 ~ 50),变换多次会重复回到原图"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 1 && i <= 50) { T = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// A
							// 密钥一
							else if (i == 3)
							{
								InputBox (ss, 10, _T ("输入密钥一(0 ~ 100),密钥不合适,变换会失败"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 0 && i <= 100) { A = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// B
							// 密钥二
							else if (i == 6)
							{
								InputBox (ss, 10, _T ("输入密钥二(0 ~ 100),密钥不合适,变换会失败"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 0 && i <= 100) { B = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							break;
						}
						// DCT 变换
						case 10:
						{
							// T
							// 变换宽度
							if (i == 0)
							{
								InputBox (ss, 10, _T ("输入宽度(1 ~ 256),建议是 2 的整数幂,宽度为 256 即是无虚部 FFT 变换,宽度为 1 即是原图复制"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 1 && i <= 256) { T = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							break;
						}
						// Haar 变换
						case 11:
						{
							break;
						}
						// 均值滤波
						case 12:
						{
							// mod
							// 滤波模式
							if (i == 0)
							{
								mod = 0;
							}
							else if (i == 1)
							{
								mod = 1;
							}
							break;
						}
						// 中值滤波
						case 13:
						{
							// T
							// 取值宽度
							if (i == 0)
							{
								InputBox (ss, 10, _T ("输入宽度(1 ~ 10),此值是欧式距离"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 1 && i <= 10) { T = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							break;
						}
						// FFT 变换
						case 14:
						{
							break;
						}
						// 低通滤波
						case 15:
						{
							// T
							// 截止频率
							if (i == 0)
							{
								InputBox (ss, 10, _T ("输入截止频率(0 ~ 256),256 是全保留,0 是全过滤"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 0 && i <= 256) { T = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// mod
							// 滤波模式
							else if (i == 1)
							{
								mod = (mod == 0 ? 1 : (mod == 1 ? 2 : 0));
							}
							break;
						}
						// 分裂图
						case 16:
						{
							// T
							// 像素宽度
							if (i == 0)
							{
								InputBox (ss, 10, _T ("输入像素宽度(2 ~ 128),建议 2 的幂次"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 2 && i <= 128) { T = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							break;
						}
						default:break;
						}

						// 图像处理初始化
						initialization_image ();
						// 第一次绘制
						draw_scene ();
					}
				}
			}
		}
	}
}

// 主进程
void Gary::carry ()
{
	// 窗口定义
	hOut = initgraph (904, 601);
	SetWindowText (hOut, _T ("常见图像处理的演示"));
	// 进程控制参数
	exit_carry = 0;
	BeginBatchDraw ();
	while (exit_carry == 0)
	{
		initialization ();
		move ();
	}
	EndBatchDraw ();
	closegraph ();
}

// 主函数
int main (void)
{
	// 创建类对象
	Gary G;
	// 进入类对象主循函数
	G.carry ();
	return 0;
}

评论 (4) -

  • 大佬,基于VS2010使用你的程序显示一些sqrt函数引用不明确,全部强制转换为double类型了。然后运行程序,它的滚条和三角箭头、选项标签什么的边框角点坐标有偏移,然后滚条按钮失效。请问大佬怎样修改保证这些信息全部正确。
    • 谢谢同学的提醒。
      我很抱歉 555
      因为我暂时无法解决你的这个问题:VS2010 强制转换后带来的坐标偏移问题。
      我只能先将注释里的编译环境改为:VC6.0。那是我最初通过的编译环境,没有问题的编译环境。这之后,我将代码迁移到 VS2010,修改后通过编译,也并没有出现你所说的情况。
      但我能给出参考。
      程序中的 initialization 函数中定义了你所说的滚条,三角箭头,选项标签,你可以按照自己的设计自定义修改,位置在 // 每个列表框的共同之处。之后。
      程序中的 move 函数负责获取鼠标信息。增减列表框表单数量,势必会造成参数的调整,可以在位置 // 点击了列表框。之后的代码,自定义修改。
      我因为编程自由度而使列表框的设计有缺陷是我最大的问题。当时是方便了我自己修改才如此设计,但现在看来,我有必要完善一下了。
      再次谢谢同学的使用和提醒^-^,针对你提醒的问题,我写在程序简介里的第二次更新里了。
  • 用vs2019好像_T会报不能用const char*转化为LPTSTR的错,强转为(char*)就能用。大佬厉害。
    • 和 vs2019 无关,const char* 是 LPCTSTR,不是 LPTSTR。差的 C 就表示 const。

添加评论