图片转字符串
基本概念
灰度值
-
把白色与黑色之间按对数关系分成若干级,称为“灰度等级”。范围一般从0到255,白色为255,黑色为0,黑白照片也称为灰度图像
-
RGB值和灰度值的换算公式 Gray=(R30+G59+B*11)/100,转换后的颜色就是RGB(Gray,Gray,Gray)
字符画
-
字符画就是用若干个字符组成,每个字符去替换原图的一块区域
-
有些字符会更接近白色(比如.),有些会更接近黑色(比如M),根据某一块的平均灰度找到最接近的字符即可
-
字符和接近的灰色值已经给出
1 字符
2 ' ', '`', '.', '^', ',', ':', '~', '"', '<', '!', 'c', 't', '+', '{', 'i', '7', '?','u', '3', '0', 'p', 'w', '4', 'A', '8', 'D', 'X', '%', '#', 'H', 'W', 'M',
3 对应的字符
4 0, 5, 7, 9, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43,45, 47, 49, 51, 53, 55, 59, 61, 63, 66, 68, 70
用到的函数
图形库函数:
1 getpixel() 获取某一点的颜色
2 RGBtoGRAY() 通过rgb返回对应的灰度值颜色
3 GetRValue() 得到RGB值中的红色部分,返回绿、蓝部分也可以
文件操作 fputc()
示例代码:
1 #include<stdio.h>
2 #include<easyx.h>
3 char GetCh(int data);
4 char ch[] = { ' ', '`', '.', '^', ',', ':', '~', '"', '<', '!', 'c', 't', '+',
5 '{', 'i', '7', '?', 'u', '3', '0', 'p', 'w', '4', 'A', '8', 'D', 'X', '%', '#', 'H', 'W', 'M' };
6 char num[] = { 0, 5, 7, 9, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41,43, 45, 47, 49, 51, 53, 55, 59, 61, 63, 66, 68, 70 };
7 int main()
8 {
9 IMAGE img;
10 loadimage(&img, L"test.bmp");
11 initgraph(img.getwidth(), img.getheight());
12 putimage(0, 0, &img);
13 FILE *fp = fopen("图片转字符.txt", "w");
14 if (!fp) return 0;
15
16 int gray; //灰度值
17 for (int i = 0; i < img.getheight() / 8; ++i)
18 {
19 for (int j = 0; j < img.getwidth() / 8; ++j)
20 {
21 gray = 0; //清零
22 for (int x = 0; x < 8; ++x)
23 {
24 for (int y = 0; y < 8; ++y)
25 {
26 //统计这个区域中的灰度值 求平均
27 gray += GetRValue(RGBtoGRAY(getpixel(j * 8 + x, i * 8 + y)));
28 }
29 }
30 gray /= 8 * 8; //取平均值
31 //将灰度值 转换成0~70之间的值 匹配数组中的数字 找到对应字符
32 fputc(GetCh(70 - gray * 70 / 255), fp);//0~255之间 --->0~70之间的数字
33 }
34 fputc('\n', fp);//每一行加个换行符号
35 }
36 fclose(fp);
37 getchar();
38 closegraph();
39 return 0;
40}
41
42 char GetCh(int data)
43{
44 //快速查找
45 int left = 0, right = 31, index; //num的最大元素下标是31
46 while (left < right)
47 {
48 index = (left + right) / 2;
49 if (num[index] == data) return ch[index]; //找到数字 直接返回对应的字符
50 else if (num[index]>data) right = index - 1; //往左找
51 else left = index + 1;
52 }
53 //退出的条件 left>=right
54 return ch[left]; //return ch[right]也可以
55}
我用的Notepad++打开的,记事本也可以打开,但是要将字体设置小点才能看清楚,下面是原图和字符图的比较:
个人建议:
我本人不建议使用Windows自带的记事本编辑文本文件。原因是Microsoft开发记事本的团队使用了一个愚蠢的行为来保存UTF-8编码的文件,他们自作聪明地在每个文件开头添加了0xefbbbf(十六进制)的字符,你会遇到很多不可思议的问题,比如,拖拽到Linux系统的文本文件打开乱码,这是使用记事本带来的。建议你下载Notepad++代替记事本,不但功能强大,而且免费!记得把Notepad++的默认编码设置为UTF-8【菜单栏–选择编码–选择UTF-8编码】。
下载地址:
https://notepad-plus-plus.org/downloads/v7.8.2/