Skip to content

Commit 3067b20

Browse files
authored
Merge pull request #333 from andrewjswan/fix-esphome-2026.4
Fix distorted animated icons on ESPHome 2026.4.0 (#331)
2 parents 7079447 + 977444c commit 3067b20

1 file changed

Lines changed: 16 additions & 2 deletions

File tree

components/ehmtxv2/__init__.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from esphome.const import CONF_BLUE, CONF_GREEN, CONF_RED, CONF_RESIZE, CONF_FILE, CONF_ID, CONF_BRIGHTNESS, CONF_RAW_DATA_ID, CONF_TIME, CONF_TRIGGER_ID
1414
from esphome.core import CORE, HexInt
1515
from esphome.cpp_generator import RawExpression
16-
from esphome.components.image import CONF_ALPHA_CHANNEL, IMAGE_TYPE
16+
from esphome.components.image import CONF_CHROMA_KEY, IMAGE_TYPE
1717

1818
from urllib.parse import urlparse
1919

@@ -484,7 +484,15 @@ def openImageFile(path):
484484
yaml_string += F"\"{conf[CONF_ID]}\","
485485

486486
dither = Image.Dither.NONE
487-
transparency = CONF_ALPHA_CHANNEL
487+
# Use CHROMA_KEY instead of ALPHA_CHANNEL: on ESPHome 2026.4.0 the
488+
# appended-alpha layout is incompatible with Animation frame indexing
489+
# (Animation::update_data_start_ advances by w*h*2 per frame, ignoring
490+
# the alpha block). Chroma-key stores the transparent-pixel marker
491+
# inline (0x0020), so each frame is exactly w*h*2 bytes and the C++
492+
# Animation class can index into it correctly on every ESPHome
493+
# version. 8x8 pixel-art icons use binary transparency anyway —
494+
# fixes issue #331.
495+
transparency = CONF_CHROMA_KEY
488496
invert_alpha = False
489497

490498
total_rows = height * frames
@@ -495,6 +503,12 @@ def openImageFile(path):
495503
dither,
496504
invert_alpha,
497505
)
506+
# ESPHome 2026.4.0 flipped the default RGB565 byte order to little-
507+
# endian, but the C++ Image::get_rgb565_pixel_ decoder still reads
508+
# big-endian. set_big_endian exists on every ESPHome release that
509+
# supports EHMTXv2; no-op on <2026.4.0 where BE was already default.
510+
if hasattr(encoder, "set_big_endian"):
511+
encoder.set_big_endian(True)
498512
for frame_index in range(frames):
499513
image.seek(frame_index)
500514
pixels = encoder.convert(image.resize((width, height)), path).getdata()

0 commit comments

Comments
 (0)