文字的颜色
本文代码在这里 https://github.com/jJayyyyyyy/bmp_maker
1.序
无论什么语言,每一段文字都有自己的颜色。比如程序员最熟悉的hello world.
,它的颜色是这样的:
又比如这个由字符搭出来的姚明脸,其颜色是这样的
是不是很神奇lol
2.原理
创意来自KaitoHH,这哥们写了一个AnyCodeToBmp,根据名字可以看出,这是一个把代码变成BMP图像的工具。
我们知道,在计算机中可以有很多种方式来表示颜色(如本文用到的RGB
颜色空间),也有很多种图像格式(如JPEG, PNG, 本文用到的是BMP格式)。如果用文本编辑器打开一张图片,可以看到里面是一连串的十六进制的数字,这就是图片在计算机里保存的形式。当我们换用画图
或者其他软件打开它,就相当于把这些数字解码,还原成图片。
因此,我们要做的就是把代码文字当成了RGB颜色,然后在文件开头写上必要的信息,将该文件标识为BMP图像,让看图软件能够识别并呈现我们的“图片”。
更为神奇的是,如果我们用文本编辑器打开这些“图片”,除了开头的乱码,剩下的就是我们原来写入的文字!
KaitoHH的工具是用C写的,既然知道了原理,我们不妨用Python来重写一遍。值得注意的是,C可以很方便的操作底层的bit啊byte啊,而Python本来不是干这个的,所以我们不必局限于原来的实现方法,参考原理和思路即可。
3.实现
BMP图像可以简单地由两部分组成:
- 文件头,
Headers(54bytes)
=BMP Header(14 bytes)
+DIB(40 bytes)
- 图片数据,
Pixel Array
, 也即Bitmap Data
具体的对应关系可以查看wikipedia: BMP file format.
我们需要在文件头中写入以下信息:
- 文件总大小
total_size
,对应的Offset是0x02
,长度4字节 - 图片宽度
width
,对应Offset是0x12
,长度4字节 - 图片高度
height
,对应Offset是0x16
,长度4字节 - 图片数据大小
raw_size
,对应0x22
,长度4字节
这些也就是可变的部分,其他地方写入固定数值即可,注意BMP采用小端序(little-endian)
然后将编码后的文字写到文件头后面,就可以得到计算机能够识别的BMP图像了。
4.实例
看完3是不是觉得还有点抽象?没关系,下面我们来看一个实例。简单起见,我们来“画出”一开始的hello world.
(注意,这段字符串长度为10
)。
首先,用十六进制打开图像后,我们将看到以下内容:
424d 4200 0000 0000 0000 3600 0000 2800
0000 0400 0000 0100 0000 0100 1800 0000
0000 0c00 0000 0000 0000 0000 0000 0000
0000 0000 0000 6865 6c6c 6f20 776f 726c
642e
然后我们来分段说明:
424d #固定,用ascii表示的"BM"
4200 0000 #total_size, 0x42 = 66 = 54 + 12(字符串长度10)
0000 #固定
0000 #固定
3600 0000 #固定, header_size, 0x36 = 54 = 14 + 40
2800 0000 #DIB_size, 0x28 = 40
0400 0000 #width, 0x04 = 4, 注意width取4的整数倍
0100 0000 #height, 0x01 = 1
0100 #固定
1800 #固定
0000 0000 #固定
0c00 0000 #raw_size, 0x0c = 12
0000 0000 #固定
0000 0000 #固定
0000 0000 #固定
0000 0000 #固定
以上就是整个Headers
的内容。剩下的就是颜色信息,逐个对应了字符串”hello world.”的ASCII码。
6865 6c6c 6f20 776f 726c 642e
这样拆解之后,结构是不是清晰了很多呢?如果要画出另外的文字,只需要修改第3节中对应的部分即可。需要注意的是,width应取4的整数倍。而在RGB空间中,每个像素pixel为3个字节(红+蓝+绿,各占一字节)。因此raw_size
是12
的整数倍,否则需要补齐。本文采用的补齐方法是在末尾添加
或者\n
。
5.跋
偷偷地告诉你一个秘密,中文博大精深,其色彩亦是绚烂多姿。最后,有一篇文章的颜色是这样的(未放大的图像在这里):
你能猜出这是哪一篇文章吗-( ゜- ゜)つロ
(END)
相关阅读
- BMP means BitMap
- DIB means Device Independent Bitmap
- KaitoHH: AnyCodeToBmp
- Wikipedia: BMP
- ASCII
- bytes
- others