Added simple bitmap interface

master
Mark 2022-06-23 11:21:26 -07:00
commit 46248d5ee6
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
2 changed files with 180 additions and 0 deletions

133
src/bitmap/bitmap.cpp Normal file
View File

@ -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");
}
*/

47
src/bitmap/bitmap.hpp Normal file
View File

@ -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
);
};