- Прочитайте главу 12 (стр. 221, 231-239) и 13 (целиком) "Low-level programming: C, assembly and program execution".
На защите мы можем обсуждать любые вопросы из учебника из глав 8–13 включительно.
# Структура BMP файла
BMP файл состоит из заголовка и растрового массива.
Заголовок задаётся следующей структурой (обратите внимание на атрибут `packed`):
```c
#include <stdint.h>
structbmp_header__attribute__((packed))
{
uint16_tbfType;
uint32_tbfileSize;
uint32_tbfReserved;
uint32_tbOffBits;
uint32_tbiSize;
uint32_tbiWidth;
uint32_tbiHeight;
uint16_tbiPlanes;
uint16_tbiBitCount;
uint32_tbiCompression;
uint32_tbiSizeImage;
uint32_tbiXPelsPerMeter;
uint32_tbiYPelsPerMeter;
uint32_tbiClrUsed;
uint32_tbiClrImportant;
};
```
Сразу после него (всегда ли?) идёт растровый массив, в котором последовательно хранятся пиксели по строчкам.
Каждый пиксель задаётся структурой размером 3 байта:
```c
structpixel{uint8_tb,g,r;};
```
Если ширина изображения в пикселах кратна четырём, то строчки идут одна за другой без пропусков.
Если ширина не кратна четырём, то она дополняется мусорными байтами до ближайшего числа байтов, кратного четырём.
Пример:
1. Изображение имеет ширину 12 пикселей = 12 * 3 байт = 36 байт. Ширина кратна четырём, каждая следующая строчка начинается сразу после предыдущей.
2. Изображение имеет ширину 5 пикселей. 5 * 3 = 15 байт, ближайшее число кратное четырём (округление вверх) это 16. После каждой строчки будет отступ в один мусорный байт перед началом следующей.
# Задание
- Необходимо реализовать поворот изображения в формате BMP на 90 градусов.
- Архитектура приложения должна содержать три чётко разделённых части:
- Описание внутреннего представления картинки `struct image`, очищенное от деталей формата
```c
structimage{
uint64_twidth,height;
structpixel*data;
};
```
- Функции для работы с BMP-файлами и сериализации/десериализации внутреннего представления.
```c
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 );
Как только мы считали изображение во внутренний формат, мы должны забыть, из какого формата оно было считано!
- Функции для трансформации внутреннего представления, которые работают с `struct image`.
```c
/* создаёт копию изображения, которая повёрнута на 90 градусов */
struct image rotate( struct image const source );
```
# Для самопроверки:
- Функции должны получать все необходимые им данные через аргументы.
- Нельзя смешивать логику вычислений и ввод-вывод.
- Нельзя использовать `typedef` для определения структур ([объяснение](https://stepik.org/lesson/408350/step/2)).
- Ваш код должен компилироваться с флагами `-std=c18 -pedantic -Wall -Werror`.
- Типы:
- Проверьте, что вы максимально возможным образом расставили `const`.
- Проверьте, что индексы используют только тип `size_t`.
- Проверьте, что вы используете только платформо-независимые типы, такие, как `int64_t` или `int_fast64_t`.
- Проверьте, что вы используете правильные спецификаторы ввода и вывода.
- Вы можете добавлять любое число вспомогательных функций для удобства, это поощряется.
- Проверьте архитектуру. Думайте о том, как бы вы хотели организовать код, чтобы легко добавлять входные форматы (не только BMP) и трансформации (не только поворот на 90 градусов).