为了保障信息安全,防止重大信息泄露,并且能够锁定泄露用户,需要对页面展示的图片加入当前用户信息的盲水印,即最终图片外观看起来和原图一样,但是经过解码以后可以识别出水印信息,并且在截图后仍能进行较好的识别。

  经过在网上的学习摸索,看了几位大神的博客以后,我也总结一下自己的代码,分享一下学习经验。

  我们将使用以下图片作为原图进行示范:

  

  

下面是图片添加盲水印的代码:

<script>
var canvas = document.getElementById("myCanvas")
var ctx = canvas.getContext("2d")
var img = new Image();
var textData,originalData;
img.src = './codeImg.png'
//图片加载完成
img.onload = function(){
//设置画布宽高为图片宽高
canvas.width = img.width;
canvas.height = img.height;
//设置水印字体
ctx.font = '30px Microsoft Yahei';
//由于图片宽度固定为800,我们需要在每一行添加三个水印,每隔100像素新增一行水印
for(var i=50;i<canvas.height;i+=100){
ctx.fillText('周杰伦', 100, i);
ctx.fillText('周杰伦', 300, i);
ctx.fillText('周杰伦', 600, i);
} //此时画布上已经有了水印的信息,我们获取水印的各个像素的信息
textData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
//将图片绘入画布
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
//获取图片各个像素点的信息,我们将originalData打印出来,我们会发现是一个非常大的数组(由于文字和图片在同一块画布,因此textData的长度等于originalData长度)
//这个数组的长度等于图片width*height*4,即图片像素宽乘以高乘以4,0-3位是第一个点的RGBA值,第4-7位是第二个点的RGBA值,以此类推
originalData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
//调用盲水印算法
mergeData(ctx, textData, 'R', originalData)
} function mergeData(ctx, textData, color, originalData) {
var oData = originalData.data;
var newData = textData.data
var bit, offset; // offset的作用是找到alpha通道值,这里需要大家自己动动脑筋 switch (color) {
case 'R':
bit = 0;
offset = 3;
break;
case 'G':
bit = 1;
offset = 2;
break;
case 'B':
bit = 2;
offset = 1;
break;
} for (var i = 0; i < oData.length; i++) {
//此处是为了筛选我们要修改的RGB中那一项,在此处,过滤出来的就是每个坐标点的R值
if (i % 4 == bit) { //我们获取到R值的位置,那对应这个点的A值就是i+offset
if (newData[i + offset] === 0 && (oData[i] % 2 === 1)) {
//此处先判断该坐标点的透明度,如果为0,说明这个点是没有水印的,将没有水印信息点的R值变为偶数,并且不能超过0-255的范围
if (oData[i] === 255) {
oData[i]--;
} else {
oData[i]++;
}
} else if (newData[i + offset] !== 0 && (oData[i] % 2 === 0)) {
//透明度非0,该点有信息,若该点的R值是偶数,将其改为奇数
oData[i]++;
}
}
}
//至此,整个图片中所有包含水印信息的点的R值都是奇数,没有水印信息的点的R值都是偶数,再将图片绘入画布,即完成整个水印添加过程
ctx.putImageData(originalData, 0, 0);
} </script>

至此,我们在页面上绘制出了带有盲水印的图片,我们先看看解码前后对比效果:

以下是右键另存为的图片及解码后的图片,受色彩识别度的误差影响,会有部分图片内容也被识别成水印内容,不过还是可以比较清晰看到水印文字

以下是使用屏幕截图的图片及解码图片:截图后的图片仍然能够识别出水印信息

接下来是水印解码的js代码:

<script>
var canvas = document.getElementById("myCanvas")
var ctx = canvas.getContext("2d")
var img = new Image()
img.src = './decode.png'
// 图片加载完成
img.onload = function(){
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height); // 将带有盲水印的图片绘入画布,获取到像素点的RGBA数组信息
originalData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); processData(ctx,originalData);
} function processData(ctx, originalData) {
var data = originalData.data;
for (var i = 0; i < data.length; i++) {
//筛选每个像素点的R值
if (i % 4 == 0) {
if (data[i] % 2 == 0) {//如果R值为偶数,说明这个点是没有水印信息的,将其R值设为0
data[i] = 0;
} else {//如果R值为奇数,说明这个点是有水印信息的,将其R值设为255
data[i] = 255;
}
} else if (i % 4 == 3) {//透明度不作处理
continue;
} else {
// G、B值设置为0,不影响
data[i] = 0;
}
}
// 至此,带有水印信息的点都将展示为255,0,0 而没有水印信息的点将展示为0,0,0 将结果绘制到画布
ctx.putImageData(originalData, 0, 0);
}
</script>

  现在,我们基本已经完成了前期预计的盲水印效果,但是,前端的安全处理还是会有隐患,比如打开控制台,即可获取到原图的链接地址,并可以直接保存。

  所以若要更好的保障信息安全,这个添加盲水印的方法在后端去处理可能更加有效。

  

本文算法内容参考自:https://juejin.cn/post/6900713052270755847

前端使用canvas生成盲水印的加密解密的更多相关文章

  1. 生成二维码 加密解密类 TABLE转换成实体、TABLE转换成实体集合(可转换成对象和值类型) COOKIE帮助类 数据类型转换 截取字符串 根据IP获取地点 生成随机字符 UNIX时间转换为DATETIME\DATETIME转换为UNIXTIME 是否包含中文 生成秘钥方式之一 计算某一年 某一周 的起始时间和结束时间

    生成二维码 /// <summary>/// 生成二维码/// </summary>public static class QRcodeUtils{private static ...

  2. openssl生成CA签署 及 加密解密基础

    openssl  生成私有CA 及签署证书 openssl 配置文件: /etc/pki/tls/openssl.cnf 1. 在openssl CA 服务器端生成私钥 cd /etc/pki/CA/ ...

  3. 前端基于Canvas生成等值面的方案

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在之前的项目中,我们做过基于PM2.5的站点监测数据对全区域进 ...

  4. PHP 生成公钥私钥,加密解密,签名验签

    test_encry.php <?php //创建私钥,公钥 //create_key(); //要加密内容 $str = "test_str"; //加密 $encrypt ...

  5. PHP通过OpenSSL生成证书、密钥并且加密解密数据,以及公钥,私钥和数字签名的理解

    一.公钥加密假设一下,我找了两个数字,一个是1,一个是2.我喜欢2这个数字,就保留起来,不告诉你们(私钥),然后我告诉大家,1是我的公钥. 我有一个文件,不能让别人看,我就用1加密了.别人找到了这个文 ...

  6. iOS使用Security.framework进行RSA 加密解密签名和验证签名

    iOS 上 Security.framework为我们提供了安全方面相关的api: Security框架提供的RSA在iOS上使用的一些小结 支持的RSA keySize 大小有:512,768,10 ...

  7. 结合jquery的前后端加密解密 适用于WebApi的SQL注入过滤器 Web.config中customErrors异常信息配置 ife2018 零基础学院 day 4 ife2018 零基础学院 day 3 ife 零基础学院 day 2 ife 零基础学院 day 1 - 我为什么想学前端

    在一个正常的项目中,登录注册的密码是密文传输到后台服务端的,也就是说,首先前端js对密码做处理,随后再传递到服务端,服务端解密再加密传出到数据库里面.Dotnet已经提供了RSA算法的加解密类库,我们 ...

  8. C# 加密–RSA前端与后台的加密&解密

    1. 前言 本问是根据网上很多文章的总结得到的. 2. 介绍 RSA加密算法是一种非对称加密算法. 对极大整数做因数分解的难度决定了RSA算法的可靠性.换言之,对一极大整数做因数分解愈困难,RSA算法 ...

  9. 加密–RSA前端与后台的加密&解密

    1. 前言 本问是根据网上很多文章的总结得到的. 2. 介绍 RSA加密算法是一种非对称加密算法. 对极大整数做因数分解的难度决定了RSA算法的可靠性.换言之,对一极大整数做因数分解愈困难,RSA算法 ...

随机推荐

  1. Annotation注解初识

    注解本质上就是一个接口,该接口默认继承Annotation接口 元注解 元注解的作用就是描述其他注解.Java1.5定义了4个标准的meta-annotation类型,它们被用来提供对其它 annot ...

  2. iczer的vue-antd-admin项目,逐步平滑迁移mock的url

    这个需求,在实战中蛮有用的.但没有看到网上太多文档,就自己hack了一个思路.供指正. 需求 在前后端分离的项目开发中,前后端的开发步骤和进度是不一致的.有时,前端为了不等待后端的API开发进度,会自 ...

  3. python编码规范以及推导式的编写

    一.python 的编码规范

  4. How to realize one's ambition

    Work Overtime Can it work? To some extent, it parhaps works very well. What if you do little job and ...

  5. 下载器Folx如何实现排队下载功能

    用户在下载多个文件时,当然会希望这些文件都能同时下载,以达到短时间内完成下载任务的目的.但另一方面来说,同时下载过多文件,会分散带宽资源,降低了每个文件的下载速度,从而导致下载时间的延长. 为了实现多 ...

  6. And Or IN Not操作符

    再sql中And比or运算符优先级要更高,比如说  条件1 Or 条件2 And 条件3     如果先执行or,就是1or2   再and3 但是实际上是  2and3 再or 1,所以如果想要 1 ...

  7. django基本内容

    1,流程 1.1 了解web程序工作流程 1.2 django生命周期 2,django介绍 ​ 目的:了解Django框架的作用和特点 ​ 作用: 简便.快速的开发数据库驱动的网站 django的优 ...

  8. 安装了向日葵或TeamViewer导致系统亮度无法调节

    1.向日葵 安装向日葵造成无法调节亮度的原因:可能为了使用向日葵的黑屏模式功能,误装了向日葵的驱动.建议不要使用该功能. 关于安装向日葵的用户,请参考以下步骤解决: 请保持电脑处于联网状态,并关闭了向 ...

  9. Spring 源码阅读环境的搭建

    前言 本文记录了 Spring 源码环境的搭建方式,以及踩过的那些坑!​当前版本:5.3.2-SNAPSHOT. 环境准备 Git JDK master 分支需要 JDK 11 5.2.x 分支, J ...

  10. 蒲公英 · JELLY技术周刊 Vol.32: 前端的自我进化之路

    蒲公英 · JELLY技术周刊 Vol.32 前端开发不过是切图仔在那儿瞎鼓捣,没啥门槛,不需要懂计算机原理,不需要懂算法,微服务.高并发这些都不需要懂,拖组件写个页面就好了,数据.逻辑.测试都可以交 ...