github stackoverflow vertx的头像是如何生成的呢?

2,469 阅读7分钟

1)稳健的一天

身为码农的我们,从走出学校的那一刻起,就不得不面临来自资本的压榨和工作的压力。为了省时省力,我们不得不流连于全球最大的同性交友平台 Github,只想着找个免费的轮子以便快速实现需求。一顿噼里啪啦的搜索后,终于你找到了想要的工具,你微微一笑,心想一切都在你的掌握之中。

你花了5分钟时间浏览 README,事实上关于项目的介绍和注意事项你啥也没看进去,就迫不及待的钻进了Quickly-Start。打开工程,引入依赖,ctrl-cv,run,你的动作极其熟练且飘逸,甚至还抽了点时间回复了微信消息,一切都有条不紊,看来今天又是不用加班的一天。诶???wocao,咋报错了,什么鬼,复制粘贴的都能报错?

你慌了,但只慌了两分钟,你迅速的冷静下来了,显然一个小小的报错根本奈何不了你。拷贝错误信息,粘贴到搜索框,回车,进入第一条搜索结果。你按照文章的内容进行了修改,仍然报错,你果断的放弃了这篇文章。半小时后,你发现第二条、第三条和第一条的内容是一模一样的,一气之下你直接关闭了浏览器的这个选项卡。我知道,你还留有后招——stackoverflow,之所以你一开始不用,只是因为你在英语这方面的天赋并不像你的颜值那么耀眼。

你稳健的打开了 stackoverflow 搜索你的问题,并打开了第一个匹配的结果,下拉查看其他用户的回复。尽管满屏都是你熟悉的文字,但你还是选择了右键 -> 翻译成中文(简体)。你终于找到了真正的解决方案,因为你按照回复里的内容修改了项目后,项目正常工作了。你内心窃喜,但强压着不能流于表面,如果不是没有 stackoverflow 账号,你高低得说两句来感谢发布这个回复的老哥。你望着这老哥发布的回复,诶...不对...他说的内容怎么这么眼熟...好像在哪看见过,直到你看见了这条回复的最开始写的是:The following is excerpted from the README of the project repository...

要是运气好,你甚至还有时间逛逛 v2ex,抽几个你感兴趣的帖子,点进去看看评论,你看到了一个好笑的回帖,遗憾的是你没有账号无法跟帖。然后你打开微信,回复所有消息。一看时间,耶,17:35,准备下班,今天又是稳健的一天。

2)如何生成头像

第二天你一到公司就注册了 stackoverflow 和 v2ex 的账号,你本想写点什么感谢提供解决方案的那条回复,但你想想还是算了,我知道你只是不知道如何表达感激之情,并不是因为语言的障碍。你百无聊赖的在主页点来点去,你突然关注到 stackoverflow 给你生成的头像,然后你打开 Github 和 v2ex,发现他们都是类似的头像。就像下面这样:

382827e41dd4e307fa0aa154e48d8637.png

你很疑惑:咦,这些网站是咋个给我生成头像的呢?

3)实现

事实上,我也不知道他们是如何生成头像的,毕竟这些功能的开发我都没有参与,但我可以提供一种替代的相对简单的实现方案。

3-1)头像特征分析

  1. 头像中包含两种颜色,可以想象为先给图像填充一个颜色(背景色),然后在固定的位置使用另一种颜色(前景色)涂绘,构成中间的特征图案;
  2. 特征图案是由一个个小方块拼接而成的,每个小方块就像是一个个像素点;
  3. 头像是左右对称的,左边和右边按照中垂线完全对称;
  4. 头像的特征图案不会完全占据所有的空间,会在最外边留出一定空间的边距。

3-2)实现步骤

  1. 取用户的特征值(比如邮箱地址)通过摘要算法得到一个字节数组;
  2. 用该数组绘制特征图案,数组中每个元素的奇偶性决定对应坐标的是否填充前景色;
  3. 将特征图案按中垂线翻转,得到完整的特征图案;
  4. 此时得到的图像尺寸较小,保持长宽比例放大若干倍后即可得到特征头像;
  5. 给头像增加合适的边框即可。

例如,尽管第一步得到的字节数组为[4, -125, -7, 230...],此时我们希望得到一个 8*8 单位的特征图案。我们的特征图案与数组元素的下标对应关系如下所示。

00 01 02 03 || 03 02 01 00
04 05 06 07 || 07 06 04 04
08 09 10 11 || 11 10 09 08
12 13 14 15 || 15 14 13 12
16 17 18 19 || 19 18 17 16
20 21 22 23 || 23 22 21 20
24 25 26 27 || 27 26 25 24
28 29 30 31 || 31 30 29 28

那么,下标为 00 对应的取值为0(偶数:4),下标为 01 对应的取值为1(奇数:-125)...同理类推。

3-3)代码示例

ImagePipes.ofEmptySource()
        .register(new HashImageGenerator.Builder("nackily@gmail.com")   // 头像生成器
                .gridVerticalNum(8)                                     // 8 * 8
                .bgColor(ColorUtils.of(240, 240, 240))                  // 背景色
                .fgColor(ColorUtils.of(50, 150, 50))                    // 前景色
                .build())
        .toThumbnails()
        .addFilter(new HighQualityExpandHandler.Builder()               // 图像无损放大器
                .finalWidth(300)                                        // 最终宽度
                .keepAspectRatio(true)                                  // 保持长宽比例
                .build())
        .addFilter(new BorderHandler.Builder()                          // 边框处理器
                .fillColor(ColorUtils.of(200, 200, 200))                // 边框背景色
                .alpha(1.0f)                                            // 边框透明度
                .vMargins(20)                                           // 垂直方向的边距
                .hMargins(20)                                           // 水平方向的边距
                .build())
        .scale(1.0)
        .toFile(".../avatar.png");

上述代码片段执行后,将得到如下的头像。

avatar.png

4)关于 Imglib

看到这里你可能反应过来了,没错,我就是来推广项目的,^_^。

4-1)简单介绍

为了不让大家反感,我这里只简单介绍几句话,有兴趣的朋友可以访问主页哦 这里是传送门。以下是 imglib 已有的主要功能:

Imglib 是一个轻量级的 JAVA 图像处理库,立足于简化对图像的常见处理。

  • 除了生成用户头像外,还可以创建其他图像以及截取屏幕图像、从 GIF、PDF 等文档中提取图像;
  • 对图像的常见处理如缩放、裁剪、旋转、图像水印、格式转换、添加边框、马赛克、圆角、灰度化、二值化、绘制形状等;
  • 拆分、拼接图像,多个图像写入 GIF 动图等其他功能。

4-2)项目现状和未来

这个项目目前已经开源,并已发布到 maven-repository。文档也较为齐全了,为许多功能写了使用示例,支持中英文文档。

尽管这个项目才刚起步,已有功能的易用性和实用性还未得到验证,预计在未来的一段时间内能渐渐断的迭代和完善起来,也希望能有志同道合的小伙伴加入进来。同时,俺也希望这个项目能一直向前,向前是需要新鲜血液的,如果你有希望在下个版本实现的新特性,或者任何的意见或者建议,以及任何你想说的,都可以在评论区告诉我!