Сдержать лептонное сжатие


17

Dropbox недавно выпустил Lepton ( GitHub ), метод, который без потерь сжимает изображения JPEG в обоих направлениях, экономя в среднем 22%.

Из-за принципа «квадратного отверстия» нельзя гарантировать , что любой общий алгоритм сжатия приведет к уменьшению файла ( общий, потому что он не применяется к входным данным, ограниченным определенным форматом). Лептон использует общие характеристики JPEG, которые в случае его искажения могут привести к появлению файла большего размера, чем исходный.

Требования

Напишите программу, которая генерирует:

  • Действительное изображение JPEG / JFIF,
  • размером от 0,5 МБ до 1 МБ,
  • не менее 256 × 256 пикселей,
  • не более 4096 × 4096 пикселей,
  • распознается Лептоном (он может успешно «сжать» .lepизображение) и
  • распаковывает до идентичного .jpg (как вход).
  • APPx, COMи другие метаданные, разделы неграфического маркера ограничены в JPEG (введение произвольного количества случайных байтов в изображение для асимптотического подхода к сжатию 1: 1 неэффективно.)
    • APP0JFIF маркер допускается , но не с миниатюрами не допускается (должно быть ровно 16 байт)
    • tl; dr Если вы намеренно не помещаете метаданные в сегмент EXIF ​​и отключаете любые миниатюры, которые ваша языковая библиотека хочет добавить в изображение, это должно быть в порядке.

Разместите код и изображение.

Если вы хотите написать программу, которая производит изображение Лептона, которое при преобразовании дает JPEG, соответствующий критериям, это нормально. Он должен оставаться одинаковым для любого количества циклов JPEG → Lepton → JPEG → ....

счет

Размер в байтах изображения Лептона, деленный на исходное изображение JPEG. Чем выше (хуже компрессия Лептона), тем лучше. Запустите Lepton с флагами и переключателями по умолчанию.


Получение Лептона

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 ты имеешь в виду, как мой пример?
Ник Т

1
Кроме того, поскольку JPEG - это формат с потерями, существует множество способов (например, «качество») для сжатия данного изображения. Каждый файл JPEG включает в себя пару таблиц, которые определяют, как декодируется остальная часть изображения, и эти таблицы в основном могут быть любыми. Если вы сохраните изображение BMP в разных программах, оно, вероятно, будет идентичным. Если вы сохраняете JPG в разных программах, если они не используют одну и ту же внутреннюю библиотеку, вероятно, нет.
Ник Т

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компрессор (в формате 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 больше исходного TGA-изображения без сжатия, хотя JPEG использует сжатие с потерями.

Интересный факт 2: Imgur (хостинг изображений по умолчанию для SO) очень плохо справляется с этим файлом - по какой-то причине он сжимает его до более низкого качества, даже если он меньше 1 МБ. Поэтому я использовал 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')

шум

Затем некоторые вещи, чтобы сделать вещь:

./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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.