BMP файл состоит из заголовка и растрового массива. Заголовок задаётся следующей структурой:
#include <stdint.h>
struct bmp_header __attribute__((packed))
{
uint16_t bfType;
uint32_t bfileSize;
uint32_t bfReserved;
uint32_t bOffBits;
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMeter;
uint32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
};Сразу после него идёт растровый массив, в котором последовательно хранятся пиксели по строчкам. Каждый пиксель задаётся структурой размером 3 байта:
struct pixel { uint8_t b, g, r; };Если ширина изображения в байтах кратна четырём, то строчки идут одна за другой без пропусков. Если ширина не кратна четырём, то она дополняется мусорными padding-байтами до ближайшего числа, кратного четырём.
Пример:
- Изображение имеет ширину 12 пикселей = 12 * 3 байт = 36 байт. Ширина кратна четырём, каждая следующая строчка начинается сразу после предыдущей.
- Изображение имеет ширину 5 пикселей. 5 * 3 = 15 байт, ближайшее число кратное четырём (округление вверх) это 16. После каждой строчки будет отступ в 16-15 = 1 байт перед началом следующей.
Программа разделена на модули; каждый модуль это .c файл, который становится файлом с расширением .o.
Описание внутреннего представления картинки struct image, очищенное от
деталей формата, и функции для работы с ним: создание, деинициализация и т.д.
struct image {
uint64_t width, height;
struct pixel* data;
};Эта часть программы не знает ни про входные форматы, ни про трансформации.
Каждый входной формат описывается в отдельном модуле; они предоставляют функции
для считывания файлов разных форматов в struct image и для записи на диск в
тех же форматах.
Эти модули знают про модуль, описывающий struct image, но ничего не знают про
трансформации.
/* deserializer */
enum read_status {
READ_OK = 0,
READ_INVALID_SIGNATURE,
READ_INVALID_BITS,
READ_INVALID_HEADER
/* коды других ошибок */
};
enum read_status from_bmp( FILE* in, struct image* img );
/* serializer */
enum write_status {
WRITE_OK = 0,
WRITE_ERROR
/* коды других ошибок */
};
enum write_status to_bmp( FILE* out, struct image const* img );Каждая трансформация описана в отдельном модуле в app/src/transform.
P.S. Реализована только функция поворота изображения