-
Введение
Цель работы:
Научиться работать файлами в формате BMP, реализовать функционал поиска максимального белого прямоугольника и вывода заданных условием вершин.
Задачи работы:
Для достижения поставленной цели требуется решить следующие задачи:
-
Создать структуры BitMapFileHeader, BitMapInfoHeader , RGB для считывания и работы с BMP-файлом и структуры Point, Vector и BmpBasket для эффективного хранения и передачи информации между функциями ;
-
Создать функции search_tops для поиска вершин фигуры и функцию rectangle, которая проверяет является ли фигура монотонным прямоугольником.
-
Осуществить проверку на наличие BMP-файла;
-
Произвести считывание файла и запустить проверки;
-
Вывести результат.
-
1.Краткое описание кода
1.1 Структура BitMapFileHeader
Здесь и далее для корректного размера структур используется директива #pragma pack(push, 1) #pragma pack(pop) . Это необходимо, чтобы поля структуры не выравнивались до кратного четырем числа байт, а оставались заданного размера. Эта структура предназначена для хранения общей информации о файле. Данная структура содержит следующие поля:
-
uint16_t bfType - тип файла;
-
uint32_t bfSize - размер файла в байтах;
-
uint16_t bfReserved1 - резервное поле;
-
uint16_t bfReserved2 - резервное поле;
-
uint32_t bfOffsetBits – сдвиг битового массива относительно начала файла;
typedef struct BitMapFileHeader{
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffsetBits;
} BitMapFileHeader;
1.2. Структура BitMapInfoHeader.
Эта структура содержит информацию о параметрах файла, его высоте, ширине и так далее. Она состоит из следующих полей:
-
uint32_t biSize - размер данной структуры;
-
uint32_t biWidth - ширина изображения в пикселях;
-
uint32_t biHeight - высота изображения в пикселях;
-
uint16_t biPlanes - количество плоскостей;
-
uint16_t biBitCount - количество бит на пиксель;
-
uint32_t biCompression - тип сжатия;
-
uint32_t biSizeImage - размер изображения в байтах;
-
uint32_t biXpenlsPerMeter- горизонтальное разрешение в пикселях на метр;
-
uint32_t biYpenlsPerMeter - вертикальное разрешение в пикселях на метр;
-
uint32_t biColorUsed - количество используемых цветов из таблицы. Если это значение равно нулю, то в растре используется максимально возможное количество цветов, которые разрешены значением biBitCount;
-
uint32_t biColorsImportant;- это количество важных цветов. Определяет число цветов, которые необходимы для того, чтобы изобразить рисунок. Если это значение равно 0 (как это обычно и бывает), то все цвета считаются важными.
typedef struct BitMapInfoHeader{
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXpenlsPerMeter;
uint32_t biYpenlsPerMeter;
uint32_t biColorUsed;
uint32_t biColorsImportant;
} BitMapInfoHeader;
1.3. Структура RGB.
Необходима для считывания одного пикселя изображения. Содержит информацию о красной, желтой и синей составляющей цвета пикселя.
typedef struct RGB{
uint8_t blue;
uint8_t green;
uint8_t red;
} RGB;
1.4. Структура Point.
Служит для описания точки на плоскости.
typedef struct Point{
uint32_t X;
uint32_t Y;
} Point;
1.5. Структура Vector.
Служит для описания вектора на плоскости.
typedef struct Vector{
int32_t X;
int32_t Y;
} Vector;
1.6. Структура BmpBasket.
Служит обёрткой для данных: координат вершин и размеров плоскости.
typedef struct BmpBasket{
uint32_t width;
uint32_t height;
Point top1;
Point top2;
Point top3;
Point top4;
} BmpBasket;
1.7. Функция rectangle.
Принимает на вход структуру с данными BmpBasket и массив с данными arr[][]. На основе вершин строятся векторы структуры Vector, сравниваются их длины с погрешностью ERROR (значение по умолчанию 0.06 ) и угол между векторами. После проводиться проверка на монотонность фигуры и в случае успеха возвращается площадь фигуры. В случае неудачи -1.
int rectangle(BmpBasket* basket, uint8_t arr[basket->height][basket->width]){
Vector vector1_2 = {basket->top2.X-basket->top1.X,basket->top2.Y-basket->top1.Y},
vector2_3 = {basket->top3.X-basket->top2.X,basket->top3.Y-basket->top2.Y},
vector3_4 = {basket->top4.X-basket->top3.X,basket->top4.Y-basket->top3.Y},
vector4_1 = {basket->top1.X-basket->top4.X,basket->top1.Y-basket->top4.Y};
double v1_len = sqrt(pow(vector1_2.X,2) + pow(vector1_2.Y,2));
double v2_len = sqrt(pow(vector2_3.X,2) + pow(vector2_3.Y,2));
double v3_len = sqrt(pow(vector3_4.X,2) + pow(vector3_4.Y,2));
double v4_len = sqrt(pow(vector4_1.X,2) + pow(vector4_1.Y,2));
int vector_work = vector1_2.X * vector2_3.X + vector1_2.Y*vector2_3.Y;
if(vector_work < 0)
vector_work *= -1;
int vector_multiply = v1_len * v2_len;
if((v1_len - v3_len) <= ERROR && (v2_len - v4_len) <= ERROR && vector_multiply != 0
&& (vector_work/vector_multiply) <= ERROR){
for(uint32_t i = basket->top4.Y; i < basket->top1.Y; i++)
for (uint32_t j = basket->top4.X; j < basket->top3.X; j++)
if(arr[i][j] != 2)
return -1;
return v1_len * v2_len;
}
return -1;
}