前端给页面添加暗水印的办法

上一篇文章讲到了在页面上添加明水印的方法,但是明水印比较好清除,而且对于一些没做处理的图片,当用户直接保存的时候,是没有水印的,这时候信息泄露问题依然存在。为了解决这样的问题,我们需要用到暗水印。

实现思路

我们知道图片是由多个像素点组成的,通过canvas的getImageData方法,我们可以得到画布指定矩形的像素数据

getImageData() 方法返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。

对于 ImageData 对象中的每个像素,都存在着四方面的信息,即 RGBA 值:

  • R - 红色 (0-255)
  • G - 绿色 (0-255)
  • B - 蓝色 (0-255)
  • A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)

值得注意的是:RGB 分量值的小量变动,是肉眼无法分辨的,不影响对图片的识别。这是我们在图片上添加暗水印的基石

color/alpha 以数组形式存在,并存储于 ImageData 对象的data属性中。

以下代码可获得被返回的 ImageData 对象中第一个像素的 color/alpha 信息:

red=imgData.data[0];
green=imgData.data[1];
blue=imgData.data[2];
alpha=imgData.data[3];

感兴趣的同学可以打印看一下效果

function createBackgroundImage(content, proportion, tiltAngle) {const can = document.createElement('canvas')can.width = document.body.clientWidth / proportioncan.height = document.body.clientHeight / proportionconst context = can.getContext('2d')context.rotate(-25 * Math.PI / 180);context.font = "800 30px Microsoft JhengHei";context.fillStyle = "#000";context.textAlign = 'center';context.textBaseline = 'Middle';context.fillText(content, 100, 100)console.log(context.getImageData(0, 0, can.width, can.height))return can.toDataURL("image/png")
}
const div = document.getElementById('content')console.log('div', div)div.style.backgroundImage = `url(${createBackgroundImage('伯约同学', 6, 10)})`

如下所示,给出了对应图片的ImageData结果,它有以下几个属性

  1. data: Uint8ClampedArray(52752) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …]
  2. colorSpace: “srgb”
  3. height: 42
  4. width: 314
  5. [[Prototype]]: ImageData

Uint8ClampedArray则是对应的像素点,每四个表征一个像素点,然后从左往右,从上往下的顺序进行排列。

下面进行一个简单的加密:把加密图案放到原图中,如果原图中对应的重叠像素点有内容,则最低位为1,否则为0

function mergeData(rawImageSrc, watermarkImageSrc) {return new Promise((resolve, reject) => {const img = new Image()img.onload = function () {const myCanvas = document.createElement("canvas");myCanvas.width = img.width;myCanvas.height = img.height;const ctx = myCanvas.getContext("2d")const bit = 0const offset = 3const oImageData = getImageData(rawImageSrc)const oData = oImageData.dataconst newData = getImageData(watermarkImageSrc).datafor (let i = 0; i < oData.length; i++) {if (i % 4 === bit) {// 只修改目标通道if (newData[i + offset] === 0 && (oData[i] % 2 === 1)) {// 没有信息的像素,将目标通道的奇数像素改为偶数if (oData[i] === 255) {oData[i]--} else {oData[i]++}} else if (newData[i + offset] !== 0 && (oData[i] % 2 === 0)) {// 有信息的像素oData[i]++}}}ctx.putImageData(oImageData, 0, 0)resolve(myCanvas.toDataURL("image/png"))}img.src = rawImageSrc})function getImageData(image) {const img = new Image()img.src = imageconst myCanvas = document.createElement("canvas");myCanvas.width = img.width;myCanvas.height = img.height;const myContext = myCanvas.getContext("2d")myContext.drawImage(img, 0, 0);return myContext.getImageData(0, 0, myCanvas.width, myCanvas.height)}

对应的解密方法

function decrypt(watermarkImage) {return new Promise((resolve, reject) => {const img = new Image()img.onload = function () {const myCanvas = document.createElement("canvas");myCanvas.width = img.width;myCanvas.height = img.height;const ctx = myCanvas.getContext("2d")const imageData = getImageData(watermarkImage)var data = imageData.data;for (var i = 0; i < data.length; i++) {if (i % 4 == 0) {// 红色分量if (data[i] % 2 == 0) {data[i] = 0;} else {data[i] = 255;}} else if (i % 4 == 3) {// alpha通道不做处理continue;} else {// 关闭其他分量,不关闭也不影响答案,甚至更美观 o(^▽^)odata[i] = 0;}}ctx.putImageData(imageData, 0, 0)resolve(myCanvas.toDataURL("image/png"))}img.src = watermarkImage})
}

核心示例代码

    const image1 = createBackgroundImage('伯约', 3, 10)const image2 = createBackgroundImage('学', 3, 10)mergeData(image1, image2).then(res => {console.log('res', res)decrypt(image2).then(res => {console.log('finalImage', res)})})

展示上面的res和finallImage并进行对比大仙,一张是两个字:伯约 另一张只有一个字:学
第一张:
第二张:

诚然,上面这个方法并不普适,毕竟加密解密方法都写成固定的了,不过思路是统一的,那就是都在原图的基础上修改像素点。

关于更多内容
姊妹篇
明水印:
https://jinbitao.blog.csdn.net/article/details/122902264

具体可以看一下参考文章

1、https://cloud.tencent.com/developer/article/1841652

2、https://www.cnblogs.com/deeproom/p/14212568.html

3、https://blog.csdn.net/qq_44197554/article/details/122648423

前端给页面添加暗水印的办法相关推荐

  1. 前端页面添加全局水印或指定页面添加水印

    前言 为了防止信息泄露或知识产权被侵犯,在web的世界里,对于图片文档等增加水印处理是十分有必要的.水印的添加根据环境可以分为两大类,前端浏览器环境添加和后端服务环境添加. 今天介绍的就是通过canv ...

  2. 使用JS(watermark)给HTML页面添加文字水印(全网最简单,最详细,复制即用,提供源码链接)

    前言: 最近在做项目,PD提需求让做一个页面水印,百度到的答案好像大部分都是图片的,要么七七八八的,百度了好久,现在总结出来了这个精简中的精简版的教程,与大家分享.(源码下载链接在文章末尾,如果不想看 ...

  3. java 给图片添加暗水印_java 实现给图片添加水印

    原图如下: 代码如下: package test; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Fon ...

  4. 如何给web页面添加一个水印

    微信搜一搜 "胖蔡话前端" 前端公众号,关注更多前端咨询.欢迎访问个人博客[EnjoyToday.cn)(http://www.enjoytoday.cn) 水印原理 我们经常看到 ...

  5. 计算机页面添加文字水印在哪,怎么添加水印-Word小技巧-快速添加高大上的水印...

    不知道各位小伙伴是否见过这样的文档,带有类似[内部文件]/[严禁外泄]水印的文档,是不是觉得很高大上,神圣而不可侵犯的感觉油然而生?只需要一分钟,小编教你如何为文档快速添加水印. 一.添加水印 切换到 ...

  6. 给你的web页面添加盲水印,附带检盲水印方案

    应用场景 在一些敏感系统有的时候我们为了防止别人截图或追溯图片源头是谁发的.我们需要在页面上埋下我们的隐形水印. 开始做 埋水印 github上有很多水印的js插件,download下来一个改一改,源 ...

  7. Jsp 页面添加动态水印

    //从session 中读取需要的信息 <% javacommon.base.LoginUser user = (javacommon.base.LoginUser) session.getAt ...

  8. java 给图片添加暗水印_Java实现给图片添加水印

    使用Java给图片添加水印 根据需求给图片添加水印,直接上代码 /** * 给图片添加水印 */ public void addWaterMark() { Color color = new Colo ...

  9. Android给文档加水印,android:给整个页面添加上水印

    [实例简介] 这个demo实现了在整个activity上加上水印的效果,加上水印后对别的控件没有任何影响 [实例截图] [核心代码] WaterMark └── WaterMark ├── Andro ...

最新文章

  1. VIM 的方向键 h(左)、j(下)、k(上)、l(右)
  2. ecs加解密_ECS云盘加密
  3. html 搜索框 自动补全,自动完成的搜索框javascript实现
  4. 机器学习模型的可解释性
  5. Python基础学习3——集合、文件、函数
  6. __new__()方法的使用和实例化
  7. Android按下多任务java_Android 使用AsyncTask实现多任务多线程断点续传下载
  8. 小米air2se耳机只有一边有声音怎么办_别光盯着AirPods,这些无线蓝牙耳机,其实也很好用...
  9. 实验一 winrunner的安装使用
  10. Linux服务器上修改深度学习代码
  11. 寻路机器人单片机程序示例_单片机c语言示例程序
  12. 骗子华中帝国,诈骗犯QQ860100371
  13. 【审稿意见】科研菜鸟如何攥写审稿意见?万能模板!!!
  14. 基于Autojs的淘宝/京东618自动化
  15. 一味研究:岩石股份摘帽即收“两连板”,海银系要认真酿酒了吗?
  16. windows批处理批量更改文件名称
  17. VSCdoe 插件开发
  18. 分词器——ik——分词算法
  19. 【树莓派智能门锁】电机锁控制电源测试【2】
  20. c语言中符号起什么作用,C语言中的符号 和 | 是什么意思?

热门文章

  1. Logstash对接 SNMP v2和 v3
  2. 一键过滤选择百度网盘文件
  3. 在网页中显示数学公式
  4. mac 4k分辨率 字太小 27寸 hidpi_电视机4a和4k的区别
  5. python3爬虫-爬取新浪新闻首页所有新闻标题
  6. Macbook air 2013安装windows7,解决鼠标键盘失灵问题的解决方法(集成USB3.0驱动的方法)
  7. 信号与系统(八)——卷积积分的应用
  8. 应变测量的传统方法与DIC(数字图像相关)方法
  9. java strtotime_强大的strtotime函数
  10. URAL 1200 - Horns and Hoofs(暴力+剪枝)