Thwart nén Lepton


17

Dropbox vừa cho ra mắt Lepton ( GitHub ), một phương pháp mà losslessly nén ảnh JPEG khứ hồi, tiết kiệm trung bình 22%.

Do nguyên tắc pigeonhole , bất kỳ thuật toán nén chung nào cũng không thể được đảm bảo dẫn đến một tệp nhỏ hơn ( chung vì nó không áp dụng cho các đầu vào bị ràng buộc theo một định dạng cụ thể). Lepton khai thác các đặc điểm phổ biến về JPEG, nếu bị lật đổ, có thể điều chỉnh nó để tạo ra một tệp lớn hơn nguồn.

Yêu cầu

Viết chương trình tạo:

  • Hình ảnh JPEG / JFIF hợp lệ,
  • với kích thước từ 0,5 MB đến 1 MB,
  • không nhỏ hơn 256 × 256 px,
  • không lớn hơn 4096 × 4096 px,
  • Lepton có thể nhận ra (nó có thể "nén" thành công .lephình ảnh) và
  • giải nén thành một bản giống hệt .jpg (làm đầu vào).
  • APPx, COMvà các siêu dữ liệu khác, các phần đánh dấu phi đồ họa bị hạn chế trong JPEG (việc đưa một lượng byte ngẫu nhiên tùy ý vào hình ảnh để tiếp cận nén 1: 1 không theo triệu chứng là khập khiễng.)
    • một APP0điểm đánh dấu JFIF được cho phép nhưng không cho phép hình thu nhỏ (phải chính xác là 16 byte)
    • tl; dr Nếu bạn không cố tình đẩy siêu dữ liệu vào một phân đoạn EXIF ​​và bạn vô hiệu hóa bất kỳ loại hình thu nhỏ nào mà thư viện ngôn ngữ bạn muốn đưa vào hình ảnh, điều đó sẽ ổn.

Gửi mã và hình ảnh.

Nếu bạn muốn viết một chương trình tạo ra hình ảnh Lepton mà khi chuyển đổi sẽ mang lại một JPEG đáp ứng các tiêu chí, điều đó tốt. Nó phải giống hệt nhau qua nhiều chu kỳ JPEG → Lepton → JPEG → ....

Chấm điểm

Kích thước byte của hình ảnh Lepton chia cho hình ảnh JPEG nguồn. Cao hơn (nén Lepton tệ hơn) là tốt hơn. Chạy Lepton với cờ và công tắc mặc định.


Bắt Lepton

Một khóa học kéo dài 5 giây để xây dựng Lepton:

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

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

Sau đó ./lepton --helpnên nói với bạn những điều.


Tôi nghĩ rằng điều này có thể được điều chỉnh lại cho một thử thách golf mã trong đó bạn viết mã tạo ra một hình ảnh không nén được ít nhất là một số hằng số. Trên thực tế, có thể chỉ cần đặt giới hạn trên cho kích thước mã nhỏ hơn nhiều so với kích thước để mã hóa jpeg, nhưng đủ lớn cho một chương trình hợp lý.
xnor

3
Có bất kỳ lý do để mong đợi rằng các pixel ngẫu nhiên thống nhất không phải là câu trả lời tốt nhất?
frageum

@feersum bạn có nghĩa là giống như ví dụ của tôi?
Nick T

1
Ngoài ra, vì JPEG là định dạng mất dữ liệu, có rất nhiều cách (ví dụ: "chất lượng" trong số những thứ khác) để nén một hình ảnh nhất định. Mỗi tệp JPEG bao gồm một vài bảng chỉ ra cách phần còn lại của hình ảnh được giải mã và các bảng đó về cơ bản có thể là bất cứ thứ gì. Nếu bạn lưu hình ảnh BMP trong các chương trình khác nhau, nó có thể sẽ giống hệt nhau. Nếu bạn lưu JPG trong các chương trình khác nhau, trừ khi chúng sử dụng cùng một thư viện back-end, có thể là không.
Nick T

2
@feersum đầu vào ngẫu nhiên đồng đều vào máy nén JPEG không dẫn đến đầu ra ngẫu nhiên đồng đều và đầu ra đó là những gì lepton hoạt động. Nếu bạn có thể đưa ra một đầu vào khiến máy nén JPEG tạo ra đầu ra ngẫu nhiên đồng đều, điều đó có thể hữu ích ở đây và ở nơi khác.
Sparr

Câu trả lời:


4

Python 3 + mozjpeg + / dev / urandom, 720 × 720: avg. đạt 102%

Tùy thuộc vào mozjpeggói, mã giả định nó được cài đặt vào /usr/local/opt/mozjpeg. (trên OS X, cài đặt không quan trọng, chỉ cần chạy brew install mozjpeg)

Ngoài ra, nó phụ thuộc vào /dev/urandomtệp đặc biệt, nó được sử dụng để tạo dữ liệu ngẫu nhiên.

Mã chỉ đơn giản cung cấp dữ liệu ngẫu nhiên cho mozjpegmáy nén (ở định dạng TGA, vì cjpeg hiểu nó và nó có tiêu đề rất đơn giản) và cho phép nó tạo một tệp jpeg được tối ưu hóa. Chất lượng được đặt ở mức tối đa vì nó làm cho các hệ số DCT trở nên ít nén nhất và không quan trọng thuật toán nào được sử dụng để nén dữ liệu không nén được.

Tôi đã kiểm tra rằng chu trình jpeg-> lepton-> jpeg là lossless - đó là sự thật.

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

Mã không phải là golf, rõ ràng.

Hình ảnh ví dụ:

Sự thật thú vị: tệp JPEG được tạo lớn hơn hình ảnh TGA không nén nguồn, mặc dù JPEG sử dụng nén mất dữ liệu.

Sự thật thú vị 2: Imgur (lưu trữ hình ảnh mặc định cho SO) thực hiện công việc rất tệ ở tệp này - vì một số lý do, nó giải nén nó thành chất lượng thấp hơn, mặc dù chỉ dưới 1 MB. Vì vậy, tôi đã sử dụng Github để tải lên hình ảnh ví dụ.

Sự thật thú vị 3: Nói chung, mozjpeg thực sự nén JPEG tốt hơn trong khi vẫn tương thích với các bộ giải mã JPEG hiện có. Và nó cũng có công cụ để tối ưu hóa các tệp JPEG một cách dễ dàng - jpegtran.


Tôi có thể sử dụng RNG đa nền tảng (ví dụ như lớp SystemRandom) nhưng tôi quá lười biếng. Đó là chuyện nhỏ và nó sẽ cho kết quả tương tự.
Sange Borsch

1

Tiếng ồn ngây thơ, 1024 × 1024: điểm 85,55%

Một ví dụ tuân thủ trong Python để có được quả bóng lăn. Không được tối ưu hóa theo bất kỳ cách nào; thiếu sót có thể xảy ra:

  • Không biết thiết lập chất lượng mặc định là gì.
  • Mỗi khối 8x8 thực tế có cùng giá trị trung bình chính xác (~ 50%) với khối liền kề với nó: Lepton nói rằng họ sử dụng thông tin đó để tiết kiệm không gian.
  • Hoàn toàn mặc định lượng tử và bảng Huffman (bất cứ điều gì thư viện quyết định sử dụng).

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

tiếng ồn

Sau đó, một số bash để làm điều:

./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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.