假设我有一个图像文件,我知道它最终将是 1024 x 1024,并且我想让该文件尽可能大(磁盘空间方面)。假设一个 72 dpi 分辨率的 PNG 文件,我会用什么填充这个文件以使其信息尽可能密集?某些颜色的存储成本是否比其他颜色高?模式?阿尔法水平?我正在专门考虑一个 PNG 文件,但也有兴趣了解 GIF 和 JPG 文件。
2 回答
一般来说,PNG 采用“无损”压缩,通常通过在文件中查找重复的 RGB 值和/或重复的图块或扫描线来工作。你可以在这里阅读更多:
http://www.libpng.org/pub/png/book/chapter09.html
一般来说,要击败几乎任何无损压缩器,您所要做的就是用随机 RGB 噪声填充图像,这样像素的 RGB 值会在每个扫描线和每个相邻像素中出现非常不同的结果——也就是说,产生尽可能少的重复像素颜色值序列。知道您将使用一个总共有 1048576 像素的文件,刚刚超过一百万,而 24 位 PNG 为您提供了 16777216 种颜色可供选择(24 位颜色,每个通道 8 位),您可以尝试采样采样时,每 16 种颜色会稍微上下调整它的值,然后将其写入图像中。
有关该主题的更多有趣信息,请参阅 概念检查:任何无损数据压缩都可能被“击败”,对吗?
举个简单的例子,让我们生成一个你尺寸的 PNG 并用随机噪声填充它:
require 'rubygems'
require 'chunky_png'
dimension = 1024
png = ChunkyPNG::Image.new(dimension, dimension)
total_colors = 2 ** (8*(3+1)) # 3 + 1 because we have alpha too!
rng = Random.new
(0...dimension).each do | x |
(0...dimension).each do | y |
r = rng.rand(0..total_colors)
png[x, y] = r
end
end
png.save('/tmp/noise.png')
`open /tmp/noise.png`
这在 OSX 上给了我一个 4.2 兆字节的文件。当我运行pngcrush
它进行一些压缩时,我得到一个相同大小的文件。如果您想让现有图像不可压缩,您可以尝试以相同的方式混合噪声。
您想让图像难以压缩,这在信息论中意味着“最大熵”,在我们的例子中意味着:“白噪声”。实际上,这意味着:为每个像素值(每个 RGB 分量)在 0-255 范围内给每个像素一个(统一且独立的)随机值。如果您可以添加 ALPHA 通道,请执行相同操作。(当然,如果您要存储 PNG 文件,则可以使用 16 位深度……但我想那是作弊)。
该文件大约为 1024x1024x3 字节 = 3MB(如果是 RGB,如果使用 RGBA,则为 x4),PNG 将无法压缩它。
GIF 或 JPEG 也是如此(但对于 GIF,您仅限于索引图像,因此大小约为 1MB)。