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,发现他们都是类似的头像。就像下面这样:
你很疑惑:咦,这些网站是咋个给我生成头像的呢?
3)实现
事实上,我也不知道他们是如何生成头像的,毕竟这些功能的开发我都没有参与,但我可以提供一种替代的相对简单的实现方案。
3-1)头像特征分析
- 头像中包含两种颜色,可以想象为先给图像填充一个颜色(背景色),然后在固定的位置使用另一种颜色(前景色)涂绘,构成中间的特征图案;
- 特征图案是由一个个小方块拼接而成的,每个小方块就像是一个个像素点;
- 头像是左右对称的,左边和右边按照中垂线完全对称;
- 头像的特征图案不会完全占据所有的空间,会在最外边留出一定空间的边距。
3-2)实现步骤
- 取用户的特征值(比如邮箱地址)通过摘要算法得到一个字节数组;
- 用该数组绘制特征图案,数组中每个元素的奇偶性决定对应坐标的是否填充前景色;
- 将特征图案按中垂线翻转,得到完整的特征图案;
- 此时得到的图像尺寸较小,保持长宽比例放大若干倍后即可得到特征头像;
- 给头像增加合适的边框即可。
例如,尽管第一步得到的字节数组为[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");
复制代码
上述代码片段执行后,将得到如下的头像。
4)关于 Imglib
看到这里你可能反应过来了,没错,我就是来推广项目的,^_^。
4-1)简单介绍
为了不让大家反感,我这里只简单介绍几句话,有兴趣的朋友可以访问主页哦 这里是传送门。以下是 imglib 已有的主要功能:
Imglib 是一个轻量级的 JAVA 图像处理库,立足于简化对图像的常见处理。
- 除了生成用户头像外,还可以创建其他图像以及截取屏幕图像、从 GIF、PDF 等文档中提取图像;
- 对图像的常见处理如缩放、裁剪、旋转、图像水印、格式转换、添加边框、马赛克、圆角、灰度化、二值化、绘制形状等;
- 拆分、拼接图像,多个图像写入 GIF 动图等其他功能。
4-2)项目现状和未来
这个项目目前已经开源,并已发布到 maven-repository。文档也较为齐全了,为许多功能写了使用示例,支持中英文文档。
尽管这个项目才刚起步,已有功能的易用性和实用性还未得到验证,预计在未来的一段时间内能渐渐断的迭代和完善起来,也希望能有志同道合的小伙伴加入进来。同时,俺也希望这个项目能一直向前,向前是需要新鲜血液的,如果你有希望在下个版本实现的新特性,或者任何的意见或者建议,以及任何你想说的,都可以在评论区告诉我!