ESPHome 2026.3.0-dev
Loading...
Searching...
No Matches
bmp_decoder.cpp
Go to the documentation of this file.
1#include "bmp_decoder.h"
2
3#ifdef USE_RUNTIME_IMAGE_BMP
4
7#include "esphome/core/log.h"
8
10
11static const char *const TAG = "image_decoder.bmp";
12
13int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) {
14 size_t index = 0;
15 if (this->current_index_ == 0 && index == 0 && size > 14) {
26 // Check if the file is a BMP image
27 if (buffer[0] != 'B' || buffer[1] != 'M') {
28 ESP_LOGE(TAG, "Not a BMP file");
30 }
31
32 // BMP file contains its own size in the header
33 size_t file_size = encode_uint32(buffer[5], buffer[4], buffer[3], buffer[2]);
34 if (this->expected_size_ == 0) {
35 this->expected_size_ = file_size; // Use file header size if not provided
36 }
37 this->data_offset_ = encode_uint32(buffer[13], buffer[12], buffer[11], buffer[10]);
38
39 this->current_index_ = 14;
40 index = 14;
41 }
42 if (this->current_index_ == 14 && index == 14 && size > this->data_offset_) {
57 this->width_ = encode_uint32(buffer[21], buffer[20], buffer[19], buffer[18]);
58 this->height_ = encode_uint32(buffer[25], buffer[24], buffer[23], buffer[22]);
59 this->bits_per_pixel_ = encode_uint16(buffer[29], buffer[28]);
60 this->compression_method_ = encode_uint32(buffer[33], buffer[32], buffer[31], buffer[30]);
61 this->image_data_size_ = encode_uint32(buffer[37], buffer[36], buffer[35], buffer[34]);
62 this->color_table_entries_ = encode_uint32(buffer[49], buffer[48], buffer[47], buffer[46]);
63
64 switch (this->bits_per_pixel_) {
65 case 1:
66 this->width_bytes_ = (this->width_ % 8 == 0) ? (this->width_ / 8) : (this->width_ / 8 + 1);
67 break;
68 case 24:
69 this->width_bytes_ = this->width_ * 3;
70 if (this->width_bytes_ % 4 != 0) {
71 this->padding_bytes_ = 4 - (this->width_bytes_ % 4);
72 this->width_bytes_ += this->padding_bytes_;
73 }
74 break;
75 default:
76 ESP_LOGE(TAG, "Unsupported bits per pixel: %d", this->bits_per_pixel_);
78 }
79
80 if (this->compression_method_ != 0) {
81 ESP_LOGE(TAG, "Unsupported compression method: %d", this->compression_method_);
83 }
84
85 if (!this->set_size(this->width_, this->height_)) {
87 }
88 this->current_index_ = this->data_offset_;
89 index = this->data_offset_;
90 }
91 switch (this->bits_per_pixel_) {
92 case 1: {
93 while (index < size) {
94 uint8_t current_byte = buffer[index];
95 for (uint8_t i = 0; i < 8; i++) {
96 size_t x = (this->paint_index_ % static_cast<size_t>(this->width_)) + i;
97 size_t y = static_cast<size_t>(this->height_ - 1) - (this->paint_index_ / static_cast<size_t>(this->width_));
98 Color c = (current_byte & (1 << (7 - i))) ? display::COLOR_ON : display::COLOR_OFF;
99 this->draw(x, y, 1, 1, c);
100 }
101 this->paint_index_ += 8;
102 this->current_index_++;
103 index++;
104 }
105 break;
106 }
107 case 24: {
108 while (index < size) {
109 if (index + 2 >= size) {
110 this->decoded_bytes_ += index;
111 return index;
112 }
113 uint8_t b = buffer[index];
114 uint8_t g = buffer[index + 1];
115 uint8_t r = buffer[index + 2];
116 size_t x = this->paint_index_ % static_cast<size_t>(this->width_);
117 size_t y = static_cast<size_t>(this->height_ - 1) - (this->paint_index_ / static_cast<size_t>(this->width_));
118 Color c = Color(r, g, b);
119 this->draw(x, y, 1, 1, c);
120 this->paint_index_++;
121 this->current_index_ += 3;
122 index += 3;
123 size_t last_col = static_cast<size_t>(this->width_) - 1;
124 if (x == last_col && this->padding_bytes_ > 0) {
125 index += this->padding_bytes_;
126 this->current_index_ += this->padding_bytes_;
127 }
128 }
129 break;
130 }
131 default:
132 ESP_LOGE(TAG, "Unsupported bits per pixel: %d", this->bits_per_pixel_);
134 }
135 this->decoded_bytes_ += size;
136 return size;
137};
138
139} // namespace esphome::runtime_image
140
141#endif // USE_RUNTIME_IMAGE_BMP
int HOT decode(uint8_t *buffer, size_t size) override
void draw(int x, int y, int w, int h, const Color &color)
Fill a rectangle on the display_buffer using the defined color.
bool set_size(int width, int height)
Request the image to be resized once the actual dimensions are known.
const Color COLOR_ON(255, 255, 255, 255)
Turn the pixel ON.
Definition display.h:303
const Color COLOR_OFF(0, 0, 0, 0)
Turn the pixel OFF.
Definition display.h:301
size_t size
Definition helpers.h:729
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
Definition helpers.h:536
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition helpers.h:528
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6