来自多彩世界的控制台——C#控制台输出彩色字符画
引言
看到酷安上有这样一个活动,萌生了用 C# 生成字符画的想法,先放出原图。


§1 黑白
将图像转换成字符画在 C# 中很简单,思路大致如下:
- 加载图像,逐像素提取明度。
- 根据明度映射到字符列表中对应的字符。
- 输出字符。
GetChars函数负责将传入的图像按一定比例导出字符画的字符串。hScale为横向比例,即每次跳过的横向像素数;vScale为纵向比例,在控制台中输出推荐为hScale的 2 倍。
private static string GetChars(Bitmap bmp, int hScale, int vScale)
{
StringBuilder sb = new StringBuilder();
for (int h = 0; h < bmp.Height; h += vScale)
{
for (int w = 0; w < bmp.Width; w += hScale)
{
Color color = bmp.GetPixel(w, h);
float brightness = color.GetBrightness(); // 这里的明度也可以使用 RGB 分量合成
char ch = GetChar(brightness);
sb.Append(ch);
}
sb.AppendLine();
}
return sb.ToString();
}
GetChar负责做明度到字符的映射工作,由于brightness取值范围为 [0, 1],所以需要乘 0.99 防止index越界。listChar是可用的字符列表,自定义只需遵循一条规则,从左往右字符应该越来越复杂。
private static readonly List<char> listChar =
new List<char>() { ' ', '^', '+', '!', '$', '#', '*', '%', '@' };
private static char GetChar(float brightness)
{
int index = (int)(brightness * 0.99 * listChar.Count);
return listChar[index];
}
调用函数,输出结果。初具雏形,黑白样式减少了不少神韵。

§2 有限彩色
2.1 Console
一开始希望通过改变Console.ForegroundColor属性来改变色彩,但是残酷的事实是这个属性只接受ConsoleColor枚举中的 16 个颜色。将全彩图片映射成 16 色输出,费力不讨好,遂求其他方法。
2.2 Colorful.Console
找到了一个彩色控制台的库 Colorful Console。看网页介绍挺厉害的,RGB、渐变色、多色输出……妥了,这肯定符合我们的需要,通过 nuget 可以直接添加到项目中。
在引用区域加一行,就可以把代码中的Console用ColorfulConsole替代。
using Console = Colorful.Console;
GetChars函数需要改变一下,因为每个字符的颜色不同,所以要在函数里面增加输出。好简单,输出内容后面加个颜色的参数就可以了。
private static string GetChars(Bitmap bmp, int hScale, int vScale, bool shouldDraw)
{
StringBuilder sb = new StringBuilder();
for (int h = 0; h < bmp.Height; h += vScale)
{
for (int w = 0; w < bmp.Width; w += hScale)
{
Color color = bmp.GetPixel(w, h);
float brightness = color.GetBrightness();
char ch = GetChar(brightness);
if (shouldDraw)
{
Console.Write(ch, color);
}
sb.Append(ch);
}
if (shouldDraw) { Console.WriteLine(); }
sb.AppendLine();
}
return sb.ToString();
}
然而现实再一次残酷起来,输出结果一片黑,使用白色背景看一看。

可能看不清,不过牛角的位置确实有几个字符不是黑色,那我们换张图片来看。可以看到确实有彩色输出,不过效果尚可的仅限最前面的一些字符,之后白色完全不见了。

在测试官网上的操作都没有问题后,我陷入了深深的思考,NMD,为什么?直到我看到了官网上最下面的一段话。
Colorful.Console can only write to the console in 16 different colors (including the black that's used as the console's background, by default!) in a single console session. This is a limitation of the Windows console itself (ref: MSDN), and it's one that I wasn't able to work my way around. If you know of a workaround, let me know!
Colorful.Console只能同时输出 16 种颜色,果然原版Console能接受的ConsoleColor枚举也是 16 种颜色是算计好的。可恶,难道只能到此为止了吗?
我不甘心。
§3 全彩
终于,我找到了这个 visual studio - Custom text color in C# console application? - Stack Overflow。在下面 Alexei Shcherbakov 和 Olivier Jacot-Descombes 的回答中,我看到了希望。
Since Windows 10 Anniversary Update, console can use ANSI/VT100 color codes
You need set flagENABLE_VIRTUAL_TERMINAL_PROCESSING(0x4)by SetConsoleMode
Use sequences:
"\x1b[48;5;" + s + "m"- set background color by index in table (0-255)
"\x1b[38;5;" + s + "m"- set foreground color by index in table (0-255)
"\x1b[48;2;" + r + ";" + g + ";" + b + "m"- set background by r,g,b values
"\x1b[38;2;" + r + ";" + g + ";" + b + "m"- set foreground by r,g,b values
Important notice: Internally Windows have only 256 (or 88) colors in table and Windows will used nearest to (r,g,b) value from table.
有了这个神奇的ENABLE_VIRTUAL_TERMINAL_PROCESSING(0x4),就可以随意修改前后景颜色了。说干就干,首先需要增加一个NativeMethods类,用来 Call kernel32.dll里的 3 个函数。
using System;
using System.Runtime.InteropServices;
namespace Img2ColorfulChars
{
internal class NativeMethods
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, int mode);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr handle, out int mode);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int handle);
}
}
然后在主程序Main函数里一开始增加以下三行,-11代表STD_OUTPUT_HANDLE(GetStdHandle function - Windows Console | Microsoft Docs), 0x4就是上面所说的ENABLE_VIRTUAL_TERMINAL_PROCESSING。
var handle = NativeMethods.GetStdHandle(-11);
NativeMethods.GetConsoleMode(handle, out int mode);
NativeMethods.SetConsoleMode(handle, mode | 0x4);
因为我们要修改的是字符的前景色,所以把上一节中GetChars函数里的
Console.Write(ch, color);
替换为
Console.Write($"\x1b[38;2;{color.R};{color.G};{color.B}m{ch}");
输出结果如下,完美。

尾声
多彩的细节,巧妙的象征,这就是青春啊(不是)。
而这个项目真正的用法:

项目链接
- github.com/Roy0309/Img2ColorfulChars
仅全彩版本,适用于1.0版
推荐阅读


作者:Kabuto_W
链接:https://www.jianshu.com/p/8a083421c11d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
来自多彩世界的控制台——C#控制台输出彩色字符画的更多相关文章
- [笔记]Go语言在Linux环境下输出彩色字符
Go语言要打印彩色字符与Linux终端输出彩色字符类似,以黑色背景高亮绿色字体为例: fmt.Printf("\n %c[1;40;32m%s%c[0m\n\n", 0x1B, & ...
- c++ 在控制台用 wcout输出宽字符的问题
在我的电脑上要想通过 std::wcout输出 宽字符 需加入以下代码 #include <io.h> #include <fcntl.h> void main() { _se ...
- echo 输出彩色字符
借助echo的-e选项来实现,语法格式为 echo -e "\033[3xmsome things you want to print out.\033[0m" \033[3xm为 ...
- 如何在浏览器控制台(console)里输出彩色样式调试信息
console.log(XX,XX,XX) log 的第一个参数声明第二.第三个参数的作用,第二个参数就是样式,第三个参数是要输出的字符串 console.log("%c%s", ...
- Python同时向控制台和文件输出日志logging的方法 Python logging模块详解
Python同时向控制台和文件输出日志logging的方法http://www.jb51.net/article/66756.htm 1 #-*- coding:utf-8 -*- 2 import ...
- Java 控制台输入数字 输出乘法表(代码练习)
最近,回忆了一些刚学习Java时经常练习的一些小练习题.感觉还是蛮有趣的,在回顾时想起好多学习时的经历和坎坷,一道小小的练习题要研究半天,珍重过往,直面未来.下面贡献代码,Java 控制台输入数字 输 ...
- 双缓冲解决控制台应用程序输出“闪屏”(C/C++,Windows)
使用 C 语言编写游戏的小伙伴们想必起初都要遇到这样的问题,在不断清屏输出数据的过程中,控制台中的输出内容会不断地闪屏.出现这个问题的原因是程序对数据处理花掉的时间影响到了数据显示,或许你可以使用局部 ...
- 改变 C/C++ 控制台程序的输出颜色和样式
我们经常可以看见Linux自带终端下的许多程序都输出了不同颜色和底纹的字体.最近也想要自己实现一下这种效果,方法是在输出流中插入占位符\033[***. 我从网上收集了一些常用的控制语句,并用以下代码 ...
- VC printf输出彩色字体
在VC下使用SetConsoleTextAttribute()函数可以改变当前控制台的前景色和背景色,从而达到输出彩色字体的效果. 使用的方法也很简单,具体代码如下: #include <win ...
- 有趣的console.log(console.log输出彩色字,图片等)
亲们支持我的新博客哦==>原文地址 ) 逛网站的时候经常发现很多网站控制台打印了很好玩的内容 比如我的网站 →calamus 或者知乎→ 平时是不是只用console调试或者打印别的信息了,没有 ...
随机推荐
- Asp .Net Core 系列:集成 Refit 和 RestEase 声明式 HTTP 客户端库
背景 .NET 中 有没有类似 Java 中 Feign 这样的框架?经过查找和实验,发现 在 .NET 平台上,虽然没有直接的 Feign 框架的端口,但是有一些类似的框架和库,它们提供了类似的功能 ...
- 【课程汇总】Hello HarmonyOS系列课程,手把手带你零基础入门
HarmonyOS是面向未来.面向全场景的新一代智能终端操作系统,为不同设备的智能化.互联与协同提供了统一的语言,给人们带来简洁.流畅.连续.安全可靠的全场景交互体验. 初识HarmonyOS的开发者 ...
- docker 应用篇————tomcat例子[七]
前言 虽然我干的事情和java不多,但是例子是为了熟悉原理,而不是为了例子而例子的,故而整理一下tomcat的例子. 正文 使用官方示例: 然后运行一下. 没有找到然后进行下载了. 可以看到这里就已经 ...
- Redis 的并发竞争问题是什么?如何解决这个问题?了解 redis 事务的 CAS 方案吗?
面试官心理分析 这个也是线上非常常见的一个问题,就是多客户端同时并发写一个 key,可能本来应该先到的数据后到了,导致数据版本错了:或者是多客户端同时获取一个 key,修改值之后再写回去,只要顺序错了 ...
- seaJS简介
所有版本的 zip 包请在这里下载:seajs/tags 解压后,目录说明如下: dist -- sea.js 等压缩好的文件,直接可用 docs -- 使用文档 lib -- 给 Node.js 用 ...
- 如何使用鞋厂ERP等企业管理软件提高企业运营整体效率?
ERP把企业客户需求.市场规划.产品研发.内部制造等活动以及供应商的资源整合在一起,形成企业一个完整的产业链和供应链,通过企业多个环节的无缝链接和整体运作来提高企业运营整体效率: (1) . 对整个产 ...
- 智能logo免费体验|如何让餐饮logo在点评网站上一眼出众?
简介:一个新的餐饮店铺,还没有人知晓,Logo就是这个重要的"门面",所传递的信息让人快速识别,就能产生记忆点,愿意进一步了解,从而为店铺带来流量和收益.如何让你的餐饮店铺log ...
- 阿里云图数据库GDB V3引擎发布,加速开启“图智”未来
简介:无论是学术界还是产业界,都对图数据库有比较高的预期.Gartner发布的<2021年十大数据和分析技术趋势>中提到:"到2025年图技术在数据和分析创新中的占比将从202 ...
- 【阿里云 CDP 公开课】 第二讲:CDH/HDP 何去何从
简介:Hadoop社区版CDH/HDP已经不再更新,也将终止服务.后续的平台路线图怎么规划?Cloudera CDP整合了CDH和HDP,有哪些性能提升和功能增强?如何平滑的进行迁移?本文结合CDH ...
- 重磅发布:微服务引擎 MSE 专业版
简介: 性能提升 10 倍,更高的 SLA 保障,新用户限时抢购 8 折资源包. 微服务引擎 MSE 专业版发布,支持 Nacos 2.0 ,相比基础版,专业版具有更高的 SLA 保障,性能提升十倍, ...