制备幻影坦克

幻影坦克

1.介绍

有些图片在qq或者贴吧等平台上,正常情况是一张图片此时背景是白色,但是打开放大变成了另一种图片此时背景是黑色,因为其表现形式像红色警戒的幻影坦克,因此将这类图片称作幻影坦克。其实这类图片是png图片,众所周知png图片有透明度,正是因为这个特性就可以让图片在不同背景下显示出不同图片成为可能。接下来介绍如何制作这类图片。

2.图像混合

在调用canvas的context的getImageData方法后,会返回一个对象,其中data属性包含这个图片的像素颜色信息。每个像素有四个数据分别是rgba,其中第四个数据是不透明度。这四个数据的取值范围均为0-255。a的数值越大越不透明,255为完全不透明,0为完全透明。那如果取值在这个中间图片会是什么样子的呢。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> r m i x = r 1 ∗ α + r 2 ∗ ( 1 − α ) r_{mix} = r_1*α+ r_2*(1-α) </math>rmix=r1∗α+r2∗(1−α)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> g m i x = g 1 ∗ α + g 2 ∗ ( 1 − α ) g_{mix} = g_1*α+ g_2*(1-α) </math>gmix=g1∗α+g2∗(1−α)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> b m i x = b 1 ∗ α + b 2 ∗ ( 1 − α ) b_{mix} = b_1*α+ b_2*(1-α) </math>bmix=b1∗α+b2∗(1−α)

其中mix下标图像混合后的色值,1下标为上面的图片色值,2下标为下面的图片或者说背景色值。

可以做个实验,左边是色值改为混合后的色值,其中背景是白色,右边是改变不透明度,其背景是白色,每隔100ms改变一次,最后的效果一致。

有了上面的公式一切都好办了。根据这个公式,我们可以得出一张png图片在不同的背景下的色值。如果把在白色背景下呈现的图片叫做表图,在黑色背景下呈现的图片叫做里图。在知道了表图以及里图的色值,就可以根据这个公式计算出这张png图片的色值以及透明度。这样就可以让这张图片在黑白不同的背景下呈现出不同的图片。

3. 从隐藏一个阿卡林开始

如果我想让表图是白色的图片,让里图是阿卡林的话,代入公式可得,下标为表代表表图的色值,下标为里代表里图的色值。白色的rgb为255,黑色的rgb为0。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> r 表 = r ∗ α + 255 ∗ ( 1 − α ) r_表 = r*α+ 255*(1-α) </math>r表=r∗α+255∗(1−α)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> g 表 = g ∗ α + 255 ∗ ( 1 − α ) g_表 = g*α+ 255*(1-α) </math>g表=g∗α+255∗(1−α)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> b 表 = b ∗ α + 255 ∗ ( 1 − α ) b_{表} = b*α+ 255*(1-α) </math>b表=b∗α+255∗(1−α)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> r 里 = r ∗ α r_里 = r*α </math>r里=r∗α
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> g 里 = g ∗ α g_里 = g*α </math>g里=g∗α
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> b 里 = b ∗ α b_{里} = b*α </math>b里=b∗α
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> α = ( r 里 − r 表 ) / 255 + 1 = ( g 里 − g 表 ) / 255 + 1 = ( b 里 − b 表 ) / 255 + 1 α = (r_里-r_表)/255+1=(g_里-g_表)/255+1=(b_里-b_表)/255+1 </math>α=(r里−r表)/255+1=(g里−g表)/255+1=(b里−b表)/255+1
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> r = r 里 / α , g = g 里 / α , b = b 里 / α r=r_里/α,g=g_里/α,b=b_里/α </math>r=r里/α,g=g里/α,b=b里/α

可以发现要想完美实现需求的话,需要里图与表图的rgb差值相同才行,这也是为啥大部分的幻影坦克用的基本是灰度图的原因,当rgb相同的时候颜色就是灰色的,数值越大越白,越小越黑。另外表图是白色也是不可能完成的需求,如果要求表图为白色就要求混合后的图片要么rgb都为255,要么不透明度为零。但是可以降低要求让表图的rgb尽可能大,尽可能偏白。如果将表图rgb设置为250灰白,一般人看不出会认为是白色。同时将阿卡林的图片变成灰度图。灰度的公式如下

avg =0.299 * r +0.587 * g +0.114 * b 将rgb都设置成avg就行,至于这三个系数是怎么来的,老实说我也不清楚,但是效果挺好的。于是就得到了如下的公式。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 250 = r g b ∗ α + 255 ( 1 − α ) , r g b 里 = r b g ∗ α 250 = rgb*α+255(1-α),rgb_里 = rbg*α </math>250=rgb∗α+255(1−α),rgb里=rbg∗α
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> α = ( r g b 里 − 250 ) / 255 + 1 , r g b = r g b 里 / α α = (rgb_里-250)/255+1,rgb = rgb_里/α </math>α=(rgb里−250)/255+1,rgb=rgb里/α

可以发现效果非常的amazing啊,另外在背景颜色为白色的情况下,表图其实不是白色,看的出来有点灰准确的讲是rgb为250的灰白色,不细看还看不出来。

那如果就是要里图是有颜色的,而不是灰色图的话要怎么办。可以尝试一下让表图的rgb不相同,试着让其尽量大偏白,这就相当于让一个不透明度变小,或者说选择里图中rgb最小的值进行计算不透明度,从而计算表图的rgb。

最终的效果,只能说在黑色背景下图片是完美显示,只是在白色背景下隐藏不了,加一层灰色的遮罩都隐藏不了,因为表图的rgb值不同所以会表现出彩色,图片隐藏不住。换句话说,如果想在黑色背景下完美展示,并在白色背景下完美隐藏的彩色图片理论上是不存在的。

4. 制作一个真正的幻影坦克

如果有一张图片想要在白色背景下展示叫做表图,另一张图片想要在黑色背景下展示加做里图。代入公式可得。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> α r g b = ( r g b 里 − r g b 表 ) / 255 + 1 , r g b = r g b 里 / α α_{rgb} = (rgb_里-rgb_表)/255+1,rgb = rgb_里/α </math>αrgb=(rgb里−rgb表)/255+1,rgb=rgb里/α

可以发现,要想完美实现一个幻影坦克就要表图的色值大于里图的色值,不然的话α会大于一,出现异样,具体表现就是在白色背景下会显示出里图。为了更好的隐藏里图可以让里图更暗一些,具体的做法就是将里图的色值等比例的缩小,不过缩的太小,里图会变的很暗,在黑色背景就不太好显示。在选择里图的时候可以考虑色值比较小的图片。

chunxi666.github.io (在线体验)

github.com/ChunXi666/C... (给个star,求求了)

相关资料

『整活』幻影坦克 基础版

幻影坦克架构指南(一)

"幻影坦克"图片的原理和任意两张图片合成幻影坦克图的完备性讨论

相关推荐
任小栗16 分钟前
Vue 3 面试题全套题库
前端·javascript·vue.js
李蚊子30 分钟前
前端开发范式的革命性转变:从编码者到意图架构师
前端·javascript·人工智能
小高00738 分钟前
为什么JavaScript的Set比Array更适合某些场景
前端·javascript
掘金0139 分钟前
ExcelJS 初学者教程:在 Vue 项目中实现表格数据导出
前端·javascript·vue.js
BUG收容所所长1 小时前
从CSS到React Spring,你的Web应用动起来了吗?
前端·javascript·css
JohnYan1 小时前
Bun技术评估 - 19 MQ(NATS)
javascript·后端·bun
飛_1 小时前
【Word Press基础】创建一个自定义区块
前端·javascript·html·word press
言兴2 小时前
React 性能优化之道:从 Hook 到组件设计的深度剖析
前端·javascript
言兴2 小时前
预备秋招面试之Mock.js
前端·javascript·面试
PineappleCoder2 小时前
JS异步编程:从回调地狱到Async/Await的华丽转身
前端·javascript·ecmascript 6