用 Golang 将图片转化成 ASCII 码
在开始之前先看看最终效果:
项目地址在这里:https://github.com/qeesung/im…,欢迎 star
我们都知道图片是通过一个像素点矩阵组成的,每一个像素点都是有四个值,分别是 R,G,B,A 组成,其中 RGB 就是红色,绿区,蓝色,简称三原色,在计算机中取值从 0 -255,而 A 则是颜色的透明度,取值 0.0-1.0。
我们现在要做的就是将一个彩色的图片转化成一个由 ASCII 组成的图片,换句话说,就是将 RGBA 像素点的矩阵转化成一个由字符组成的矩阵,必要的时候再给字符加上颜色就可以啦。
(R, G, B, A) (R, G, B, A) (R, G, B, A) char1, char2, char3
(R, G, B, A) (R, G, B, A) (R, G, B, A) –> char4, char5, char6
(R, G, B, A) (R, G, B, A) (R, G, B, A) char7, char8, char9
那么问题又来了,R,G,B 的值都是从 0 -255 的,而字符的数量是很有限的(一般我们只会用少数几个有限的字符来表示),那么我们如何将由多种组合的 R,G,B 映射到一个字符上呢?
convert(pixel) -> character
我们不妨将 RGB 值和透明度和在一起,算出一个总值权重 W,然后将这个值 W 均分到不同的字符串上,这样就完成了像素点到字符的映射,就是这么简单。注意下面的可选字符串的从左往右 ” .,:;i1tfLCG08@” 辨识度一次增加,或者辨识度依次减少,如果不这样做,那么图片识别出来效果可能不太行。
value := (r + g + b) * a / 255
// Choose the char options.Pixels = ” .,:;i1tfLCG08@”
precision := float64(255 * 3 / (len(options.Pixels) – 1))
rawChar := options.Pixels[roundValue(float64(value)/precision)]
现在可以将像素转化为字符了,那么颜色怎么办?上面的操作好比只是把图片转化成了黑白的,然后把轮廓画出来来了,那么如何取颜色呢?
加颜色需要注意的是,现在的颜色不再是单单的颜色了,现在的颜色包含两块,一块是字符自身的颜色,即前景色,一块是字符的后面的颜色,即背景色。
我们这里不调整背景色,只渲染字符的前景色,即只渲染字符的颜色。
在 linux 终端中,是可以通过输出特殊字符来配置输出字符颜色的,拿着就好办了,只需用图片的 RGB 混合一下,输出颜色就可以了,我们这里用 http://github.com/aybabtme/rg…。
func decorateWithColor(r, g, b uint64, rawChar byte) string {
coloredChar := rgbterm.FgString(string([]byte{rawChar}), uint8(r), uint8(g), uint8(b))
return coloredChar
}
更多源码细节可以看这里:https://github.com/qeesung/im… 欢迎 star????