Конвертация изображений из формата PPM в QOI

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

aquaratixc

Программист-самоучка и программист-любитель

Добавить комментарий