-
Notifications
You must be signed in to change notification settings - Fork 0
/
BMPFileRW.h
88 lines (81 loc) · 4.24 KB
/
BMPFileRW.h
1
2
3
4
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
#include <Windows.h>
#include <fstream>
void BMPRead(RGBTRIPLE**&, BITMAPFILEHEADER&, BITMAPINFOHEADER&, std::string);
void BMPWrite(RGBTRIPLE**& rgb, int imWidth, int imHeight, std::string);
unsigned char get_row_data_padding(unsigned int width);
unsigned int bmp24b_file_size_calc(unsigned int width, unsigned int height);
// Определение величины дополнения на случай если ширина изображения не кратна 4
unsigned char get_row_data_padding(unsigned int width) {
return (width % 4 == 0) ? 0 : (4 - (width * sizeof(RGBTRIPLE)) % 4);
}
// Вычисление размера BMP файла
unsigned int bmp24b_file_size_calc(unsigned int width, unsigned int height) {
return sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + height * (width * sizeof(RGBTRIPLE) + get_row_data_padding(width));
}
void BMPRead(RGBTRIPLE**& rgb, BITMAPFILEHEADER& header, \
BITMAPINFOHEADER& bmiHeader, std::string fin)
{
// Открываем файл BMP
std::ifstream InFile(fin, std::ios::binary);
// Считываем заголовок файла
InFile.read((char*)(&header), sizeof(BITMAPFILEHEADER));
// Считываем заголовочную часть изображения
InFile.read((char*)(&bmiHeader), sizeof(BITMAPINFOHEADER));
// Выделяем память под массив RGB хранящий структуры RGBTRIPLE
rgb = new RGBTRIPLE * [bmiHeader.biHeight];
// формируем единую область данных для оптимизации хранения
rgb[0] = new RGBTRIPLE[bmiHeader.biWidth * bmiHeader.biHeight];
for (int i = 1; i < bmiHeader.biHeight; i++)
{ // нестраиваем указатели начала каждой строки
rgb[i] = &rgb[0][bmiHeader.biWidth * i];
}
// перемещаемся на начало данных изображения
InFile.seekg(header.bfOffBits, std::ios::beg);
// определяем величину дополнения на случай если ширина изображения не кратна 4
int padding = get_row_data_padding(bmiHeader.biWidth);
char tmp[3] = { 0,0,0 };
// Считываем данные изображения в массив структур RGB
for (int i = 0; i < bmiHeader.biHeight; i++)
{
InFile.read((char*)(&rgb[bmiHeader.biHeight - 1 - i][0]), bmiHeader.biWidth * sizeof(RGBTRIPLE)); // RGBTRIPLE {Blue Green bRed;}
if (padding > 0)
InFile.read((char*)(&tmp[0]), padding);
}
// Закрываем файл
InFile.close();
}
void BMPWrite(RGBTRIPLE**& rgb, int imWidth, int imHeight, std::string fout)
{
// Открываем файл для записи изображения в формат BMP
std::ofstream OutFile(fout, std::ios::binary);
// Создаем заголовочную часть для файла BMP
BITMAPFILEHEADER header = { 0 };
header.bfType = ('M' << 8) + 'B';
header.bfSize = bmp24b_file_size_calc(imWidth, imHeight);;
header.bfOffBits = 54;
// Создаем заголовочную часть для данных изображения
BITMAPINFOHEADER bmiHeader = { 0 };
// заполняем необходимыми данными
bmiHeader.biSize = 40;
bmiHeader.biWidth = imWidth;
bmiHeader.biHeight = imHeight;
bmiHeader.biPlanes = 1;
bmiHeader.biBitCount = 24;
bmiHeader.biSizeImage = header.bfSize - sizeof(BITMAPINFOHEADER) - sizeof(BITMAPFILEHEADER);
//// Записываем заголовок файла
OutFile.write((char*)(&header), sizeof(BITMAPFILEHEADER));
//// Записываем заголовочную часть изображения
OutFile.write((char*)(&bmiHeader), sizeof(BITMAPINFOHEADER));
// определяем величину дополнения на случай если ширина изображения не кратна 4
int padding = get_row_data_padding(bmiHeader.biWidth);
char tmp[3] = { 0,0,0 };
// Записываем данные изображения из массива структур RGBTRIPLE в файл
for (int i = 0; i < bmiHeader.biHeight; i++)
{
OutFile.write((char*)&(rgb[bmiHeader.biHeight - i - 1][0]), bmiHeader.biWidth * sizeof(RGBTRIPLE));
if (padding > 0)
OutFile.write((char*)(&tmp[0]), padding);
}
// закрываем файл
OutFile.close();
}