Формат изображения PPM (Portable Pixmap)

Формат изображения PPM (Portable Pixmap)

Формат PPM (Portable Pixmap Format) — это простой формат графических файлов, используемый для хранения цветных растровых изображений. Он принадлежит к семейству форматов Netpbm, которые также включают PBM (Portable Bitmap) и PGM (Portable Graymap). PPM-файлы являются текстовыми или бинарными и предназначены для простого хранения и обмена изображениями между разными системами. Простота формата делает его удобным для учебных целей и быстрой реализации в различных языках программирования.

Структура PPM-файла

PPM-файл имеет следующую структуру:

  1. Магическое число: определяет тип файла и формат хранения данных. Для текстового формата PPM это «P3», для бинарного — «P6».
  2. Число колонок (ширина изображения): количество пикселей по горизонтали.
  3. Число рядов (высота изображения): количество пикселей по вертикали.
  4. Максимальное значение яркости: максимальное значение цвета для одного канала (обычно 255).
  5. Информация о пикселях: данные о цвете каждого пикселя, представлены в виде тройки значений (красный, зеленый, синий).

Пример структуры текстового PPM-файла:

P3
4 4
255
255 0 0  0 255 0  0 0 255  255 255 0
255 255 255  128 128 128  64 64 64  0 0 0
255 0 255  0 255 255  192 192 192  32 32 32
128 0 128  0 128 0  0 0 128  255 255 255

Пример PPM-файла

Пример простого PPM-файла в текстовом формате (P3):

P3
3 2
255
255 0 0   0 255 0   0 0 255
255 255 0 255 255 255 0 0 0

Этот файл описывает изображение размером 3×2 пикселя. Первая строка содержит магическое число «P3», указывающее на текстовый формат. Вторая строка задает ширину и высоту изображения. Третья строка определяет максимальное значение яркости (255). Далее следуют данные о пикселях: первые три числа — это значения RGB для первого пикселя, следующие три — для второго и так далее.

Инструкции по созданию и чтению PPM-файлов на языке программирования D (Dlang)

Для работы с PPM-файлами в языке программирования D создадим два класса: Pixel и Image. Класс Pixel будет представлять отдельный пиксель изображения, а класс Image — все изображение целиком.

Класс Pixel

class Pixel {
    uint r;
    uint g;
    uint b;

    this(uint r, uint g, uint b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }
}

Класс Image

import std.stdio;
import std.file;

class Image {
    uint width;
    uint height;
    uint maxColorValue;
    Pixel[][] pixels;

    this(uint width, uint height, uint maxColorValue = 255) {
        this.width = width;
        this.height = height;
        this.maxColorValue = maxColorValue;
        this.pixels = new Pixel[][](height, width);
    }

    void setPixel(uint x, uint y, Pixel pixel) {
        pixels[y][x] = pixel;
    }

    Pixel getPixel(uint x, uint y) {
        return pixels[y][x];
    }

    void saveToFile(string filename) {
        File file = File(filename, "w");
        file.writefln("P3");
        file.writefln("%d %d", width, height);
        file.writefln("%d", maxColorValue);
        foreach (row; pixels) {
            foreach (pixel; row) {
                file.writefln("%d %d %d", pixel.r, pixel.g, pixel.b);
            }
        }
        file.close();
    }

    static Image loadFromFile(string filename) {
        File file = File(filename, "r");
        string header = file.readln().strip();
        if (header != "P3") {
            throw new Exception("Invalid PPM file format");
        }

        auto dimensions = file.readln().strip().split();
        uint width = dimensions[0].to!uint;
        uint height = dimensions[1].to!uint;

        uint maxColorValue = file.readln().strip().to!uint;

        Image img = new Image(width, height, maxColorValue);
        foreach (y; 0 .. height) {
            foreach (x; 0 .. width) {
                auto rgb = file.readln().strip().split();
                uint r = rgb[0].to!uint;
                uint g = rgb[1].to!uint;
                uint b = rgb[2].to!uint;
                img.setPixel(x, y, new Pixel(r, g, b));
            }
        }
        file.close();
        return img;
    }
}

Пример кода для сохранения и загрузки PPM-файлов

import std.stdio;

void main() {
    // Создание нового изображения 3x2
    auto img = new Image(3, 2);

    // Установка пикселей
    img.setPixel(0, 0, new Pixel(255, 0, 0));
    img.setPixel(1, 0, new Pixel(0, 255, 0));
    img.setPixel(2, 0, new Pixel(0, 0, 255));
    img.setPixel(0, 1, new Pixel(255, 255, 0));
    img.setPixel(1, 1, new Pixel(255, 255, 255));
    img.setPixel(2, 1, new Pixel(0, 0, 0));

    // Сохранение изображения в файл
    img.saveToFile("output.ppm");

    // Загрузка изображения из файла
    auto loadedImg = Image.loadFromFile("output.ppm");

    // Проверка загруженных данных
    foreach (y; 0 .. loadedImg.height) {
        foreach (x; 0 .. loadedImg.width) {
            auto pixel = loadedImg.getPixel(x, y);
            writeln("Pixel at (", x, ",", y, "): ", pixel.r, " ", pixel.g, " ", pixel.b);
        }
    }
}

Этот пример демонстрирует создание и сохранение изображения в формате PPM, а затем загрузку и вывод данных о пикселях загруженного изображения.


Карпов Ярослав

Автор статьи:

Обновлено:

01.06.2024


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *