Конвертация PNG в файлы Portable Any Map и Farbfeld

В одной из статей мы упоминали, что нам не удалось найти примеры изображений в одном из описанных в блоге форматов. Тогда, проблема с отсутствием демонстрационных файлов решилась с помощью сторонних утилит и последующей конвертацией в нужный формат. Однако, очень неудобно иметь зависимость от стороннего инструмента и потому мы решили написать простой рецепт осуществления этой задачи силами D.

Для конвертации файла с изображением в формате PNG в любой из файлов Portable Any Map используется dlib, а также две наших библиотеки (обе теперь есть в dub): ppmformats и farbfelded. Заготовка кода конвертации при этом будет выглядеть так:

#!/usr/bin/env dub
/+ dub.sdl:
     name "png2ff"
     dependency "dlib" version="~>0.20.0"
     dependency "farbfelded" version="~>0.0.1"
     dependency "ppmformats" version="~>0.0.3"
+/

import dlib.image;
import farbfelded;
import ppmformats;

auto toFarbfeld(SuperImage simg)
{
    FarbfeldImage ff = new FarbfeldImage(simg.width, simg.height);

    foreach (i; 0..simg.width)
    {
        foreach (j; 0..simg.height)
        {
            auto color = simg[i, j];
            ff[i, j] = new RGBAColor(
                cast(int) (65535 * color.r),
                cast(int) (65535 * color.g),
                cast(int) (65535 * color.b),
                cast(int) (65535 * color.a)
            );
        }
    }

    return ff;
}


auto toPNM(SuperImage simg, string pmFormat = "P6")
{
    auto pmf = image(simg.width, simg.height, pmFormat);

    foreach (i; 0..simg.width)
    {
        foreach (j; 0..simg.height)
        {
            auto color = simg[i, j];
            pmf[i, j] = new RGBColor(
                cast(int) (255 * color.r),
                cast(int) (255 * color.g),
                cast(int) (255 * color.b)
            );
        }
    }

    return pmf;
}


void main(string[] args)
{
    import std.stdio;
    import std.string;
    import std.traits;
   
    auto p = load(`/home/aquareji/Templates/Lenna0.png`);

    string[] fmts = cast(string[]) [EnumMembers!PixMapFormat];
    string[] ext = ["pbm", "pgm", "ppm"];

    foreach (i, e; ext)
    {
        auto I = 2 * i;
        SuperImage q;
       
        if (e == "pbm")
        {
            q = p.otsuBinarization;
        }
        else
        {
            q = p;
        }
    
        q.toPNM(fmts[I]).save(`/home/aquareji/Templates/Lenna_%s.%s`.format(fmts[I], ext[i]));
        q.toPNM(fmts[I+1]).save(`/home/aquareji/Templates/Lenna_%s.%s`.format(fmts[I + 1], ext[i]));
    }

    p.toFarbfeld.save(`/home/aquareji/Templates/Lenna.ff`);
}

Примечание. Для тех кто забыл напоминаем, Portable AnyMap имеет 6 различных вариантов формата для изображений, которые отличаются друг от друга видом представляемой информации и “магическим числом” — сигнатурой. Сигнатура служит еще и именем формата, которое позволяет уточнить тип файла. К примеру, можно сказать, что есть формат изображения P6, подразумевая при этом файл вида Portable Any Map с сигнатурой P6, т.е. обычный бинарный вариант PPM.

Данный код реализует две функции конвертации изображения с типом SuperImage (это тип изображения, который использует dlib) в нужные виды изображения:

  • toFarbfeld – конвертация в формат Farbfeld с генерацией результата с типом FarbfeldImage;
  • toPNM – конвертация в формат PNM (Portable aNy Map) с последующей генерацией одного из типов PxImage, где x – число от 1 до 6, соответствующее номеру в сигнатуре формата.

Эти функции используются в приведенном примере-заготовке, который реализует простейший скрипт-конвертор. В скрипте прописаны нужны зависимости для dub и вручную прописаны пути для демонстрационного изображения Lenna в формате PNG. Сам скрипт при этом выполняет конвертацию изображения Лены во все известные библиотеке ppmformats форматы от P1 до P6, после чего производит конвертацию в формат Farbfeld. Кроме того, скрипт работает не только с PNG, но и другими форматами, которые поддерживает dlib, а это означает, что показанный нами код может быть использован как основа для других типов конверсии, а также как код для универсального конвертера.

Исходный файл и результат работы скрипта можно увидеть тут: https://github.com/LightHouseSoftware/EoFF

aquaratixc

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

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