用盲文字符来在终端画黑白图像
用盲文字符来在终端画黑白图像
食用提示
如果这篇文章在您的设备上显示很多方框,或许是字体出了问题。请确保自己使用的字体可以正常显示盲文。
在我的设备上,无论怎么操作都无法使 urxvt (rxvt , xterm ) 表现出我想要的样子。因此在不建议您进行实验时使用 urxvt (rxvt , xterm ) 。
想法来源
有一天发现盲文就是一堆像素点,就想着用盲文文字在终端画图。
实现效果
分析
1 | ⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏ |
这是 UTF-8 中的盲文字符。共有 256 个。每个盲文字符都由数个点组成。点最多的盲文字符(右下角)有 8 个点,它看起来像个实心黑框框;点最少的盲文字符有 0 个点(左上角),虽然它看上去像个空格,但它真的和空格不是一个东西。
稍微观察可以发现,一个盲文字符可以当成 4x2 的小形位图使用,如果能够良好组织,使盲文字符按某种方式排列,就可以拼出大一些的位图。
不同的 4x2 位图共有 2^8 = 256 个,而不同的盲文字符正好也有 256 个。这意味着盲文字符和 4x2 的位图之间有着一一对应的关系。为了方便盲文与位图的与相转化,我们需要设计一种编码方案。
上面列出的表显然是经过良好组织的,可以发现盲文字符的排布很有规律。找规律的过程略去不提,这里仅说编码方案。经过以下操作后,可以保证盲文字符和其对应的 4x2 位图有相同的编号:
盲文:将上表中的盲文从上到下,从左到右依次编号 0 到 255 。
位图:考虑搞一张权值表:
1 | 1 8 |
将表中所有对应位图黑色位置的权值加起来,得到的和即为位图的编号。
例如,字符 “⢫” ,其编号为 171 ,其位图为:
1 | 1 1 |
和权值表 py 后得到 1 + 8 + 2 + 32 + 128 = 171 ,和期待结果一致。
使用这个方法,可以将 4x2 的小位图和它所对应的盲文字符的编号对应起来。于是,我们就可以在终端画图了。
实现
首先对盲文字符打表:
1 | const char *magic_table[] = { |
接着实现 canvas 结构体。这里用 unsigned char
数组当成 bool
数组使用。日后优化时,可以用 bitmap 节省空间。
1 | typedef struct canvas { |
实现画像素点和打印功能:
1 | void canvas_draw(canvas p, int x, int y) |
实现完成。以下是函数功能与参数说明:
1 | int canvas_init(canvas *p, int width, int height); 将 p 初始化为宽 width 高 height 的画布 |
实现示例中的效果
用 ImageMagick 的 convert 命令将图片文件转为只有 2 种颜色的 xpm 文件,写个傻瓜 xpm 解析器,配合上面的代码简单处理即可得到示例中的效果。傻瓜解析器的代码见:doxpm.c 。
在本机上,实现示例效果的命令为:
1 | $ convert -colors 2 sample.png a.xpm |
完
代码仅被用来说明想法,并没有想写成一个可用的库。所以码风略快糙猛请多包涵。
感谢 zrz_orz 同学教我在洛谷日报上投稿,并提出大量修改意见。