js图片隐写-图片中还能藏文章???

在上一篇文章《js图片隐写-找出图片中隐藏的漂亮小姐姐》中,我们介绍了如何用最低有效位算法将一张漂亮小姐姐照片藏在另外一张风景照中,本文我们将继续介绍如何利用最低有效位算法将一段文本甚至一篇文章藏在一张图片中。

一、将字符串转换成二进制

我们在隐藏信息的过程中,需要先将信息转换成二进制表示,然后将二进制的每一位依次隐藏到图片像素的最低有效位中,将文本转二进制,以下问题我们需要注意。

1、对于常规的字符、数字,符号都是1字节的,但是汉字至少是2字节的,所以我们需要选用最大字节数2字节即28位。

2、对于文本的结束,我们需要设置一定的标识,这里选用一个使用频率特别低的字符“”来作为文本结束的标记,二进制表示“0101011000000010”。

代码实现如下:

function str2binary(str) {
    const ret = [];
    for (let i=0; i<str.length; i++) {
        const char = str[i];
        const ascii = str.charCodeAt(i);
        const binary = ascii.toString(2).padStart(16, 0);
        ret.push(binary);
    }
    ret.push('嘂'.charCodeAt(0).toString(2).padStart(16, 0));
    return ret.join('').split('');
}

二、将得到的二进制字符串隐藏到图片中

在得到二进制字符串数组之后,我们依次将二进制字符串的每一位存储到像素的最低有效位中,代码如下:

function hideBinaryInPixel(textBinary, pixel, numPerPixel) {
    return pixel.map((data, index) => {
        const hideChar = textBinary.splice(0, numPerPixel).join('');
        if (hideChar) {
            const bData = toBinary(data);
            return parseInt(`${bData.slice(0, 8-hideChar.length)}${hideChar}`, 2);
        }
        return data;
    });
}

function doHideText(mainImageData, text, threshold = 2) {
    isImageReady = false;
    const mainImageLength = mainImageData.data.length;
    const textBinary = str2binary(text);
    if (textBinary.length > mainImageLength * threshold) {
        return alert('主图过小不足以隐藏文本');
    }
    let tempArr = [];
    let index = 0;
    for (let i=0; i<mainImageData.data.length; i+=4) {
        const mr = mainImageData.data[i];
        const mg = mainImageData.data[i + 1];
        const mb = mainImageData.data[i + 2];
        const ma = mainImageData.data[i + 3];
        const [r, g, b, a] = hideBinaryInPixel(textBinary, [mr, mg, mb, ma], threshold);
        mainImageData.data[i] = r;
        mainImageData.data[i + 1] = g;
        mainImageData.data[i + 2] = b;
        mainImageData.data[i + 3] = a;
        if (textBinary.length === 0) {
            break;
        }
    }
    isImageReady = true;
}

三、解析隐藏在图片中的文本

在得到了隐藏了文本的图片后,我们需要将图片做解析获取图片中藏着的文本,解析的过程就是按照上面定的规则遍历每一个像素点还原隐藏的二进制字符串,再将二进制字符串转换成对应的字符,最终得到结果,代码如下:

function parseHideText(imageData, threshold = 2) {
    let text = '';
    let tmpStr = '';
    ret: for (let i = 0; i < imageData.data.length; 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 textByteCount = 16;
        const numCount = Math.floor(tmpStr.length / textByteCount);
        for (let i=0; i<numCount; i++) {
            const binary = tmpStr.slice(0, textByteCount);
            tmpStr = tmpStr.slice(textByteCount);
            let char = String.fromCharCode(parseInt(binary, 2));
            if (/^01010110000000/.test(binary)) {
                break ret;
            }
            text += char;
        }
    }
    return text;
}

需要注意的是,在做解析时,我们需要传入隐藏文本时选择的有效位个数threshold

四、问题思考

1、通过浏览器保存后,像素会有缺失,导致后期解析出来的内容会有少部分乱码。

2、判断文本是否结束不能通过全等来实现,建议使用正则做匹配,因为我们在填入不同的有效位个数时,最后一个像素点不一定是完整填充了有效位。

五、后记

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

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

下一篇文章,我们会继续介绍如何将一个视频隐藏到图片中,敬请期待!

系列文章导航:

第1节: js图片隐写-找出图片中隐藏的漂亮小姐姐

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

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

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

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

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

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

相关文章