给网站加个“隐藏”水印

🥺 前排提示,受我自己的技术限制,本篇文章烂尾了

说到网站水印,也许你的第一反应就是那种侵犯隐私便于开发者追踪的盲水印
image

简单来说,可以通过使用人眼无法察觉的颜色变化,通过傅立叶变换在图片频谱图上叠加内容等方式在网站上或 App 里添加一些信息。这些信息会随着你发送图片而传播,并且一般抗干扰,意味着可以抵抗压缩,剪裁或其他图片处理的方式。

留在上面的信息一般也是与你有关的,有说法说是说便于开发者追溯 BUG,至于追溯什么东西,DDDD

不过这次要实现的水印和盲水印不一样。

图片水印#

image

你从大部分社交媒体上直接保存的图片,在右下角都会有这么个水印,一定程度上保护了版权,以及平台回流。更有甚者出现了多重水印
image

如果你在运营一个网站,你当然会希望自己的网站的每张图片都不会有 **“牛皮癣”** ,这也是为什么这个水印基本都在你主动进行保存操作下才会被添加上。不过美观归美观,有些想要借鉴你网站的人直接右键保存图片,转手到自己网站上了怎么办?

没办法从技术上拦截保存,又不好给每张图片都打上牛皮癣;那也试着模仿一下盲水印来搞定网站上的图片怎么样?

颜色上的互相抵消#

我们的目标很明确:图片上有水印,下载下来能直接看见,但是在网站上显示的时候却看不见水印。

那我们只要实现一个叠加图层,这个图层叠加到有水印的图片上时能抵消掉图片上水印的颜色即可。那么也许你能够想到一个概念:互补色
image

这个是色环,对边的颜色等量混合起来会出现褐色或灰色。不过我们网页可不是用的颜料,而是RGB。那么在 RGB 中互补色的定义很简单:两个颜色的每个颜色通道加起来是255,即为互补色。也就是说:

红色(255, 0, 0)的补色是青色(0, 255, 255) 绿色(0, 255, 0)的补色是洋红色(255, 0, 255) 蓝色(0, 0, 255)的补色是黄色(255, 255, 0)

RGB 互补色#

根据这个规则,我只需要两个颜色的文本图层叠加起来就行:

image

可惜电脑上的颜色和颜料又不一样,我们需要把在上层的绿色的透明度设置为 50%,以混合洋红色,得到了一个偏中性的灰色:
image

但是转头一想,你会发现,还有一个洋红色的透明度是 100%,那洋红色底下的内容总不可能凭空脑补出来吧?所以我们相对的还要调整洋红色的透明度。调整到洋红色 50%,绿色 32% 左右,会得到一个还不错的效果。

但是,灰色并不是我们想得到的结果啊?这样的水印还是很明显:
image

所以要依靠一个新东西,图片混合模式。把绿色使用叠加模式,然后调整两个颜色的透明度,你便可得到一个不错的效果:
image
image

那这样算成功了吗?别急,我们的图片总不可能都是黑色的吧,给这张图片点颜色瞧瞧:
image

额... 这样就得到了非常炸裂的效果 😢

彩色图片下的叠加模式#

彩色下的颜色模式还真不好折腾,试来试去得到最好的结果也只有这样:
image

查阅了一圈好像确实没办法仅通过颜色叠加的方式来达到我的理想情况,不过缩小试试看?
image

好像只要不仔细看,这个色差确实不太容易引起人眼察觉。那咱就换个思路,把这个水印做大,做细,让色差范围不连片。但是很遗憾,效果还是不行:
image

这个办法对底色要求很严格,底色也会影响互补色的混合,导致在灰色上的水印会尤其明显。

这个方案仅适用于纯色图片,可能与彩色图片无缘了。那想一想其他办法?

图片处理模式上下手#

虽然就我的理论上来说,没有好办法实现颜色相互抵消这种事情,那我增加借鉴者偷图片的复杂度总行了吧?看一眼图像调整的菜单,处理后能够还原图片信息的,似乎只有反相和替换颜色这两项。
image

反相#

这个我感觉是最好实现的,但是也是最容易被还原的办法。要实现起来很简单,网站侧一句 CSS 就行:

Copy
filter: invert(100%);

image

但是只要稍微接触过图片处理的人就会知道碰见这种图片应该怎么做 😂

还记得之前研究过的反爬虫吗?有些网站会通过动态生成字体来替换文字实现程序输出的和浏览者看到渲染之后的样子不一样;那么实现一个颜色表进行替换怎么样?

替换颜色#

要想在网页里实现对图片的颜色替换,需要用到canvas。但是万万没想到,canvas 2D 的getImageData方法竟然可以实现跨域获取敏感数据:
image
image

那就很糟糕了,虽然我们的目的无害,但是如果要将这个办法通用开来,有跨域问题的存在体验会很差

难道没有别的办法了吗?这时我又想到了 CSS 中强大的filter

filter 属性#

除了用invert函数进行反相,私护还有一个hue-rotate调整色相的函数也不会丢失图像原来的色彩信息。

但我经过简单的实验,你会发现,在 PS 里和 CSS 里对色相的调整竟然出现两种不一样的结果!?
image

我在浏览器里无论怎么调整,都无法得到一样的结果... 那是Safari的问题?也不是,Chrome得到了和Safari一样的色彩表现。那就很奇怪了

两边调整色相到底有什么不一样?#

首先,hue-rotate是旋转色相,为什么是旋转呢?
image

让我们回到这个色环。你可以看到这个圆圈,有360度,所谓的旋转,就是颜色从某个点旋转多少度到目标颜色。比如,位于0度的红色偏橙色,旋转90度就变成了黄色,旋转360度就变回了红色偏橙色。

那我试试直接在两边调整色环不就能看出差别了吗?
image

这一试,我们得到了三个关键信息:

两边调整色相都是在旋转色环,你可以看到在色系上,两边颜色映射是对的。 有一边对于部分颜色的处理上有差异,在 PS 里似乎丢失了较多的颜色信息(绿色的三个块快成一块了) CSS 处理上也丢失了颜色信息
image

😅 这就很尴尬了,如果是旋转的话理论上不会丢失颜色信息啊,但如果情况是这样的话,hue-rotate就不能拿来用了。

灰溜溜收场#

颜色上我做了很多尝试,目前除了最简单的反相确实没有什么很好的解决方案。但是我认为颜色替换是一个很有意思的想法,也许有空可以做一个 demo 实现一下。但是抛开跨域问题,性能上我觉得也会是大问题(毕竟是逐个像素的操作)加之 JS 部分肯定是需要混淆处理的。

那最好的解决方案其实还是加大水印🤔️ 另外一些小儿科的方法(禁止右键,防盗链之类的)就实在是防君子不防小人了。

最后再来一张用 Python 处理旋转色相的图片
image

我真的不理解... 为什么会这样...

文章来源:

Author:时光的时光轴
link:https://xlog.app/api/redirection?characterId=51408¬eId=39