ESPHome 2025.12.0-dev
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 {
7namespace image {
8
9void Image::draw(int x, int y, display::Display *display, Color color_on, Color color_off) {
10 int img_x0 = 0;
11 int img_y0 = 0;
12 int w = width_;
13 int h = height_;
14
15 auto clipping = display->get_clipping();
16 if (clipping.is_set()) {
17 if (clipping.x > x)
18 img_x0 += clipping.x - x;
19 if (clipping.y > y)
20 img_y0 += clipping.y - y;
21 if (w > clipping.x2() - x)
22 w = clipping.x2() - x;
23 if (h > clipping.y2() - y)
24 h = clipping.y2() - y;
25 }
26
27 switch (type_) {
28 case IMAGE_TYPE_BINARY: {
29 for (int img_x = img_x0; img_x < w; img_x++) {
30 for (int img_y = img_y0; img_y < h; img_y++) {
31 if (this->get_binary_pixel_(img_x, img_y)) {
32 display->draw_pixel_at(x + img_x, y + img_y, color_on);
33 } else if (!this->transparency_) {
34 display->draw_pixel_at(x + img_x, y + img_y, color_off);
35 }
36 }
37 }
38 break;
39 }
41 for (int img_x = img_x0; img_x < w; img_x++) {
42 for (int img_y = img_y0; img_y < h; img_y++) {
43 const uint32_t pos = (img_x + img_y * this->width_);
44 const uint8_t gray = progmem_read_byte(this->data_start_ + pos);
45 Color color = Color(gray, gray, gray, 0xFF);
46 switch (this->transparency_) {
48 if (gray == 1) {
49 continue; // skip drawing
50 }
51 break;
53 auto on = (float) gray / 255.0f;
54 auto off = 1.0f - on;
55 // blend color_on and color_off
56 color = Color(color_on.r * on + color_off.r * off, color_on.g * on + color_off.g * off,
57 color_on.b * on + color_off.b * off, 0xFF);
58 break;
59 }
60 default:
61 break;
62 }
63 display->draw_pixel_at(x + img_x, y + img_y, color);
64 }
65 }
66 break;
68 for (int img_x = img_x0; img_x < w; img_x++) {
69 for (int img_y = img_y0; img_y < h; img_y++) {
70 auto color = this->get_rgb565_pixel_(img_x, img_y);
71 if (color.w >= 0x80) {
72 display->draw_pixel_at(x + img_x, y + img_y, color);
73 }
74 }
75 }
76 break;
77 case IMAGE_TYPE_RGB:
78 for (int img_x = img_x0; img_x < w; img_x++) {
79 for (int img_y = img_y0; img_y < h; img_y++) {
80 auto color = this->get_rgb_pixel_(img_x, img_y);
81 if (color.w >= 0x80) {
82 display->draw_pixel_at(x + img_x, y + img_y, color);
83 }
84 }
85 }
86 break;
87 }
88}
89Color Image::get_pixel(int x, int y, const Color color_on, const Color color_off) const {
90 if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
91 return color_off;
92 switch (this->type_) {
94 if (this->get_binary_pixel_(x, y))
95 return color_on;
96 return color_off;
98 return this->get_grayscale_pixel_(x, y);
100 return this->get_rgb565_pixel_(x, y);
101 case IMAGE_TYPE_RGB:
102 return this->get_rgb_pixel_(x, y);
103 default:
104 return color_off;
105 }
106}
107#ifdef USE_LVGL
108lv_img_dsc_t *Image::get_lv_img_dsc() {
109 // lazily construct lvgl image_dsc.
110 if (this->dsc_.data != this->data_start_) {
111 this->dsc_.data = this->data_start_;
112 this->dsc_.header.always_zero = 0;
113 this->dsc_.header.reserved = 0;
114 this->dsc_.header.w = this->width_;
115 this->dsc_.header.h = this->height_;
116 this->dsc_.data_size = this->get_width_stride() * this->get_height();
117 switch (this->get_type()) {
119 this->dsc_.header.cf = LV_IMG_CF_ALPHA_1BIT;
120 break;
121
123 this->dsc_.header.cf = LV_IMG_CF_ALPHA_8BIT;
124 break;
125
126 case IMAGE_TYPE_RGB:
127#if LV_COLOR_DEPTH == 32
128 switch (this->transparency_) {
130 this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
131 break;
133 this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
134 break;
135 default:
136 this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR;
137 break;
138 }
139#else
140 this->dsc_.header.cf =
141 this->transparency_ == TRANSPARENCY_ALPHA_CHANNEL ? LV_IMG_CF_RGBA8888 : LV_IMG_CF_RGB888;
142#endif
143 break;
144
146#if LV_COLOR_DEPTH == 16
147 switch (this->transparency_) {
149 this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
150 break;
152 this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
153 break;
154 default:
155 this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR;
156 break;
157 }
158#else
159 this->dsc_.header.cf =
160 this->transparency_ == TRANSPARENCY_ALPHA_CHANNEL ? LV_IMG_CF_RGB565A8 : LV_IMG_CF_RGB565;
161#endif
162 break;
163 }
164 }
165 return &this->dsc_;
166}
167#endif // USE_LVGL
168
169bool Image::get_binary_pixel_(int x, int y) const {
170 const uint32_t width_8 = ((this->width_ + 7u) / 8u) * 8u;
171 const uint32_t pos = x + y * width_8;
172 return progmem_read_byte(this->data_start_ + (pos / 8u)) & (0x80 >> (pos % 8u));
173}
175 const uint32_t pos = (x + y * this->width_) * this->bpp_ / 8;
176 Color color = Color(progmem_read_byte(this->data_start_ + pos + 0), progmem_read_byte(this->data_start_ + pos + 1),
177 progmem_read_byte(this->data_start_ + pos + 2), 0xFF);
178
179 switch (this->transparency_) {
181 if (color.g == 1 && color.r == 0 && color.b == 0) {
182 // (0, 1, 0) has been defined as transparent color for non-alpha images.
183 color.w = 0;
184 }
185 break;
187 color.w = progmem_read_byte(this->data_start_ + (pos + 3));
188 break;
189 default:
190 break;
191 }
192 return color;
193}
195 const uint8_t *pos = this->data_start_ + (x + y * this->width_) * this->bpp_ / 8;
196 uint16_t rgb565 = encode_uint16(progmem_read_byte(pos), progmem_read_byte(pos + 1));
197 auto r = (rgb565 & 0xF800) >> 11;
198 auto g = (rgb565 & 0x07E0) >> 5;
199 auto b = rgb565 & 0x001F;
200 auto a = 0xFF;
201 switch (this->transparency_) {
203 a = progmem_read_byte(pos + 2);
204 break;
206 if (rgb565 == 0x0020)
207 a = 0;
208 break;
209 default:
210 break;
211 }
212 return Color((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2), a);
213}
214
216 const uint32_t pos = (x + y * this->width_);
217 const uint8_t gray = progmem_read_byte(this->data_start_ + pos);
218 switch (this->transparency_) {
220 if (gray == 1)
221 return Color(0, 0, 0, 0);
222 return Color(gray, gray, gray, 0xFF);
224 return Color(0, 0, 0, gray);
225 default:
226 return Color(gray, gray, gray, 0xFF);
227 }
228}
229int Image::get_width() const { return this->width_; }
230int Image::get_height() const { return this->height_; }
231ImageType Image::get_type() const { return this->type_; }
232Image::Image(const uint8_t *data_start, int width, int height, ImageType type, Transparency transparency)
233 : width_(width), height_(height), type_(type), data_start_(data_start), transparency_(transparency) {
234 switch (this->type_) {
236 this->bpp_ = 1;
237 break;
239 this->bpp_ = 8;
240 break;
242 this->bpp_ = transparency == TRANSPARENCY_ALPHA_CHANNEL ? 24 : 16;
243 break;
244 case IMAGE_TYPE_RGB:
245 this->bpp_ = this->transparency_ == TRANSPARENCY_ALPHA_CHANNEL ? 32 : 24;
246 break;
247 }
248}
249
250} // namespace image
251} // namespace esphome
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:336
Rect get_clipping() const
Get the current the clipping rectangle.
Definition display.cpp:715
Color get_rgb565_pixel_(int x, int y) const
Definition image.cpp:194
const uint8_t * data_start_
Definition image.h:55
Color get_rgb_pixel_(int x, int y) const
Definition image.cpp:174
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:38
Image(const uint8_t *data_start, int width, int height, ImageType type, Transparency transparency)
Definition image.cpp:232
Color get_pixel(int x, int y, Color color_on=display::COLOR_ON, Color color_off=display::COLOR_OFF) const
Definition image.cpp:89
ImageType type_
Definition image.h:54
int get_height() const override
Definition image.cpp:230
ImageType get_type() const
Definition image.cpp:231
bool get_binary_pixel_(int x, int y) const
Definition image.cpp:169
lv_img_dsc_t * get_lv_img_dsc()
Definition image.cpp:108
Transparency transparency_
Definition image.h:56
lv_img_dsc_t dsc_
Definition image.h:60
void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override
Definition image.cpp:9
int get_width() const override
Definition image.cpp:229
Color get_grayscale_pixel_(int x, int y) const
Definition image.cpp:215
uint16_t type
@ TRANSPARENCY_ALPHA_CHANNEL
Definition image.h:22
@ TRANSPARENCY_CHROMA_KEY
Definition image.h:21
@ IMAGE_TYPE_GRAYSCALE
Definition image.h:14
@ IMAGE_TYPE_BINARY
Definition image.h:13
@ IMAGE_TYPE_RGB565
Definition image.h:16
@ IMAGE_TYPE_RGB
Definition image.h:15
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
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:394
uint8_t progmem_read_byte(const uint8_t *addr)
Definition core.cpp:70
uint8_t w
Definition color.h:42
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