mirror of
https://github.com/esphome/esphome.git
synced 2025-01-18 03:55:40 +00:00
[image] Fix mdi images (#8082)
This commit is contained in:
parent
fc2b15e307
commit
c3412df169
@ -82,11 +82,13 @@ class ImageEncoder:
|
||||
self.dither = dither
|
||||
self.index = 0
|
||||
self.invert_alpha = invert_alpha
|
||||
self.path = ""
|
||||
|
||||
def convert(self, image):
|
||||
def convert(self, image, path):
|
||||
"""
|
||||
Convert the image format
|
||||
:param image: Input image
|
||||
:param path: Path to the image file
|
||||
:return: converted image
|
||||
"""
|
||||
return image
|
||||
@ -103,6 +105,16 @@ class ImageEncoder:
|
||||
"""
|
||||
|
||||
|
||||
def is_alpha_only(image: Image):
|
||||
"""
|
||||
Check if an image (assumed to be RGBA) is only alpha
|
||||
"""
|
||||
# Any alpha data?
|
||||
if image.split()[-1].getextrema()[0] == 0xFF:
|
||||
return False
|
||||
return all(b.getextrema()[1] == 0 for b in image.split()[:-1])
|
||||
|
||||
|
||||
class ImageBinary(ImageEncoder):
|
||||
allow_config = {CONF_OPAQUE, CONF_INVERT_ALPHA, CONF_CHROMA_KEY}
|
||||
|
||||
@ -111,7 +123,9 @@ class ImageBinary(ImageEncoder):
|
||||
super().__init__(self.width8, height, transparency, dither, invert_alpha)
|
||||
self.bitno = 0
|
||||
|
||||
def convert(self, image):
|
||||
def convert(self, image, path):
|
||||
if is_alpha_only(image):
|
||||
image = image.split()[-1]
|
||||
return image.convert("1", dither=self.dither)
|
||||
|
||||
def encode(self, pixel):
|
||||
@ -136,7 +150,16 @@ class ImageBinary(ImageEncoder):
|
||||
class ImageGrayscale(ImageEncoder):
|
||||
allow_config = {CONF_ALPHA_CHANNEL, CONF_CHROMA_KEY, CONF_INVERT_ALPHA, CONF_OPAQUE}
|
||||
|
||||
def convert(self, image):
|
||||
def convert(self, image, path):
|
||||
if is_alpha_only(image):
|
||||
if self.transparency != CONF_ALPHA_CHANNEL:
|
||||
_LOGGER.warning(
|
||||
"Grayscale image %s is alpha only, but transparency is set to %s",
|
||||
path,
|
||||
self.transparency,
|
||||
)
|
||||
self.transparency = CONF_ALPHA_CHANNEL
|
||||
image = image.split()[-1]
|
||||
return image.convert("LA")
|
||||
|
||||
def encode(self, pixel):
|
||||
@ -166,7 +189,7 @@ class ImageRGB565(ImageEncoder):
|
||||
invert_alpha,
|
||||
)
|
||||
|
||||
def convert(self, image):
|
||||
def convert(self, image, path):
|
||||
return image.convert("RGBA")
|
||||
|
||||
def encode(self, pixel):
|
||||
@ -204,7 +227,7 @@ class ImageRGB(ImageEncoder):
|
||||
invert_alpha,
|
||||
)
|
||||
|
||||
def convert(self, image):
|
||||
def convert(self, image, path):
|
||||
return image.convert("RGBA")
|
||||
|
||||
def encode(self, pixel):
|
||||
@ -308,7 +331,7 @@ def is_svg_file(file):
|
||||
if not file:
|
||||
return False
|
||||
with open(file, "rb") as f:
|
||||
return "<svg " in str(f.read(1024))
|
||||
return "<svg" in str(f.read(1024))
|
||||
|
||||
|
||||
def validate_cairosvg_installed():
|
||||
@ -548,7 +571,7 @@ async def write_image(config, all_frames=False):
|
||||
encoder = IMAGE_TYPE[type](width, total_rows, transparency, dither, invert_alpha)
|
||||
for frame_index in range(frame_count):
|
||||
image.seek(frame_index)
|
||||
pixels = encoder.convert(image.resize((width, height))).getdata()
|
||||
pixels = encoder.convert(image.resize((width, height)), path).getdata()
|
||||
for row in range(height):
|
||||
for col in range(width):
|
||||
encoder.encode(pixels[row * width + col])
|
||||
@ -557,7 +580,7 @@ async def write_image(config, all_frames=False):
|
||||
rhs = [HexInt(x) for x in encoder.data]
|
||||
prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs)
|
||||
image_type = get_image_type_enum(type)
|
||||
trans_value = get_transparency_enum(transparency)
|
||||
trans_value = get_transparency_enum(encoder.transparency)
|
||||
|
||||
return prog_arr, width, height, image_type, trans_value, frame_count
|
||||
|
||||
|
@ -22,10 +22,27 @@ void Image::draw(int x, int y, display::Display *display, Color color_on, Color
|
||||
case IMAGE_TYPE_GRAYSCALE:
|
||||
for (int img_x = 0; img_x < width_; img_x++) {
|
||||
for (int img_y = 0; img_y < height_; img_y++) {
|
||||
auto color = this->get_grayscale_pixel_(img_x, img_y);
|
||||
if (color.w >= 0x80) {
|
||||
display->draw_pixel_at(x + img_x, y + img_y, color);
|
||||
const uint32_t pos = (img_x + img_y * this->width_);
|
||||
const uint8_t gray = progmem_read_byte(this->data_start_ + pos);
|
||||
Color color = Color(gray, gray, gray, 0xFF);
|
||||
switch (this->transparency_) {
|
||||
case TRANSPARENCY_CHROMA_KEY:
|
||||
if (gray == 1) {
|
||||
continue; // skip drawing
|
||||
}
|
||||
break;
|
||||
case TRANSPARENCY_ALPHA_CHANNEL: {
|
||||
auto on = (float) gray / 255.0f;
|
||||
auto off = 1.0f - on;
|
||||
// blend color_on and color_off
|
||||
color = Color(color_on.r * on + color_off.r * off, color_on.g * on + color_off.g * off,
|
||||
color_on.b * on + color_off.b * off, 0xFF);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
display->draw_pixel_at(x + img_x, y + img_y, color);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -179,8 +196,16 @@ Color Image::get_rgb565_pixel_(int x, int y) const {
|
||||
Color Image::get_grayscale_pixel_(int x, int y) const {
|
||||
const uint32_t pos = (x + y * this->width_);
|
||||
const uint8_t gray = progmem_read_byte(this->data_start_ + pos);
|
||||
uint8_t alpha = (gray == 1 && this->transparency_ == TRANSPARENCY_CHROMA_KEY) ? 0 : 0xFF;
|
||||
return Color(gray, gray, gray, alpha);
|
||||
switch (this->transparency_) {
|
||||
case TRANSPARENCY_CHROMA_KEY:
|
||||
if (gray == 1)
|
||||
return Color(0, 0, 0, 0);
|
||||
return Color(gray, gray, gray, 0xFF);
|
||||
case TRANSPARENCY_ALPHA_CHANNEL:
|
||||
return Color(0, 0, 0, gray);
|
||||
default:
|
||||
return Color(gray, gray, gray, 0xFF);
|
||||
}
|
||||
}
|
||||
int Image::get_width() const { return this->width_; }
|
||||
int Image::get_height() const { return this->height_; }
|
||||
|
Loading…
Reference in New Issue
Block a user