需求:现需要将一段字符串密码隐藏到一张图片当中
先说一下我想的实现思路把,下面有展示代码:
我们都知道利用canvas上线文对象的drawImage方法可以将图片绘制到画布上;利用getImageData方法可以获取到画布的像素数据,获取到的对象有个data属性,这是个数组,这个数组就描述了每个像素点的颜色信息。具体规则为:数组的每四个数为一组,分别表示rgba()中的红色,绿色,蓝色,透明度;
如果我们获取到这个数组之后将一部分元素替换成字符串密码对应的Unicode编码,然后生成一张新的图片,那么这个新图片就携带了我们想要的信息。我们只需要再次拿到新图片的像素,从数组中拿到这些改过的元素,就可以根据Unicode编码就拿到我们的明文字符串了。
直接看代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas1"></canvas>
<button id="create">生成加密的图片</button>
<script>
var pic;
var canvas;
var ctx;
var imgData;
var data;
window.onload = function () {
canvas = document.getElementById("canvas1");
ctx = canvas.getContext("2d");
canvas.width = 88;
canvas.height = 88;
pic = new Image();
pic.src = "./img/1.png";
pic.onload = function () {
console.log(pic.width,pic.height);
ctx.drawImage(pic, 0, 0, 88, 88);
// 获取图片的像素数据
imgData = ctx.getImageData(0, 0, 88, 88);
data = imgData.data;
console.log('打印最初的像素数据',JSON.parse(JSON.stringify(data)) )
// 根据密码的Unicode编码来修改像素数据
var s = encodeURI("abcd");
for (var j = 0; j < s.length; j++) {
console.log("打印编码",s.charCodeAt(j))
data[j] = s.charCodeAt(j);
}
console.log('打印修改后的像素',JSON.parse(JSON.stringify(data)) )
// 将修改后的像素数据绘制到画板
ctx.putImageData(imgData,0,0);
var dImgData = ctx.getImageData(0,0,88,88);
var dData = dImgData.data;
console.log('打印第二次拿到的像素数据',JSON.parse(JSON.stringify(dData)));
}
// 保存待密码的图片
create.onclick=function(){
let urlData = canvas.toDataURL()
let downLoadA=document.createElement('a')
downLoadA.setAttribute('download','携带密码的图片')
downLoadA.href=urlData
downLoadA.click()
}
};
</script>
</body>
</html>
如上图所示,遇到的问题是我们在修改了获取到的像素数据之后得到新的像素数据(我们称为 ‘像素数据A’ ),将 ‘像素数据A’ 重新绘制到画布上。然后再次获取像素(我们称为‘像素数据B’),像素数据A和像素数据B是不一样的。这是为什么呢?请各位码友解答
ps:上例中我们使用的密码是abcd,有四位;我修改的是数组的前四个元素(他们对应下标是0,1,2,3),如果我们修改的的元素下标是3,7,11,15;那么就不会出现像素数据A和像素数据B是不一样的的情况。