Menggagalkan kompresi Lepton

17

Dropbox baru-baru ini merilis Lepton ( GitHub ), sebuah metode yang tanpa kompres memadatkan gambar perjalanan JPEG, menghemat rata-rata 22%.

Karena prinsip pigeonhole , algoritma kompresi umum apa pun tidak dapat dijamin menghasilkan file yang lebih kecil ( umum karena tidak berlaku untuk input yang dibatasi ke format tertentu). Lepton mengeksploitasi karakteristik umum tentang JPEG, yang jika ditumbangkan, mungkin akan membuatnya jadi file yang lebih besar dari sumbernya.

Persyaratan

Tulis program yang menghasilkan:

  • Gambar JPEG / JFIF yang valid,
  • dengan ukuran antara 0,5 MB dan 1 MB,
  • tidak lebih kecil dari 256 × 256 px,
  • tidak lebih besar dari 4096 × 4096 px,
  • dikenali oleh Lepton (berhasil dapat "kompres" ke .lepgambar), dan
  • mendekompresi menjadi identik .jpg (sebagai input).
  • APPx,, COMdan metadata lainnya, bagian marker non-grafis dibatasi dalam JPEG (menyuntikkan jumlah acak byte ke dalam gambar untuk secara asimptotik mendekati kompresi 1: 1 lumpuh.)
    • sebuah APP0JFIF penanda diperbolehkan tetapi tidak ada thumbnail diperbolehkan (harus tepat 16 bytes)
    • tl; dr Jika Anda tidak sengaja mendorong metadata ke dalam segmen EXIF ​​dan Anda menonaktifkan segala jenis thumbnail yang ingin dimasukkan ke dalam pustaka bahasa Anda ke dalam gambar, itu tidak masalah.

Posting kode dan gambar.

Jika Anda ingin menulis sebuah program yang menghasilkan gambar Lepton yang ketika dikonversi menghasilkan JPEG yang memenuhi kriteria, itu bagus. Itu harus tetap identik di banyak siklus JPEG → Lepton → JPEG → sewenang-wenang.

Mencetak gol

Ukuran byte dari gambar Lepton dibagi dengan gambar JPEG sumber. Lebih tinggi (kompresi Lepton yang lebih buruk) lebih baik. Jalankan Lepton dengan flag dan sakelar default.


Mendapatkan Lepton

Kursus kilat 5 detik untuk membangun Lepton:

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

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

Maka ./lepton --helpharus memberi tahu Anda hal-hal.

Nick T
sumber
Saya pikir ini bisa retooled ke tantangan golf kode di mana Anda menulis kode yang menghasilkan gambar yang gagal kompresi oleh setidaknya beberapa konstanta. Sebenarnya, itu mungkin cukup untuk hanya menempatkan batas atas pada ukuran kode yang jauh lebih kecil dari ukuran untuk hardcode jpeg, tetapi cukup besar untuk program yang masuk akal.
xnor
3
Apakah ada alasan untuk berharap bahwa piksel acak yang seragam bukanlah jawaban terbaik?
feersum
@feersum yang Anda maksud persis seperti contoh saya?
Nick T
1
Juga, karena JPEG adalah format lossy, ada banyak, banyak cara (misalnya "kualitas" di antara hal-hal lain) untuk mengompres gambar yang diberikan. Setiap file JPEG menyertakan beberapa tabel yang menentukan bagaimana sisa gambar diterjemahkan, dan tabel tersebut pada dasarnya bisa apa saja. Jika Anda menyimpan gambar BMP di berbagai program, itu mungkin akan identik. Jika Anda menyimpan JPG di program yang berbeda, kecuali mereka menggunakan pustaka back-end yang sama, mungkin tidak.
Nick T
2
@feersum input acak seragam ke kompresor JPEG tidak menghasilkan output acak seragam, dan output itulah yang bekerja pada lepton. Jika Anda dapat menghasilkan input yang menyebabkan kompresor JPEG menghasilkan output acak yang seragam, yang mungkin berguna di sini dan di tempat lain.
Sparr

Jawaban:

4

Python 3 + mozjpeg + / dev / urandom, 720 × 720: rata-rata skor 102%

Tergantung pada mozjpegpaket, kode menganggap itu diinstal ke dalam /usr/local/opt/mozjpeg. (pada OS X itu sepele untuk menginstal, jalankan saja brew install mozjpeg)

Juga tergantung pada /dev/urandomfile khusus, ini digunakan untuk menghasilkan data acak.

Kode ini hanya mozjpegmemasukkan data acak ke kompresor (dalam format TGA, karena cjpeg memahaminya dan memiliki header yang sangat sederhana), dan memungkinkannya membuat file jpeg yang dioptimalkan. Kualitas diatur ke maksimum karena membuat koefisien DCT yang paling tidak dapat dikompres, dan tidak masalah apa algoritma yang digunakan untuk kompres data yang tidak dapat dikompres.

Saya memeriksa bahwa siklus jpeg-> lepton-> jpeg adalah lossless - itu benar.

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()

Kode tidak golf, jelas.

Contoh gambar:

Fakta menyenangkan: file JPEG yang dihasilkan lebih besar dari sumber gambar TGA yang tidak terkompresi, meskipun JPEG menggunakan kompresi lossy.

Fakta menyenangkan 2: Imgur (hosting gambar default untuk SO) melakukan pekerjaan yang sangat buruk pada file ini - untuk beberapa alasan ia mengompresnya kembali ke kualitas yang lebih rendah, meskipun kurang dari 1MB. Jadi saya menggunakan Github untuk mengunggah contoh gambar.

Fakta menyenangkan 3: Secara umum, mozjpeg memang melakukan kompresi JPEG yang lebih baik sambil tetap kompatibel dengan decoder JPEG yang ada. Dan itu juga memiliki alat untuk mengoptimalkan file JPEG, juga - jpegtran.

Nama tampilan
sumber
Saya bisa menggunakan RNG lintas-platform (kelas SystemRandom misalnya) tapi saya terlalu malas. Itu sepele dan harus memberikan hasil yang serupa.
Nama Tampilan
1

Noise Naif, 1024 × 1024: skor 85,55%

Contoh yang sesuai dalam Python untuk mendapatkan bola bergulir. Tidak dioptimalkan dengan cara apa pun; kemungkinan kekurangan:

  • Tidak tahu apa pengaturan kualitas default.
  • Setiap blok 8x8 praktis memiliki nilai rata-rata yang sama persis (~ 50%) dengan yang berdekatan: Lepton mengatakan bahwa mereka menggunakan informasi itu untuk menghemat ruang.
  • Tabel kuantisasi dan Huffman yang benar-benar default (apa pun perpustakaan memutuskan untuk menggunakan).

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')

kebisingan

Kemudian beberapa bash untuk melakukan hal itu:

./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
Nick T
sumber