很早之前就看过到关于 commits.io 的一个帖子,这个站点专门制作代码明信片。什么是代码明信片呢?如下图。
背景是代码,然后中间印上指定的图案,就是一幅代码明信片了。看起来有点意思,将自己的得意作品做成一个代码明信片打印出来挂在办公室将是一个非常不错的装逼选择:wink:。
当时我就在想,这东西挺有意思,有空自己做一个。当然,事情一多也就忘记了。最近,我又看到了一个帖子, Build your own code poster with elixir ,是说怎样用Elixir来制作代码明信片的。Elixir是我最近正在研究的语言,不过我不觉得它适合拿来干这个,这种程序,拿Go做一个CLI最爽,编译好了就可以发放给亲朋好友体验了。说干就干,再不能拖延了。
一个程序,无非是:输入、处理、输出。老话说的好, 程序就是数据结构+算法 。数据结构用来表示数据,算法用来处理数据。我们先来看看我们要开发的代码明信片程序的这三个方面分别是什么。
光这两个参数行吗?当然不行。最终生成的代码明信片是多大?所以,又要加两个参数。width,代码明信片的宽度,height,代码明信片的高度。
这样就够了吗?看起来好像是够了。在程序开发过程中,一开始就将程序所需要的所有参数都定义完全的情况很少,一般在实现过程中发现不够了再补充。这里我们不妨先将思维转换到程序实现上。
程序的主要逻辑是遍历每个字符,计算字符的位置,然后得出这个位置在图片中的颜色即可,最终输出一个HTML文件由浏览器进行渲染。所以,问题来了,首先,每行有多少个字符?如果不知道这个,我们根本没法计算字符的坐标。所以,我们需要清楚的知道单个字符的宽度和高度,这就额外引出了四个参数:
span
中,指定好字体和字体大小,用检查器就可以看到单个字符的宽度和高度。 这里,我使用 Hack
字体为例,可以看出,当字体选择Hack,字体大小为16.63px像素时,单个字符的宽度是10,高度是19。
最后,图片尺寸一般比代码明信片的尺寸要小,放在中央位置。所以,我们还需要一个背景颜色(bgColor),对于位置不在图片中的字符,应该填充背景色。
最终处理完毕后,以什么样的格式输出呢?作为一个整天和浏览器打交道的人,我觉得输出为一个HTML文件是最为方便的,直接交给浏览器去渲染。
输出为HTML也有多种选择。
为什么要要先考虑输出呢?因为输出会影响程序的结构。在输入输出定义好的情况下,在去想程序实现是比较合理的,无论你怎么实现,只要输入输出不变,都不会影响用户的使用。
因为我们要支持输出多种格式,所以我们的核心程序一定是产生一个中间结果,然后再由不同的模块根据中间结果产生不同的输出。这就是输出对程序结构的影响。
最后,我们根据确定好的输入输出,来讨论程序具体的处理逻辑。
到这里,程序的实现就很清楚了,借助于Go强大的标准库,需要我们编写的代码其实很少,作为一个周末项目练练手是非常不错的选择。
最终,程序在仓库在Github上, codeposter 。测试了几幅图片,效果还不错。默认使用的字体是 Hack
,字体大小为7X14,明信片宽度是114X54。如果想提高字符的密度,也就是 分辨率 ,减少字体大小即可:stuck_out_tongue_winking_eye:。