A fork of https://github.com/crosspoint-reader/crosspoint-reader
1#pragma once
2
3#include <HalStorage.h>
4
5#include <cstdint>
6
7#include "BitmapHelpers.h"
8
9#pragma pack(push, 1)
10struct BmpHeader {
11 struct {
12 uint16_t bfType;
13 uint32_t bfSize;
14 uint16_t bfReserved1;
15 uint16_t bfReserved2;
16 uint32_t bfOffBits;
17 } fileHeader;
18 struct {
19 uint32_t biSize;
20 int32_t biWidth;
21 int32_t biHeight;
22 uint16_t biPlanes;
23 uint16_t biBitCount;
24 uint32_t biCompression;
25 uint32_t biSizeImage;
26 int32_t biXPelsPerMeter;
27 int32_t biYPelsPerMeter;
28 uint32_t biClrUsed;
29 uint32_t biClrImportant;
30 } infoHeader;
31 struct RgbQuad {
32 uint8_t rgbBlue;
33 uint8_t rgbGreen;
34 uint8_t rgbRed;
35 uint8_t rgbReserved;
36 };
37 RgbQuad colors[2];
38};
39#pragma pack(pop)
40
41enum class BmpReaderError : uint8_t {
42 Ok = 0,
43 FileInvalid,
44 SeekStartFailed,
45
46 NotBMP,
47 DIBTooSmall,
48
49 BadPlanes,
50 UnsupportedBpp,
51 UnsupportedCompression,
52
53 BadDimensions,
54 ImageTooLarge,
55 PaletteTooLarge,
56
57 SeekPixelDataFailed,
58 BufferTooSmall,
59 OomRowBuffer,
60 ShortReadRow,
61};
62
63class Bitmap {
64 public:
65 static const char* errorToString(BmpReaderError err);
66
67 explicit Bitmap(FsFile& file, bool dithering = false) : file(file), dithering(dithering) {}
68 ~Bitmap();
69 BmpReaderError parseHeaders();
70 BmpReaderError readNextRow(uint8_t* data, uint8_t* rowBuffer) const;
71 BmpReaderError rewindToData() const;
72 int getWidth() const { return width; }
73 int getHeight() const { return height; }
74 bool isTopDown() const { return topDown; }
75 bool hasGreyscale() const { return bpp > 1; }
76 int getRowBytes() const { return rowBytes; }
77 bool is1Bit() const { return bpp == 1; }
78 uint16_t getBpp() const { return bpp; }
79
80 private:
81 static uint16_t readLE16(FsFile& f);
82 static uint32_t readLE32(FsFile& f);
83
84 FsFile& file;
85 bool dithering = false;
86 int width = 0;
87 int height = 0;
88 bool topDown = false;
89 uint32_t bfOffBits = 0;
90 uint16_t bpp = 0;
91 uint32_t colorsUsed = 0;
92 bool nativePalette = false; // true if all palette entries map to native gray levels
93 int rowBytes = 0;
94 uint8_t paletteLum[256] = {};
95
96 // Dithering state (mutable for const methods)
97 mutable int16_t* errorCurRow = nullptr;
98 mutable int16_t* errorNextRow = nullptr;
99 mutable int prevRowY = -1; // Track row progression for error propagation
100
101 mutable AtkinsonDitherer* atkinsonDitherer = nullptr;
102 mutable FloydSteinbergDitherer* fsDitherer = nullptr;
103};