README.md 5.77 KB
Newer Older
Igor Zhirkov's avatar
Igor Zhirkov committed
1 2 3
# Assignment #6: Image rotation
---
Лабораторная работа №6: поворот картинки
Igor Zhirkov's avatar
Igor Zhirkov committed
4

Igor Zhirkov's avatar
Igor Zhirkov committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
# Подготовка

- Прочитайте главу 12 (стр. 221, 231-239) и 13 (целиком) "Low-level programming: C, assembly and program execution". 

На защите мы можем обсуждать любые вопросы из учебника из глав 8–13 включительно.

# Структура BMP файла

BMP файл состоит из заголовка и растрового массива.
Заголовок задаётся следующей структурой (обратите внимание на атрибут `packed`):

```c
#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 байта:

```c
   struct pixel { uint8_t b, g, r; };
```

Если ширина изображения в пикселах кратна четырём, то строчки идут одна за другой без пропусков.
Если ширина не кратна четырём, то она дополняется мусорными байтами до ближайшего числа байтов, кратного четырём.

Пример:

1. Изображение имеет ширину 12 пикселей = 12 * 3 байт = 36 байт. Ширина кратна четырём, каждая следующая строчка начинается сразу после предыдущей.
2. Изображение имеет ширину 5 пикселей. 5 * 3 = 15 байт, ближайшее число кратное четырём (округление вверх) это 16. После каждой строчки будет отступ в один мусорный байт перед началом следующей.


# Задание


- Необходимо реализовать поворот изображения в формате BMP на 90 градусов.
- Архитектура приложения должна содержать три чётко разделённых части:
   - Описание внутреннего представления картинки `struct image`, очищенное от деталей формата
   ```c
   struct image {
     uint64_t width, height;
     struct pixel* 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 );
    /*  serializer   */
    enum  write_status  {
        WRITE_OK = 0,
        WRITE_ERROR
        /* коды других ошибок  */
    };
    /*  serializer   */ 
    enum write_status to_bmp( FILE* out, struct image const* 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 градусов).