在浏览论坛或评论区的时候,你可能偶尔会遇到一种奇妙的现象:一张图片,在点击放大查看时,呈现出来的内容竟然和最初看到的缩略图完全不同!这个现象让我非常好奇,经过探究我理解了其背后的原理,并且编写了一个简易工具来方便地创建这种图片。
效果展示
下面是一张我制作的可变图片,尝试点击进入大图页面,看看它是不是会变化吧!在博客左上角切换日间/夜间模式同样也可以让图片变化。
小工具
我编写了一个小工具,大家只需要准备两个图像,分别作为表层和里层就可以生成可变图像了。该工具的计算全部由本地浏览器完成,选择的图片不会发送到我的服务器,因此可以放心使用。
工具链接为:https://www.chriskim.cn/image-blender
由于图片是本地处理的,因此不要上传过大的图片,以免把浏览器卡死。电脑端测试时 6400*6400 的图片可以流畅处理。工具代码已经开源在 GitHub,如果觉得写的不错可以给我点星哦~
原理说明
如果你觉得只会用工具制作还不够,想要了解其中原理,那么可以接着往下看。
图片透明叠加规则
首先,我们要了解含透明通道的图片叠加时的融合规则。
若有图片 A 与 B,图片 A 叠加在图片 B 的上面,叠加后形成的图片记为 C. 设图像 A 的像素颜色为 Color_a,透明度为 Alpha_a;图像 B 的像素颜色为 Color_b,透明度为 Alpha_b. 这里的透明度取值是 0~1 的浮点数,0 为全透明,1 为不透明。
那么混合后的图片颜色 Color_c 和透明度 Alpha_c 按以下公式计算:
Color_c = Alpha_a · Color_a + (1 – Alpha_a) · Color_b
Alpha_c = Alpha_a + (1 – Alpha_a) · Alpha_b
简单来说,结果图像的颜色是基于两个图像的颜色和它们各自的透明度加权混合得到的,而最终图像的透明度则反映了两者透明度的组合效果。
可变图像的结构
我们有图片 A 与 B 分别为表层图像和里层图像,我们将其制作成可变图像 C.
比较神奇的是,图片 C 的颜色是固定的,与 A, B 图无关。具体来说,图片 C 的颜色是像国际象棋棋盘一样交错的黑白像素,如下图展示:
既然图片 C 的颜色已经固定了,那就说明它显示的图案仅取决于透明度。为了计算每个像素的透明度,我们先得把 A 和 B 转为灰度图,即每个像素的灰度值用 0 ~ 1 的浮点数表示。
然后参照上面的棋盘格:对于黑色的像素,它的透明度是 A 的灰度值的逆,即 1 – A;对于白色的像素,它的透明度就是 B 的灰度值。
这就是图像 C 的结构了,想必知道这个后,大家也能在十分钟内写好一个生成器了。
为什么能变
为什么按上述规则构造图像 C 就能变化?我们首先要知道的是,很多 APP 在图片预览和图片大图显示时背景颜色是不一样的。图片预览时,背景是白色的;点进去进入大图显示时,背景是黑色的。
那么我们联系刚才提到的叠加规则和图像结构:
- 黑底时
- 对于黑色像素,它与背景颜色相同:Color_c = Alpha_a · 0 + (1 – Alpha_a) · 0 = 0 = 黑色
- 对于白色像素,它与背景颜色不同:Color_c = Alpha_b · 1 + (1 – Alpha_b) · 0 = Alpha_b
- 黑色像素来源于图片 A 全部变成黑色了,图案不可见了。
- 白色像素来源于图片 B,它通过与黑底进行透明叠加显示出了图片 B 的效果。
- 白底时
- 对于黑色像素,它与背景颜色不同:Color_c = Alpha_a · 0 + (1 – Alpha_a) · 1 = 1 – Alpha_a
- 对于白色像素,它与背景颜色相同:Color_c = Alpha_b · 1 + (1 – Alpha_b) · 1 = 1 = 白色
- 黑色像素来源于图片 A,它通过与白底进行透明叠加显示出了图片 B 的效果。
- 白色像素来源于图片 B 全部变成白色了,图案不可见了。
综上,这便是有趣的可变图片的原理了。可以发现至关重要的就是透明度了,这也是为什么有些时候发出去的可变图片,别人收到后并不可变:因为可能被平台进行二次压缩,透明度被丢弃了。因此要提醒对方点击查看原图,才能实现变化效果。
发表回复