В этой небольшой статье, мы вам покажем как с помощью нашей библиотеки qoiformats, про которую мы еще не рассказывали, осуществить перевод картинок из уже знакомых вам PPM P6 файлов в относительно новый формат со сжатием QOI.
Формат QOI (само наименование расшифровывается как Quiet OK Image) — это новый формат для хранения изображений, который был разработан Домиником Шаблевски. Данный формат является форматом со сжатием, но без потери качества, и основан он на простой арифметике и его реализация представляет собой 300 строк бесхитростного кода на C. Но, не это в новом формате главное, поскольку настоящим его достоинством является очень высокая скорость кодирования/декодирования при размерах файлов сопоставимых с аналогичными файлами формата PNG. По заявлениям автора скорость сжатия картинок превышает таковую в 20 — 30 раз, а при декодировании в 2 — 3 раза, если брать распространенные библиотеки libpng и stbi, при этом размеры файлов почти такие же.
На фоне интереса к данному формату на площадке HabrHabr, мы задумали написать свою версию библиотеки для работы с QOI и не мудрствуя лукаво, мы взяли за основу код основной реализации на C. Далее, осуществили перевод (практически без изменений) в D и расширили несколько базовый функционал библиотеки, добавив туда обертки на C-подобным кодом, а также написав ряд типов для более удобного взаимодействия с библиотекой. Данная библиотека нами была выпущена 22 января 2022 года под названием qoiformats (но мы так и не решились о ней рассказать) и с момента создания доступна в реестре dub.
У этой библиотеки интерфейс очень похож на интерфейс другой нашей библиотеки — ppmformats, и ее мы тоже будем использовать в скрипте конверсии. В частности, есть похожие типы для представления пикселя и изображения, а также есть целые методы и принципы доступа к отдельным элементам, которые одинаковы во обеих библиотеках: индексирование изображения через одномерный/двумерный массив, запрос компонентов цвета, save/load и многое другое. Это обстоятельство позволит без проблем подружить обе библиотеки в одном проекте, а также на примере простого скрипта показать интерфейс одной из них.
С помощью следующего однофайлового dub-скрипта можно сделать конвертер изображений из формата PPM P6 в формат QOI:
#!/usr/bin/env dub /+ dub.sdl: dependency "ppmformats" version="0.0.5" dependency "qoiformats" version="0.0.2" +/ import std.file : exists; import std.stdio : writeln, writefln; import std.string : replace; import ppmformats; import qoiformats; void main(string[] args) { if (args.length < 2) { writeln("Usage: ppm2qoi <file1 file2 ... fileN>"); } else { foreach (f; args[1..$]) { if (f.exists) { auto ppm = new P6Image; ppm.load(f); scope(failure) { writefln("Error in loading %s ppm file", f); continue; } auto width = cast(uint) ppm.width; auto height = cast(uint) ppm.height; auto qoi = new QoiImage(width, height); foreach (i; 0..(width * height)) { auto color = ppm[i]; qoi[cast(uint) i] = new QoiColor( cast(ubyte) color.getR, cast(ubyte) color.getG, cast(ubyte) color.getB ); } qoi.save( f.replace(`.ppm`, `.qoi`) ); scope(failure) { writefln("Error in saving file %s as QOI", f); continue; } qoi.info.writeln; } else { writefln("File %s not exists", f); continue; } } } }
Как видите, тут все просто. И несмотря на то, что была показана лишь малая часть работы с библиотекой, но этого вполне достаточно чтобы начать с ней работу, а наши примеры с использованием ppmformats легко переводятся на работу с qoiformats с помощью простой автозамены некоторых именований и функций.
В качестве примера изображения можно воспользоваться одним из тестовых примеров изображений от автора формата (доступны здесь) или же взять стандартное изображение Lenna, которое создали мы с помощью данного скрипта (взять можно здесь).
И напоследок ряд ссылок по QOI:
- Главное — скорость. Новый графический формат QOI в 20−50 раз быстрее PNG
- QOI: как сжимать изображения в 20 раз быстрее STBI и без потерь
- Официальная страница формата (не поверите, описание формата — это одностраничный PDF !)
- Страница QOI на GitHub — описание формата, инструментов и доступных библиотек для работы (qoiformats есть в списке)
- Страница qoiformats на GitHub
- Страница qoiformats в реестре dub
- Официальная реализация кодера/декодера в одном C-файле