图片转字符

图片转字符,就是将一张图片转换成字符的形式的文档,话不多说,直接看效果

原图.jpg

效果图.png

思路分析

  1. 关于颜色的RGB值
    电脑表示的颜色都是由RGB(Red 红色 Green 绿色 Blue 蓝色)三种颜色光合成的.所有的颜色都可以用一个RGB值表示.

    RGB值 #5F4B8B比如说这个#5F4B8B 这是一个16进制数字,5F,4B,8B这三个值分别表示rgb三种颜色的亮度.RGB值越大,颜色越接近白色,RGB值越小,颜色越接近黑色

  2. 关于灰度
    联想一下黑白图片,虽然黑白图片没有红绿,但是人眼还是能够区分出各种不一样的颜色,区别就是所谓的灰度(下图从左到右灰度越来越低),灰度值越低,也就越接近白色.

灰度
  上图的灰色用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`
  1. 图片划分
    对于一整张图片,其实先分为多块,每一块用一个合适的字符进行模拟,最后把所有的字符全部都写到文件里面,就可以了
    图片分成的块数越多,也就意味着最后的字符图能够表示的细节越多,也就越接近原图

  2. 关于字符的'颜色'
    字符图最后是通过字符样式来表示某种颜色,而不是通过字体本身的颜色来体现的,所以需要对颜色做一些处理,对于字符和字符M,M就更适合表示深色,适合表示浅一点的颜色,那么对于不同字符,选出如下一些来做最终的效果

涉及到的内容

  1. 工具 VS或者VC 需要安装图形库
  2. 素材 一张图片
  3. 语法部分
    分支 数组 循环 文件操作 图形库的函数

准备代码

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

  1. 最后txt文档打开的时候,如果出现形状不合适,一般是字体的问题,为了确保结果完美,请选择使用等宽字体预览.比如Courier New、Terminal 或者可以下载其他等宽字体.
  2. 建议选择图片简单一点的,图片太复杂效果不是特别好
  3. 有其他问题或者是建议可以留言 比心~
(* ̄3 ̄)╭

有兴趣一起学习C/C++的小伙伴们记得加群: 871318929,会有许多的资源可以供大家学习分享,欢迎大家前来一起学习进步!

你可能感兴趣的:(图片转字符)