将文本嵌入PNG图片中

6

我正在寻找一种工具,可以让我在PNG文件中嵌入JSON格式的信息。

目前为止还很安静。我必须自己写吗?

我对使用JavaScript实现特别感兴趣。我用 toDataURL 方法从画布中提取图像。


你想在图像上面绘制文字,还是做一些隐写术? - Wayne Werner
你能否在图片上覆盖一些东西吗?(^后2秒) - Brandon Frohbieter
我刚想在发布我的答案后问这个问题...是隐写术还是覆盖? - erik
2
哦,看来我没有解释清楚。我的意思是想将一些JSON编码的数据嵌入到图像中,这样我就不需要单独提供它到我的JavaScript游戏中了。 - Cheery
所以你基本上想在一张图片中隐藏信息? - erik
显示剩余2条评论
8个回答

6
如果您想嵌入文本,可以查看特别来自此处的内容,这是来自PNG规范。它似乎有点复杂。
“简单”的隐写术方法看起来更加简单。
对于您的目的,实际上可能更适合创建一个包含图像数据和JSON数据的javascript对象,然后在需要时将该对象传递给任何地方。

2
我完全不熟悉Python,但是如果你可以访问任何主要的图像处理库,这是可能的。
请点击这里查看ImageMagick<->Python的解决方案。

编辑

您可能希望查看这个博客帖子,了解有关隐写术(在图像中隐藏信息)和ImageMagick库的一个分支的信息。它在这里使用C++,但我相信您可以想出一种将基本过程合并到Python中的方法。


2
这里的答案严重地过度工程化了问题。很抱歉你等了11年才得到答案。这个功能是标准的,是PNG规范的一部分。今天有很多应用程序都在使用它。
您可以将JSON或任何其他数据直接嵌入到PNG中。使用npm“png-chunk-text”(https://www.npmjs.com/package/png-chunk-text)只需要3行JavaScript代码即可完成此操作。
现在,您可以以闪电般的速度读取和写入PNG内的JSON,并且开发过程仅需30秒,而且该过程是标准的,即其他工具也可以读取它。

1

复制我的另一个答案:

这是我曾经为朋友做过的一个旧的不太花哨的模块( Python 2.x 代码) :

代码

from __future__ import division

import math, os, array, random
import itertools as it
import Image as I
import sys

def encode(txtfn, imgfn):
    with open(txtfn, "rb") as ifp:
        txtdata= ifp.read()
    txtdata= txtdata.encode('zip')

    img= I.open(imgfn).convert("RGB")
    pixelcount= img.size[0]*img.size[1]
##  sys.stderr.write("image %dx%d\n" % img.size)

    factor= len(txtdata) / pixelcount
    width= int(math.ceil(img.size[0]*factor**.5))
    height= int(math.ceil(img.size[1]*factor**.5))

    pixelcount= width * height
    if pixelcount < len(txtdata): # just a sanity check
        sys.stderr.write("phase 2, %d bytes in %d pixels?\n" % (len(txtdata), pixelcount))
        sys.exit(1)
##  sys.stderr.write("%d bytes in %d pixels (%dx%d)\n" % (len(txtdata), pixelcount, width, height))
    img= img.resize( (width, height), I.ANTIALIAS)

    txtarr= array.array('B')
    txtarr.fromstring(txtdata)
    txtarr.extend(random.randrange(256) for x in xrange(len(txtdata) - pixelcount))

    newimg= img.copy()
    newimg.putdata([
        (
            r & 0xf8 |(c & 0xe0)>>5,
            g & 0xfc |(c & 0x18)>>3,
            b & 0xf8 |(c & 0x07),
        )
        for (r, g, b), c in it.izip(img.getdata(), txtarr)])
    newimg.save(os.path.splitext(imgfn)[0]+'.png', optimize=1, compression=9)

def decode(imgfn, txtfn):
    img= I.open(imgfn)
    with open(txtfn, 'wb') as ofp:
        arrdata= array.array('B',
            ((r & 0x7) << 5 | (g & 0x3) << 3 | (b & 0x7)
            for r, g, b in img.getdata())).tostring()
        findata= arrdata.decode('zip')
        ofp.write(findata)

if __name__ == "__main__":
    if sys.argv[1] == 'e':
        encode(sys.argv[2], sys.argv[3])
    elif sys.argv[1] == 'd':
        decode(sys.argv[2], sys.argv[3])

算法

使用以下方式存储每个图像像素的1个字节数据:蓝色频带的3个最低有效位、绿色频带的2个LSB和红色频带的3个LSB。

编码函数:将输入文本文件使用zlib进行压缩,然后调整输入图像的大小(保持比例),以确保至少有与压缩字节数相同数量的像素。保存一个PNG图像,其名称与输入图像相同(因此如果保留代码,请不要使用“.png”文件名作为输入 :)),其中包含隐写数据。

解码函数:从输入图像中提取之前存储的zlib压缩数据,并将其未压缩保存在提供的文件名下。

我验证了旧代码仍然可以运行,因此这里有一个包含隐写数据的示例图像:

contains steganographic data

你会注意到添加的噪声几乎不可见。


1

1
您可以使用最近发布的JavaScript库steganography.js。请查看展示和基本用法文档。
该库利用HTML canvas并将信息嵌入到图像的alpha通道中。基本上,您只需要使用steg.encode(message, image),将JSON数据(作为字符串)作为消息传递,并将图像作为dataURL传递。要从图像中读取此信息,请使用steg.decode(image),再次将图像作为dataURL传递。

读取信息后,您将获得JSON数据作为字符串,因此您需要将其解析为JavaScript对象。所以除了从/到字符串的解析之外,我希望它符合您的要求。


0

为什么不直接使用这个工具呢?

http://www.jsclasses.org/package/324-JavaScript-Embed-encoded-text-in-images-using-steganography.html

还有在 GitHub 上:

https://github.com/blauharley/LoremImageCryptonator

这是一个普通的对象,可用于将文本嵌入到每个颜色通道(红色、绿色等)中。

当将文本嵌入到 alpha 通道时,噪声不应该像在其他颜色通道上嵌入文本那样多,因此在将文本插入图像之前和之后,您不应该看到任何区别。


0

有人已经尝试在PNG图像中嵌入类似马里奥平台游戏。使用getImageData是读取数据的关键;该方法返回的对象提供了一个一维数组,其中包含每个像素的单独RGBA值。

请注意,这并不是将数据“隐藏”在用户看到的区域内,但您可能可以使用类似CSS精灵的技术(或使用多个画布“裁剪”图像)来仅显示您想要的组合图像的部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接