ESPHome 2026.10.2
Loading...
Searching...
No Matches
image.cpp
Go to the documentation of this file.
1#include "image.h"
2
3#include "esphome/core/hal.h"
5
6namespace esphome::image {
7
8void Image::draw(int x, int y, display::Display *display, Color color_on, Color color_off) {
9 int img_x0 = 0;
10 int img_y0 = 0;
11 int w = width_;
12 int h = height_;
13
14 auto clipping = display->get_clipping();
15 if (clipping.is_set()) {
16 if (clipping.x > x)
17 img_x0 += clipping.x - x;
18 if (clipping.y > y)
19 img_y0 += clipping.y - y;
20 if (w > clipping.x2() - x)
21 w = clipping.x2() - x;
22 if (h > clipping.y2() - y)
23 h = clipping.y2() - y;
24 }
25
26 switch (type_) {
27 case IMAGE_TYPE_BINARY: {
28 for (int img_x = img_x0; img_x < w; img_x++) {
29 for (int img_y = img_y0; img_y < h; img_y++) {
30 if (this->get_binary_pixel_(img_x, img_y)) {
31 display->draw_pixel_at(x + img_x, y + img_y, color_on);
32 } else if (!this->transparency_) {
33 display->draw_pixel_at(x + img_x, y + img_y, color_off);
34 }
35 }
36 }
37 break;
38 }
40 for (int img_x = img_x0; img_x < w; img_x++) {
41 for (int img_y = img_y0; img_y < h; img_y++) {
42 const uint32_t pos = (img_x + img_y * this->width_);
43 const uint8_t gray = progmem_read_byte(this->data_start_ + pos);
44 Color color = Color(gray, gray, gray, 0xFF);
45 switch (this->transparency_) {
47 if (gray == 1) {
48 continue; // skip drawing
49 }
50 break;
52 // gray is the alpha: blend from color_off to color_on, drawn opaque
53 color = Color(Color::blend_channel(color_off.r, color_on.r, gray),
54 Color::blend_channel(color_off.g, color_on.g, gray),
55 Color::blend_channel(color_off.b, color_on.b, gray), 0xFF);
56 break;
57 default:
58 break;
59 }
60 display->draw_pixel_at(x + img_x, y + img_y, color);
61 }
62 }
63 break;
65 for (int img_x = img_x0; img_x < w; img_x++) {
66 for (int img_y = img_y0; img_y < h; img_y++) {
67 auto color = this->get_rgb565_pixel_(img_x, img_y);
68 if (color.w >= 0x80) {
69 display->draw_pixel_at(x + img_x, y + img_y, color);
70 }
71 }
72 }
73 break;
74 case IMAGE_TYPE_RGB:
75 for (int img_x = img_x0; img_x < w; img_x++) {
76 for (int img_y = img_y0; img_y < h; img_y++) {
77 auto color = this->get_rgb_pixel_(img_x, img_y);
78 if (color.w >= 0x80) {
79 display->draw_pixel_at(x + img_x, y + img_y, color);
80 }
81 }
82 }
83 break;
84 }
85}
86Color Image::get_pixel(int x, int y, const Color color_on, const Color color_off) const {
87 if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
88 return color_off;
89 switch (this->type_) {
91 if (this->get_binary_pixel_(x, y))
92 return color_on;
93 return color_off;
95 return this->get_grayscale_pixel_(x, y);
97 return this->get_rgb565_pixel_(x, y);
98 case IMAGE_TYPE_RGB:
99 return this->get_rgb_pixel_(x, y);
100 default:
101 return color_off;
102 }
103}
104#ifdef USE_LVGL
105lv_image_dsc_t *Image::get_lv_image_dsc() {
106 // lazily construct lvgl image_dsc.
107 if (this->dsc_.data != this->data_start_) {
108 this->dsc_.data = this->data_start_;
109 this->dsc_.header.reserved_2 = 0;
110 this->dsc_.header.stride = this->get_width_stride();
111 this->dsc_.header.w = this->width_;
112 this->dsc_.header.h = this->height_;
113 this->dsc_.data_size = this->get_width_stride() * this->get_height();
114 switch (this->get_type()) {
116 this->dsc_.header.cf = LV_COLOR_FORMAT_A1;
117 break;
118
120 this->dsc_.header.cf = LV_COLOR_FORMAT_A8;
121 break;
122
123 case IMAGE_TYPE_RGB:
124 switch (this->transparency_) {
126 this->dsc_.header.cf = LV_COLOR_FORMAT_ARGB8888;
127 break;
129 default:
130 this->dsc_.header.cf = LV_COLOR_FORMAT_RGB888;
131 break;
132 }
133 break;
134
136 switch (this->transparency_) {
138 this->dsc_.header.cf = LV_COLOR_FORMAT_RGB565A8;
139 break;
140 default:
141 this->dsc_.header.cf = LV_COLOR_FORMAT_RGB565;
142 }
143 break;
144 }
145 }
146 return &this->dsc_;
147}
148#endif // USE_LVGL
149
150bool Image::get_binary_pixel_(int x, int y) const {
151 const uint32_t width_8 = ((this->width_ + 7u) / 8u) * 8u;
152 const uint32_t pos = x + y * width_8;
153 return progmem_read_byte(this->data_start_ + (pos / 8u)) & (0x80 >> (pos % 8u));
154}
156 const uint32_t pos = (x + y * this->width_) * this->bpp_ / 8;
157 Color color = Color(progmem_read_byte(this->data_start_ + pos + 2), progmem_read_byte(this->data_start_ + pos + 1),
158 progmem_read_byte(this->data_start_ + pos + 0), 0xFF);
159
160 switch (this->transparency_) {
162 if (color.g == 1 && color.r == 0 && color.b == 0) {
163 // (0, 1, 0) has been defined as transparent color for non-alpha images.
164 color.w = 0;
165 }
166 break;
168 color.w = progmem_read_byte(this->data_start_ + (pos + 3));
169 break;
170 default:
171 break;
172 }
173 return color;
174}
176 const uint8_t *pos = this->data_start_ + (x + y * this->width_) * this->bpp_ / 8;
177 uint16_t rgb565 = encode_uint16(progmem_read_byte(pos + 1), progmem_read_byte(pos));
178 auto r = (rgb565 & 0xF800) >> 11;
179 auto g = (rgb565 & 0x07E0) >> 5;
180 auto b = rgb565 & 0x001F;
181 auto a = 0xFF;
182 switch (this->transparency_) {
184 a = progmem_read_byte(this->data_start_ + this->width_ * this->height_ * 2 + (x + y * this->width_));
185 break;
187 if (rgb565 == 0x0020)
188 a = 0;
189 break;
190 default:
191 break;
192 }
193 return Color((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2), a);
194}
195
197 const uint32_t pos = (x + y * this->width_);
198 const uint8_t gray = progmem_read_byte(this->data_start_ + pos);
199 switch (this->transparency_) {
201 if (gray == 1)
202 return Color(0, 0, 0, 0);
203 return Color(gray, gray, gray, 0xFF);
205 return Color(0, 0, 0, gray);
206 default:
207 return Color(gray, gray, gray, 0xFF);
208 }
209}
210int Image::get_width() const { return this->width_; }
211int Image::get_height() const { return this->height_; }
212ImageType Image::get_type() const { return this->type_; }
213Image::Image(const uint8_t *data_start, int width, int height, ImageType type, Transparency transparency)
214 : width_(width), height_(height), type_(type), data_start_(data_start), transparency_(transparency) {
215 switch (this->type_) {
217 this->bpp_ = 1;
218 break;
220 this->bpp_ = 8;
221 break;
223 this->bpp_ = 16;
224 break;
225 case IMAGE_TYPE_RGB:
226 this->bpp_ = this->transparency_ == TRANSPARENCY_ALPHA_CHANNEL ? 32 : 24;
227 break;
228 }
229}
230
231} // namespace esphome::image
uint8_t h
Definition bl0906.h:2
void draw_pixel_at(int x, int y)
Set a single pixel at the specified coordinates to default color.
Definition display.h:337
Rect get_clipping() const
Get the current the clipping rectangle.
Definition display.cpp:764
Color get_rgb565_pixel_(int x, int y) const
Definition image.cpp:175
const uint8_t * data_start_
Definition image.h:54
Color get_rgb_pixel_(int x, int y) const
Definition image.cpp:155
size_t get_width_stride() const
Return the stride of the image in bytes, that is, the distance in bytes between two consecutive rows ...
Definition image.h:37
Image(const uint8_t *data_start, int width, int height, ImageType type, Transparency transparency)
Definition image.cpp:213
Color get_pixel(int x, int y, Color color_on=display::COLOR_ON, Color color_off=display::COLOR_OFF) const
Definition image.cpp:86
ImageType type_
Definition image.h:53
int get_height() const override
Definition image.cpp:211
ImageType get_type() const
Definition image.cpp:212
bool get_binary_pixel_(int x, int y) const
Definition image.cpp:150
Transparency transparency_
Definition image.h:55
lv_img_dsc_t dsc_
Definition image.h:58
lv_image_dsc_t * get_lv_image_dsc()
Definition image.cpp:105
void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override
Definition image.cpp:8
int get_width() const override
Definition image.cpp:210
Color get_grayscale_pixel_(int x, int y) const
Definition image.cpp:196
uint16_t type
@ TRANSPARENCY_ALPHA_CHANNEL
Definition image.h:21
@ TRANSPARENCY_CHROMA_KEY
Definition image.h:20
@ IMAGE_TYPE_GRAYSCALE
Definition image.h:13
@ IMAGE_TYPE_BINARY
Definition image.h:12
@ IMAGE_TYPE_RGB565
Definition image.h:15
@ IMAGE_TYPE_RGB
Definition image.h:14
size_t size_t pos
Definition helpers.h:1186
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:978
uint8_t progmem_read_byte(const uint8_t *addr)
Definition hal.h:43
static void uint32_t
uint8_t w
Definition color.h:42
static uint8_t blend_channel(uint8_t from, uint8_t to, uint8_t amnt) ESPHOME_ALWAYS_INLINE
One channel of gradient(): from at amnt 0 to to at amnt 255.
Definition color.h:180
uint8_t g
Definition color.h:34
uint8_t b
Definition color.h:38
uint8_t r
Definition color.h:30
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6