阻碍勒普顿压缩


17

Dropbox最近发布了LeptonGitHub),该方法可无损地压缩JPEG图像往返,平均节省22%。

由于信鸽原理,不能保证任何常规的压缩算法都会导致文件更小(一般是因为它不适用于限制为特定格式的输入)。Lepton充分利用了JPEG的共同特征,如果这些特征被颠覆了,可能会导致其产生比源更大的文件。

要求

编写一个生成以下内容的程序:

  • 有效的JPEG / JFIF图像,
  • 大小介于0.5 MB和1 MB之间,
  • 不小于256×256 px,
  • 不大于4096×4096像素,
  • Lepton可以识别(它可以成功地“压缩”为.lep图像),并且
  • 解压缩为相同的 .jpg(作为输入)。
  • APPxCOM以及其他元数据,非图形标记部分在JPEG中受到限制(向图像中注入任意数量的随机字节以渐近地接近1:1压缩是la脚的。)
    • 允许使用APP0JFIF标记,但不允许使用缩略图(应为16个字节)
    • tl; dr如果您不是故意将元数据推入EXIF段中,并且禁用了您希望选择的语言库想要放入图像的任何缩略图,那应该没问题。

发布代码和图像。

如果要编写一个生成Lepton图像的程序,该程序在转换时会产生符合条件的JPEG,那就很好。在任意多个JPEG→轻子→JPEG→...循环中,它必须保持相同。

计分

Lepton图像的字节大小除以源JPEG图像。更高(更轻的Lepton压缩)更好。使用默认标志和开关运行Lepton。


到达莱普顿

5秒钟的速成课程来构建Lepton:

git clone https://github.com/dropbox/lepton.git
cd lepton
./autogen.sh && ./configure && make

# fish shell: ./autogen.sh ;and ./configure ;and make

./lepton --help应该告诉你的事情。


我认为这可能会重新适应代码高尔夫挑战,其中您编写的代码生成的图像压缩至少会失败一些常数。实际上,仅对代码大小设置一个上限就足够了,该上限比对jpeg进行硬编码的大小小得多,但对于合理的程序来说足够大了。
xnor

3
有没有理由期望均匀随机像素不是最佳答案?
feersum

@feersum您的意思就像我的例子一样?
尼克T

1
另外,由于JPEG是有损格式,因此有很多很多方法(例如“质量”)来压缩给定图像。每个JPEG文件都包含几个表,这些表指示如何解码其余图像,这些表基本上可以是任何表。如果将BMP图像保存在其他程序中,则可能完全相同。如果将JPG保存在其他程序中,除非它们使用相同的后端库,否则可能不会。
尼克T

2
JPEG压缩器的@feersum均匀随机输入不会导致均匀随机输出,而该输出正是lepton所使用的。如果您能提供一个使JPEG压缩器产生均匀随机输出的输入,那么在这里和其他地方可能会很有用。
Sparr

Answers:


4

Python 3 + mozjpeg + / dev / urandom,720×720:平均 得分102%

取决于mozjpeg软件包,代码假定它已安装到中/usr/local/opt/mozjpeg。(在OS X上,安装非常简单,只需运行即可brew install mozjpeg

此外,它取决于/dev/urandom特殊文件,用于生成随机数据。

该代码仅将随机数据馈入mozjpeg压缩器(采用TGA格式,因为cjpeg可以理解并且它具有非常简单的标头),并允许它创建优化的jpeg文件。将质量设置为最高是因为它使DCT系数的可压缩性最低,并且使用哪种算法压缩不可压缩的数据都无关紧要。

我检查了jpeg-> lepton-> jpeg循环是否无损-是的。

import subprocess
from subprocess import PIPE

c_mozjpeg_path = '/usr/local/opt/mozjpeg/bin/cjpeg'
cjpeg_params = '-quality 100 -dc-scan-opt 2 -dct float -targa'
image_size = 720


def write_random_tga_image(w, h, of, rf):
    def wb(value, size):
        of.write(int.to_bytes(value, size, 'little'))

    wb(0, 2)
    wb(3, 1)
    wb(0, 9)
    wb(w, 2)
    wb(h, 2)
    wb(8, 1)
    wb(0, 1)

    data_size = w * h
    while data_size > 0:
        data_size -= of.write(rf.read(data_size))


def main():
    with open('/dev/urandom', 'rb') as rf:
        with open('oops.jpg', 'wb') as f:
            p = subprocess.Popen((c_mozjpeg_path,) + tuple(cjpeg_params.split(' ')), stdin=PIPE, stdout=f)
            write_random_tga_image(image_size, image_size, p.stdin, rf)
            p.communicate()


if __name__ == '__main__':
    main()

显然,代码没有打高尔夫。

示例图片:

有趣的事实:即使JPEG使用有损压缩,生成的JPEG文件也比源未压缩的TGA图像大。

有趣的事实2:Imgur(SO的默认图像托管)在此文件上做得很糟糕-由于某种原因,即使它小于1MB,它也会将其重新压缩以降低质量。因此,我使用Github上传示例图片。

有趣的事实3:总的来说,mozjpeg在与现有JPEG解码器保持兼容的同时,确实可以实现更好的JPEG压缩。而且,它也具有无损优化JPEG文件的工具jpegtran


我可以使用跨平台的RNG(例如SystemRandom类),但是我太懒了。这是微不足道的,它应该给出相似的结果。
显示名称

1

天真噪声,1024×1024:得分85.55%

Python中的一个兼容示例,可以使工作顺利进行。没有以任何方式进行优化;可能的缺点:

  • 不知道默认的质量设置是什么。
  • 每个8x8区块实际上具有与其相邻区块相同的平均值(〜50%):Lepton说,他们使用该信息来节省空间。
  • 完全默认的量化表和霍夫曼表(无论库决定使用什么)。

import numpy as np
from PIL import Image

np.random.seed(0) # make sure it's repeatable.

size = 1024

imgr = np.random.randint(0, 0xFF, (size, size, 3)).astype('uint8')
pimg = Image.fromarray(imgr)
pimg.save('noise.jpg')

噪声

然后用一些bash来做这件事:

./lepton noise.jpg noise.lep 2>\dev\null # vomits out a lot of technobabble
./lepton noise.lep noise-out.jpg 2>\dev\null

diff -qs noise.jpg noise-out.jpg

SIZE1=$(stat -f "%z" noise.jpg) # http://superuser.com/a/570920/18931
SIZE2=$(stat -f "%z" noise.lep)
RATIO=$(bc <<< "scale=4; $SIZE2/$SIZE1")
echo "$SIZE2/$SIZE1 = $RATIO"

# Files noise.jpg and noise-out.jpg are identical
# 538817/629769 = .8555
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.