В этой небольшой статье, мы вам покажем как с помощью нашей библиотеки 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-файле