Да, старый добрый GIF. Любимый за его универсальность, ненавистный за его патенты и частично устаревший из-за его ограничений (и патентов), GIF состоит, в основном, из цветовой палитры и изображения с индексом палитры, сжатых с использованием алгоритма LZW.
Ваша задача - написать программу, которая считывает изображение в формате ASCII PPM (магическое число «P3») со стандартного ввода и записывает то же изображение (идентично попиксельно) в формате GIF в стандартный вывод. Вывод может быть либо в двоичной форме, либо в виде текста ASCII, где каждый байт представлен числом от 0 до 255 (включительно), разделенным пробелом.
Входное изображение гарантированно не будет иметь более 256 различных цветов.
Подсчет очков:
Ваша программа будет протестирована на 3 образцах изображений, а ваш счет будет рассчитываться следующим образом:
размер программы + сумма (выходной размер - эталонный размер для каждого изображения образца)
Побеждает самый низкий показатель.
Требования:
- Ваша программа должна работать с любыми подобными видами изображений разных размеров, и не ограничиваться образцами изображений. Вы можете, например, ограничить размеры, кратные 2, или предположить, что максимальный цвет ppm равен 255, но он все равно должен работать с широким спектром входных изображений.
- Выходными данными должен быть действительный GIF-файл, который можно загрузить с помощью любой совместимой программы (после преобразования обратно в двоичный файл, если используется опция вывода ASCII).
- Вы не можете использовать какие-либо функции обработки изображений (встроенные или сторонние), ваша программа должна содержать весь соответствующий код.
- Ваша программа должна быть запущена в Linux с использованием свободно доступного программного обеспечения.
- Исходный код должен использовать только символы ASCII.
Образцы изображений:
Вот 3 образца изображения, которые будут использоваться для оценки. Вы можете скачать zip-архив с файлами ppm (используйте кнопку загрузки в верхней части этой страницы). Или вы можете преобразовать их из изображений PNG ниже, используя ImageMagick с помощью следующей команды:
convert file.png -compress none file.ppm
Я также предоставляю контрольные суммы MD5 файлов ppm для подтверждения.
1. янтарь
Контрольный размер: 38055 Контрольная
сумма MD5 ppm: d1ad863cb556869332074717eb278080
2. голубые
Контрольный размер: 28638 Контрольная
сумма MD5 ppm: e9ad410057a5f6c25a22a534259dcf3a
3. перец
Контрольный размер: 53586 Контрольная
сумма MD5 ppm: 74112dbdbb8b7de5216f9e24c2e1a627
источник
Ответы:
Perl, 515 + -2922 + 0 + -2571 = -4978
Другой подход. На этот раз я пытаюсь сохранить изображение в тайлах размером 64xH. Это хорошо согласно спецификациям, но некоторые программы могут показывать только первую плитку или анимацию. Плитка лучше сжимается благодаря лучшему пространственному расположению. Я все еще делаю обычное сжатие для второго изображения и выбираю то, что получилось короче. Так как это сжимает изображение дважды, это вдвое медленнее по сравнению с моим предыдущим решением.
Perl, 354 + 12 + 0 + -1 = 365
418 9521 51168 56639Либо в моем коде есть какая-то ошибка, либо второе изображение оптимизировано для конкретного кодировщика, так как казалось бы незначительное изменение уменьшило размер до эталонного размера. Принимает около 30-х-60-х годов на изображение.
Гольф версия.
Единственное решение, которое может принять компрессор GIF, - это сброс словаря LZW. В общем, из-за того, как изображения для этой задачи были выбраны, наилучшим моментом для этого является каждый 4096 кодов, то есть момент, когда словарь переполняется. С таким ограничением словарь никогда не переполняется, что экономит пару байтов в реализации. Вот как это работает в деталях:
Perl, 394 + -8 + 0 + -12 = 374
Добавление эвристики для угадывания точки сброса немного улучшает сжатие, но не настолько, чтобы оправдать дополнительный код:
источник
CJam, счет 155 + 35306 + 44723 + 21518 = 101702
Просто тупая эталонная реализация. Это медленно, не делает никакого фактического сжатия, и это не игра в гольф.
источник