Added simple bitmap interface
commit
46248d5ee6
|
@ -0,0 +1,133 @@
|
||||||
|
#include "bitmap.hpp"
|
||||||
|
|
||||||
|
Bitmap::Bitmap(size_t w, size_t h) {
|
||||||
|
this->width = w;
|
||||||
|
this->height = h;
|
||||||
|
|
||||||
|
this->data.reserve(h);
|
||||||
|
for (size_t r = 0; r < h; r++) {
|
||||||
|
data[r].reserve(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Bitmap::dump_int_to_bytes(
|
||||||
|
uint64_t a,
|
||||||
|
uint8_t *array,
|
||||||
|
size_t index,
|
||||||
|
size_t num_bytes
|
||||||
|
) {
|
||||||
|
// Dump bytes of i into array starting at index.
|
||||||
|
// least-significant byte goes first.
|
||||||
|
|
||||||
|
if (num_bytes > 4) {
|
||||||
|
throw std::invalid_argument("Cannot dump more than 4 bytes.");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_bytes; i++) {
|
||||||
|
array[index + i] = (a >> (8 * i)) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Bitmap::clear() {
|
||||||
|
// Fill with white pixels
|
||||||
|
for (size_t r = 0; r < height; r++) {
|
||||||
|
for (size_t i = 0; i < width; i++) {
|
||||||
|
data[r][i] = std::make_tuple(
|
||||||
|
0xFF, 0xFF, 0xFF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Bitmap::setpixel(
|
||||||
|
size_t row,
|
||||||
|
size_t col,
|
||||||
|
uint8_t r,
|
||||||
|
uint8_t g,
|
||||||
|
uint8_t b
|
||||||
|
) {
|
||||||
|
data[row][col] = std::make_tuple(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Bitmap::save(const char *filename) const {
|
||||||
|
|
||||||
|
uint8_t header[54] = {
|
||||||
|
// Universal 14-byte header
|
||||||
|
0x42, 0x4D, // Bitmap standard header
|
||||||
|
0x00, 0x00, 0x00, 0x00, // file size (bit 2, overwritten)
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Reserved (leave as zero)
|
||||||
|
0x36, 0x00, 0x00, 0x00, // Index of first byte of pixmap
|
||||||
|
|
||||||
|
// 40-byte BITMAPINFOHEADER
|
||||||
|
0x28, 0x00, 0x00, 0x00, // Length of DIB
|
||||||
|
0x00, 0x00, 0x00, 0x00, // width (px, bit 18, overwritten)
|
||||||
|
0x00, 0x00, 0x00, 0x00, // height (px, bit 22, overwritten)
|
||||||
|
0x01, 0x00, // Number of color planes (always 1)
|
||||||
|
0x18, 0x00, // Number of bits per pixel (0x18 = 24)
|
||||||
|
0x00, 0x00, 0x00, 0x00, // BI_RGB, no pixel array compression
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Size of raw bitmap data, incl. padding (bit 34, overwritten)
|
||||||
|
0xFF, 0x0A, 0x00, 0x00, // Size of horizontal print resolution (px/m)
|
||||||
|
0xFF, 0x0A, 0x00, 0x00, // Size of vertical print resolution (px/m)
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Size of colors in palette
|
||||||
|
0x00, 0x00, 0x00, 0x00 // 0 important colors => all colors are important
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// How many bytes we need to store a row, including padding
|
||||||
|
size_t row_size = ((24 * width + 31) / 32) * 4;
|
||||||
|
// Total size of pixmap
|
||||||
|
uint64_t pixmap_size = row_size * height;
|
||||||
|
// Total size of file
|
||||||
|
uint64_t file_size = 54 + pixmap_size;
|
||||||
|
|
||||||
|
// Set values in header
|
||||||
|
dump_int_to_bytes(file_size, header, 2, 4);
|
||||||
|
dump_int_to_bytes(width, header, 18, 4);
|
||||||
|
dump_int_to_bytes(height, header, 22, 4);
|
||||||
|
dump_int_to_bytes(pixmap_size, header, 34, 4);
|
||||||
|
|
||||||
|
|
||||||
|
FILE *fp = fopen(filename, "wb");
|
||||||
|
fwrite(header, sizeof(header), 1, fp);
|
||||||
|
|
||||||
|
uint8_t r, g, b;
|
||||||
|
for (size_t row = 0; row < height; row++) {
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
// Pixel data
|
||||||
|
while (i < width) {
|
||||||
|
std::tie(r, g, b) = data[height - row - 1][i];
|
||||||
|
fwrite(&b, sizeof(uint8_t), 1, fp);
|
||||||
|
fwrite(&g, sizeof(uint8_t), 1, fp);
|
||||||
|
fwrite(&r, sizeof(uint8_t), 1, fp);
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i *= 3;
|
||||||
|
// Row Padding
|
||||||
|
r = 0;
|
||||||
|
while (i < row_size) {
|
||||||
|
fwrite(&r, sizeof(uint8_t), 1, fp);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
int main() {
|
||||||
|
Bitmap b = Bitmap(200, 200);
|
||||||
|
b.save("file.bmp");
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
class Bitmap {
|
||||||
|
public:
|
||||||
|
Bitmap(size_t w, size_t h);
|
||||||
|
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
void setpixel(
|
||||||
|
size_t row,
|
||||||
|
size_t col,
|
||||||
|
uint8_t r,
|
||||||
|
uint8_t g,
|
||||||
|
uint8_t b
|
||||||
|
);
|
||||||
|
|
||||||
|
void save(const char *filename) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t width;
|
||||||
|
size_t height;
|
||||||
|
|
||||||
|
// Pixel data.
|
||||||
|
// First is a vector of rows,
|
||||||
|
// Second is a vector of pixels.
|
||||||
|
// RGB format.
|
||||||
|
std::vector<
|
||||||
|
std::vector<
|
||||||
|
std::tuple<
|
||||||
|
uint8_t,
|
||||||
|
uint8_t,
|
||||||
|
uint8_t
|
||||||
|
>>
|
||||||
|
> data;
|
||||||
|
|
||||||
|
static void dump_int_to_bytes(
|
||||||
|
uint64_t a,
|
||||||
|
uint8_t* bytes,
|
||||||
|
size_t index,
|
||||||
|
size_t num_bytes
|
||||||
|
);
|
||||||
|
};
|
Loading…
Reference in New Issue