常见图像处理的演示
2022-2-13 ~ 2022-2-25
(4)
程序简介
这个程序包括了一些常见图像处理的演示,并提供了一些按钮来改变参数。有旋转,均衡化,分割,填充,锐化,模糊,滤波,变换和一个分裂图小游戏。
我的理解是,图像变换就是基于某个规则对图像中像素点的处理,可以是统一处理,也可以分类处理。
程序的初始化函数 initialization 中默认加载了三张所使用的图片,第一张是大部分图像处理所用图片,第二张是滤波处理所用图片,第三张是分裂图所用图片。也可以通过输入图片相对位置及名称来使用自己的图片。
FFT 变换和低通滤波时间较长,展示时需要等待较长时间才能完成,谨慎使用。
图像处理演示列表:
- 图像旋转
- 直方图均衡化
- 图像分割
- 伪色彩填充
- 图像锐化
- 图像模糊
- Arnold 变换
- DCT 变换
- Haar 变换
- 均值滤波
- 中值滤波
- FFT 变换
- 低通滤波
- 分裂图
第一次更新:
- 界面和图片的统一调整,重复变量的删减。
- 分裂图一开始不会展示使用的图片,保留悬念。
第二次更新:
- 程序现在可以通过 VC2010 的编译了。
原代码从 VC6.0 迁移到 VC2010 会出现 3 个错误,sqrt 函数参数错误,pow 函数参数错误,sscanf 函数参数错误。前两个问题可以强制转换,我在报错的地方加上 double 来解决;第三个问题可以进入 VC2010 的项目,属性,配置,属性,常规,字符集:“使用 Unicode 字符集”改为“使用多字节字符集”来解决。 - 程序开头的注释中,将“编译环境:Visual C++ 6.0/2010”改为“编译环境:Visual C++ 6.0”。
老师要求程序不能有警告,通过 VC2010 的编译后,虽然没有报错,但有大量警告,基本是变量类型需要强制转换的问题,这些都是 VC6.0 没有的警告。看到评论的同学提出的问题后,我意识到,我暂时没有办法解决变量类型强制转换后带来的位移问题,所以我不能随便强制转换,只能先减少编译环境了,谢谢评论的大同学。
第三次更新:
- 图片更新,减小边框
- 代码更新,现在兼容 vc2010,不兼容 vc6.0
vc2010:_stscanf_s,vc6.0:_stscanf
vc2010:_stprintf_s,vc6.0:_stprintf
列表框箭头坐标偏移的问题,建议直接删除箭头,只采用滑条即可。这个程序 debug 没问题,release 有问题,暂时不要使用 release。
程序执行效果
所用素材
完整源代码
////////////////////////////////////////
// 程序:常见图像处理的演示
// 作者: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;
}
我很抱歉 555
因为我暂时无法解决你的这个问题:VS2010 强制转换后带来的坐标偏移问题。
我只能先将注释里的编译环境改为:VC6.0。那是我最初通过的编译环境,没有问题的编译环境。这之后,我将代码迁移到 VS2010,修改后通过编译,也并没有出现你所说的情况。
但我能给出参考。
程序中的 initialization 函数中定义了你所说的滚条,三角箭头,选项标签,你可以按照自己的设计自定义修改,位置在 // 每个列表框的共同之处。之后。
程序中的 move 函数负责获取鼠标信息。增减列表框表单数量,势必会造成参数的调整,可以在位置 // 点击了列表框。之后的代码,自定义修改。
我因为编程自由度而使列表框的设计有缺陷是我最大的问题。当时是方便了我自己修改才如此设计,但现在看来,我有必要完善一下了。
再次谢谢同学的使用和提醒^-^,针对你提醒的问题,我写在程序简介里的第二次更新里了。