之前在qq群里看到老司机发了一张图片,表面看起来挺正经,点开放大之后变成了另一张图…

不正经的图.png

原理其实很简单,qq里的图片,没点开时是白底,点开后会换成黑底背景,只不过被图片覆盖了看不出来。 如果图片本身是半透明的,那由于白底黑底的切换,就会实现有趣的换图效果。

img

(通过切换本页面的深浅色模式可以看到一定效果,在qq中效果明显,微信无效。

因为本人对ps等图片处理软件还不太熟练,所以用python写了个能达到同样效果的小脚本,代码如下

from PIL import Image

input_img1 = './input1.png'
input_img2 = './input2.png'
output_img = './output.png'

# 读取两张图片,并转换成灰度图
img1 = Image.open(input_img1).convert('L')
img2 = Image.open(input_img2).convert('L')

# 用第一张图片的尺寸作为输出图片的尺寸
width, Height = img1.size
img2 = img2.resize(size=img1.size)

# 新创建一个图片对象, 模式为灰度图加上Alpha通道,尺寸和第一张图片相同
img3 = Image.new('LA', size=(width, Height))

# 遍历第一张图片的每一个像素点,坐标为(l, h)
for x in range(width):
for y in range(Height):
xy = (x, y)
L1 = img1.getpixel(xy)
L2 = img2.getpixel(xy)

# 设输出图像在xy坐标点的灰度值为L3, alpha值为A, 二者的取值范围都为(0, 255)
# 则该点的不透明度: A% = A / 255
# 由透明度叠加算法,列出下面算式
# 黑底: L3 * A% = L1 / 2
# 白底: L3 * A% + 255 * (1 - A%) = (L2 + 255) / 2
# 解得:
L3 = int(L1 * 255 / (L1 - L2 + 255))
A = int((255 + L1 - L2) / 2)

# 将算出的值填入图片
img3.putpixel(xy, (L3, A))

# 保存输出图片
img3.save(output_img)