js图片隐写-找出图片中隐藏的漂亮小姐姐

一、什么是图片隐写术

图片隐写术是一门关于信息隐藏的技巧与科学,通过对普通图片进行处理,让人无法察觉其中隐藏的“机密”数据。

你能想象上面这张风景中其实藏着一个漂亮的小姐姐吗?

接下来,我们将一步一步去分析我们是怎么将小姐姐放入一张风景图又该怎么从看似普通的风景图中取出我们收藏的小姐姐的。

二、如何实现图片隐写

实现图片隐写的算法有很多,我们这里介绍的是最低有效位(LSB)算法,使用过Canvas的朋友都应该知道每一个像素点是由RGBA四个通道组成的,每个通道的颜色值各占8位,LSB就是修改每个颜色值的最低位,而这些修改人眼一般是无法分辨出来的,从而达到隐藏信息的目的。

比如我们需要将“A”隐藏到图片中,我们先把“A”转换成二进制即01000001,如果我们选用一位低位,则需要2个像素点即8个颜色值,然后将这些颜色值的最低位依次修改为A的二进制表示的每一位。

三、图片隐写代码实现

function doHideImage(mainImageData, hideImageData, threshold = 2) {
    const mainImageLength = mainImageData.data.length;
    const hideImageLength = hideImageData.data.length;
    if (hideImageLength * 8 > mainImageLength * threshold) {
        return console.log('主图过小不足以隐藏目标图片');
    }
    let tempArr = [];
    let index = 0;
    for (let i=0; i<hideImageData.data.length; i+=4) {
        const hr = hideImageData.data[i];
        const hg = hideImageData.data[i + 1];
        const hb = hideImageData.data[i + 2];
        const ha = hideImageData.data[i + 3];
        const bins = [toBinary(hr), toBinary(hg), toBinary(hb), toBinary(ha)].join('').split('');
        const countPerGroup = 4 * threshold;
        tempArr = tempArr.concat(bins);
        const count = Math.floor(tempArr.length / countPerGroup);
        const arrForGroup = tempArr.splice(0, count * countPerGroup);
        const bins_2 = arrChange(arrForGroup, countPerGroup);
        bins_2.forEach(arr => {
            const mr = mainImageData.data[index];
            const mg = mainImageData.data[index + 1];
            const mb = mainImageData.data[index + 2];
            const ma = mainImageData.data[index + 3];
            const [r, g, b, a] = hideDataInPixel(arr, [mr, mg, mb, ma], threshold);
            mainImageData.data[index] = r;
            mainImageData.data[index + 1] = g;
            mainImageData.data[index + 2] = b;
            mainImageData.data[index + 3] = a;
            index += 4;
        });
    }
}

其中,mainImageData是主图的ImageData数据,hideImageData是待隐藏图片的ImageData数据,threshold是最低位的个数,需要注意的是最低位的个数越大,图片失真越厉害,建议设置3以内,另外需要提前判断主图是不是足以存下需要隐藏的图片。

四、解析处理后的图片,找出隐藏的小姐姐

这一步主要是将每一个像素点的每一个8位的低位按照我们设置的低位个数threshold依次取出来,每8位对应一个像素值,然后依次还原,代码如下:

function parseHideImage(imageData, width, height, threshold = 2) {
    const count = Math.floor(width * height * 32 / threshold);
    const retImageData  = createImageData(width, height);
    let index = 0;
    let tmpStr = '';
    for (let i = 0; i <= count - 4; i += 4) {
        const r = imageData.data[i];
        const g = imageData.data[i + 1];
        const b = imageData.data[i + 2];
        const a = imageData.data[i + 3];
        const binStr = [toBinary(r), toBinary(g), toBinary(b), toBinary(a)].map(str => {
            return str.slice(8 - threshold, 8);
        }).join('');
        tmpStr += binStr;
        const numCount = Math.floor(tmpStr.length / 8);
        for (let i=0; i<numCount; i++) {
            const binary = tmpStr.slice(0, 8);
            tmpStr = tmpStr.slice(8);
            retImageData.data.set([parseInt(binary, 2)], index);
            index ++;
        }
    }
    return retImageData;
}

提取隐藏的图片,除了需要输入图片以外,还需要输入隐藏进去的图片宽和高以及生成图片时选择的低位个数即threshold才能正常提取出图片,该方法在生成图片后直接重解析能完美解析出隐藏的图片,不会有任何像素缺失,但是如果生成的图片重新保存过,再解析会有少量像素异常,这个目前不知道为什么,有知道的朋友还望告诉我一下。

五、隐写术有什么作用

1、除了可以隐藏图片,我们还可以将文字无损隐藏进入图片中,达到隐藏数据传输的目的。

2、可以做版权保护,如果有人盗了我们的图,我们可以通过图片中隐藏的信息维护我们的权益。

六、后记

不管什么技术,用在正确的地方才能体现它的价值,请不要将其用于非法用途。

在线demo:https://demo.deanhan.cn/hideImage/

如需下载本文所涉及的源码及素材包,请在关注本站公众号后回复:hideimage

系列文章导航:

第2节: js图片隐写-图片中还能藏文章???

第3节: js图片隐写-藏在图片中的小视频

第4节: 你不知道的信息隐藏术-零宽字符的应用

第5节: 隐写术应用-从图片还原画板

  • 支付宝二维码 支付宝
  • 微信二维码 微信

本文地址: /js-hide-info-in-image.html

版权声明: 本文为原创文章,版权归 逐梦个人博客 所有,欢迎分享本文,转载请保留出处!

相关文章