レプトン圧縮を阻止する


17

Dropboxは最近、レプトンGitHub)をリリースしました。これは、往復でJPEG画像を無損失で圧縮し、平均22%を節約する方法です。

そのための鳩の巣原理、任意の一般的な圧縮アルゴリズムをすることはできません保証(小さいファイルをもたらすために、一般的には、特定の形式に制約の入力には適用されないため)。LeptonはJPEGに関する一般的な特性を利用します。JPEGは、破壊された場合、ソースよりも大きいファイルを生成するためにそれをピジョンホールする可能性があります。

必要条件

以下を生成するプログラムを作成します。

  • 有効なJPEG / JFIF画像、
  • 0.5 MB〜1 MBのサイズで、
  • 256×256 px以上
  • 4096×4096 px以下
  • レプトンが認識できる(.lep画像に正常に「圧縮」できる)
  • (入力として)同一に 解凍し.jpgます。
  • APPxCOMおよびその他のメタデータ、非グラフィックマーカーセクションはJPEGで制限されています(ランダムな量の任意のバイトを画像に注入して、1:1圧縮に漸近的に近づくことは不十分です)。
    • APP0JFIFマーカーは(正確に16バイトでなければならない)、許可されているが、サムネイルが許可されません
    • tl; dr意図的にメタデータをEXIFセグメントに押し込んでおらず、選択した言語ライブラリが画像に配置したいサムネイルを無効にしている場合、それは問題ありません。

コードと画像を投稿してください。

変換すると基準を満たすJPEG が生成されるLeptonイメージを生成するプログラムを作成する場合は、問題ありません。任意の多くのJPEG→Lepton→JPEG→...サイクルにわたって同一のままでなければなりません。

得点

ソースJPEG画像で割ったレプトン画像のバイトサイズ。高い(レプトン圧縮が悪い)ほど優れています。デフォルトのフラグとスイッチでレプトンを実行します。


レプトンを取得する

レプトンを構築する5秒間のクラッシュコース:

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
@feersum JPEGコンプレッサーへの一様にランダムな入力は、一様にランダムな出力にはなりません。その出力はレプトンの動作対象です。JPEGコンプレッサーが一様にランダムな出力を生成する入力を思い付くことができれば、それはおそらくここや他の場所で役立つでしょう。
スパー

回答:


4

Python 3 + mozjpeg + / dev / urandom、720×720:平均 スコア102%

mozjpegパッケージによって異なりますが、コードはにインストールされていると想定してい/usr/local/opt/mozjpegます。(OS Xではインストールは簡単で、実行するだけですbrew install mozjpeg

また、/dev/urandom特別なファイルに依存し、ランダムデータの生成に使用されます。

このコードは、ランダムデータをmozjpegコンプレッサーに単純に供給し(cjpegが理解し、非常に単純なヘッダーを持っているため、TGA形式で)、最適化された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%)があります。レプトンは、その情報を使用してスペースを節約すると言います。
  • 完全にデフォルトの量子化テーブルとハフマンテーブル(ライブラリが使用することを決定したもの)。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.