将文本嵌入PNG中

6 投票
8 回答
16009 浏览
提问于 2025-04-16 01:50

我在找一个工具,可以让我把json格式的信息嵌入到PNG文件里。

到现在为止还没有找到合适的工具。我是不是得自己写一个?

我特别想用javascript来实现这个功能。具体来说,就是把我从画布上用toDataURL方法提取出来的图片进行处理。

8 个回答

2

这是我在另一个问题中复制的一个回答:

这是我以前为朋友做的一个简单模块(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])

算法

这个模块每个图像像素存储一个字节的数据,具体方法是:使用蓝色通道的3个最低有效位,绿色通道的2个最低有效位,以及红色通道的3个最低有效位。

encode函数:这个函数会把输入的文本文件进行压缩(使用zlib),然后将输入的图像进行调整大小(保持比例),确保图像的像素数量至少和压缩后的字节数一样多。接着,它会保存一个与输入图像同名的PNG图像(所以如果你不修改代码,输入的文件名不要带“.png”后缀哦 :)),这个图像里包含了隐写数据。

decode函数:这个函数会从输入图像中提取之前存储的zlib压缩数据,并将其解压后保存到你提供的文件名下。

我确认这个旧代码仍然可以运行,所以这里有一个包含隐写数据的示例图像:

包含隐写数据

你会注意到,添加的噪音几乎是看不见的。

2

我对Python完全不熟悉,不过如果你能使用一些流行的图像处理库,那是可以做到的。

你可以在这里查看关于ImageMagick和Python的解决方案。


编辑

你可能还想看看这篇博客文章,里面有关于隐写术(在图像中隐藏信息)和ImageMagick库的相关信息。虽然这里用的是C++,但我相信你可以找到方法把基本的过程用Python实现。

6

如果你想把文字嵌入到图片里,可以看看这个链接,它是来自PNG的规范。这个方法看起来有点复杂。

相对简单一点的方式是使用隐写术,这个方法看起来更容易一些。

不过,可能更适合你需求的是创建一个javascript对象,这个对象里包含了图片数据和JSON数据,然后在需要的地方直接传递这个对象就可以了。

撰写回答