将字符串编码为图片会导致压缩。

7
我正在开发一个程序,它将接受一个字符串,将字符串中的每个字符转换为颜色,然后从左到右、从上到下地在图像上绘制这些颜色。使用同一程序,可以解码图像以获取原始消息。例如,这是作为图像编码的 clojure.core

Clojure.core encoded as an image

我写这个只是作为一个玩具,但我注意到它生成的图像具有一个有趣的特性:它们比原始文本消息要小。对于 clojure.core,文本大小为259kb,但作为图像(如上所示),大小仅为88.9kb(两个值都是“磁盘上的大小”)。为确保数据未丢失,我解码了图像,并得到了原始消息。
这怎么可能呢?我认为图像(png格式)会有头文件和其他额外信息,会导致大小膨胀。
整个 clojure.core 包含265486个字符(根据Notepad++),这意味着每个字符基本上占用一个字节。
从使用 BufferedImage 类(Java)的经验来看,颜色似乎存储为4字节整数,因此每个像素需要 ~4倍的内存?
以下是它的编码方式:
  1. 弹出字符串的第一个字符

  2. 通过获取其ASCII值,将其乘以一个大数(以更好地覆盖可能的颜色范围),然后将该数字转换为3位、256进制数字([123 100 200])将其转换成颜色。

  3. 每个数字都被视为红、绿和蓝通道,并传递给 BufferedImagesetRGB 方法。

  4. 位置指示器向前移动,弹出下一个字符,然后重复该过程,直到整个消息被编码。

目前算法有点复杂。@Thumbnail在Code Review中提出了一种更好的方法,但我还没有实现它。由于结果是相同的,这对问题不应造成影响。

2
尽管答案有些显而易见,但我仍然很喜欢阅读你的发现。像这样的东西总是很有趣。 - Luke Joshua Park
1个回答

7

噢,回想起来那很明显。谢谢。 - Carcigenicate
值得一提的是,PNG使用Zlib/Deflate压缩算法(而且直接在文本文件上使用Deflate可能会获得更好的结果)。 - Harald K
@haraldK 那也是我的期望。除了deflate外,png还进行了预处理,有助于“真实”图像的压缩(在这些图像中,一个像素在统计上看起来非常像其相邻的像素)。您可以通过选择彼此相近的颜色来利用它(从而获得更好的png压缩)。此外,可能可以通过将多个字符编码到一个像素中(Truecolor + alpha png图像每像素使用64位)来制作较小尺寸的图像-尽管这样做很可能不会压缩得很好。 - thebjorn

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