-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbmpwriter.cpp
66 lines (54 loc) · 1.9 KB
/
bmpwriter.cpp
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
#include <iostream>
#include <fstream>
#include <vector>
#pragma pack(push, 1)
struct BMPHeader {
uint16_t bfType = 0x4D42; // 'BM'
uint32_t bfSize = 0;
uint16_t bfReserved1 = 0;
uint16_t bfReserved2 = 0;
uint32_t bfOffBits = 54;
};
struct DIBHeader {
uint32_t biSize = 40;
int32_t biWidth = 0;
int32_t biHeight = 0;
uint16_t biPlanes = 1;
uint16_t biBitCount = 24;
uint32_t biCompression = 0;
uint32_t biSizeImage = 0;
int32_t biXPelsPerMeter = 0;
int32_t biYPelsPerMeter = 0;
uint32_t biClrUsed = 0;
uint32_t biClrImportant = 0;
};
#pragma pack(pop)
struct color {
float r, g, b;
};
void saveBMP(const char* filename, int width, int height, const void* rgbDataVoid) {
const color* rgbData = static_cast<const color*>(rgbDataVoid);
BMPHeader bmpHeader;
DIBHeader dibHeader;
dibHeader.biWidth = width;
dibHeader.biHeight = -height;
dibHeader.biSizeImage = ((width * 3 + 3) & ~3) * height; // row size must be multiple of 4 bytes
bmpHeader.bfSize = sizeof(BMPHeader) + sizeof(DIBHeader) + dibHeader.biSizeImage;
std::ofstream file(filename, std::ios::binary);
if (!file) {
return;
}
file.write(reinterpret_cast<const char*>(&bmpHeader), sizeof(bmpHeader));
file.write(reinterpret_cast<const char*>(&dibHeader), sizeof(dibHeader));
std::vector<uint8_t> rowBuffer((width * 3 + 3) & ~3); // 4-byte aligned row buffer
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
const color& col = rgbData[y * width + x];
rowBuffer[x * 3 + 0] = static_cast<uint8_t>(col.b * 255); // BMP stores BGR format
rowBuffer[x * 3 + 1] = static_cast<uint8_t>(col.g * 255);
rowBuffer[x * 3 + 2] = static_cast<uint8_t>(col.r * 255);
}
file.write(reinterpret_cast<const char*>(rowBuffer.data()), rowBuffer.size());
}
file.close();
}