图片转字符,就是将一张图片转换成字符的形式的文档,话不多说,直接看效果
思路分析
-
关于颜色的RGB值
电脑表示的颜色都是由RGB(Red 红色 Green 绿色 Blue 蓝色)三种颜色光合成的.所有的颜色都可以用一个RGB值表示.RGB值 #5F4B8B比如说这个#5F4B8B 这是一个16进制数字,5F,4B,8B这三个值分别表示rgb三种颜色的亮度.RGB值越大,颜色越接近白色,RGB值越小,颜色越接近黑色
关于灰度
联想一下黑白图片,虽然黑白图片没有红绿,但是人眼还是能够区分出各种不一样的颜色,区别就是所谓的灰度(下图从左到右灰度越来越低),灰度值越低,也就越接近白色.
上图的灰色用RGB表示的话,R G B三个值是一样的,对于将一个颜色转成灰色,大致有如下几种方案:
* 取R G B三个值的平均值
* 按照`Gray=R*0.299+G*0.587+B*0.114`的方式求灰度值
* 按照3:6:1的方式得到灰度值`Gray=(R*3+G*6+B)/10`
图片划分
对于一整张图片,其实先分为多块,每一块用一个合适的字符进行模拟,最后把所有的字符全部都写到文件里面,就可以了
图片分成的块数越多,也就意味着最后的字符图能够表示的细节越多,也就越接近原图关于字符的'颜色'
字符图最后是通过字符样式来表示某种颜色,而不是通过字体本身的颜色来体现的,所以需要对颜色做一些处理,对于字符和字符M,M就更适合表示深色,适合表示浅一点的颜色,那么对于不同字符,选出如下一些来做最终的效果
涉及到的内容
- 工具 VS或者VC 需要安装图形库
- 素材 一张图片
- 语法部分
分支 数组 循环 文件操作 图形库的函数
准备代码
char ch[] = { ' ', '`', '.', '^', ',', ':', '~', '"', '<', '!', 'c', 't', '+', '{', 'i', '7', '?', 'u', '3', '0', 'p', 'w', '4', 'A', '8', 'D', 'X', '%', '#', 'H', 'W', 'M' };
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 };
#include //图形库头文件 easyx.h
#include
//一个小块 8*8个像素 小块越小 字符图越像 选取合适的大小就行
int GetCh(int data)//在数组num中找到最接近data的元素
{
//数组有序 --->
int left=0,right=31,index;//num的最大元素下标是31
while (left < right)
{
index = (left + right) / 2;
if (num[index] == data) return ch[index];//找到数字 直接返回对应的字符
else if (num[index]>data) right = index-1;//往左找
else left = index+1;
}
//退出的条件 left>=right
return ch[left];//这个写ch[right]也行
//或者比较num[left]和num[right] 选最接近data的那个
}
int main()
{
//图片需要用户输入路径 就另外写
char fileName[128]="素材.jpg"; //这是文件的路径,也可以在后面手动输入
//printf("提示用户输入图片名字\n");
//scanf("%s", fileName);
IMAGE img1;//准备变量 存放图片
loadimage(&img1, fileName);//加载图片
int x = img1.getwidth();
int y = img1.getheight() / 2;//高度压缩一半 高度压缩一半之后更加接近原图
IMAGE img;
loadimage(&img, fileName,x,y);
initgraph(img.getwidth(), img.getheight());
//initgraph(640, 640); //如果图片太大 也可以考虑不使用图片本身大小
putimage(0, 0, &img);
int gray;
FILE *fp = fopen("ASCII.txt", "w");//创建文件
for (int i = 0; i < img.getheight()/8; ++i)
{
for (int j = 0; j < img.getwidth() / 8; ++j)
{
//得到这个小块中 所有点的颜色 -->计算灰度值 取平均值
gray = 0;
for (int x = 0; x < 8; ++x)
{
for (int y = 0; y < 8; ++y)
{
//统计这个方块中的灰度值 求平均
gray+=GetRValue(RGBtoGRAY(getpixel(j * 8+x, i * 8+y)));
}
}
gray /= 8 * 8;//取平均值
//找对应的字符
fputc(GetCh(70 - gray * 70 / 255),fp);//0~255之间 --->0~70之间的数字
//将灰度值 转换成0~70之间的值 匹配数组中的数字 找到对应字符
//fputc 将字符写入文件 后序直接打开txt就能看到效果
}
fputc('\n', fp);//每一行加个换行符号
}
/*
getpixel 图形库中用于获取某个点的颜色的函数
RGBtoGRAY 将一个RGB颜色转换成灰度颜色
GetRValue 获取颜色中R部分的值
//灰度颜色 R G B
*/
fclose(fp);//关闭文件
getchar();
closegraph();
return 0;
}
Tips
- 最后txt文档打开的时候,如果出现形状不合适,一般是字体的问题,为了确保结果完美,请选择使用等宽字体预览.比如Courier New、Terminal 或者可以下载其他等宽字体.
- 建议选择图片简单一点的,图片太复杂效果不是特别好
- 有其他问题或者是建议可以留言 比心~
有兴趣一起学习C/C++的小伙伴们记得加群: 871318929,会有许多的资源可以供大家学习分享,欢迎大家前来一起学习进步!