From ecbbf2d3f43e3b85fc02a5152f2ea6a2d35caebc Mon Sep 17 00:00:00 2001 From: Dave T <17680170+davet2001@users.noreply.github.com> Date: Thu, 22 Dec 2022 06:53:53 +0000 Subject: [PATCH] Ili9341 8bit indexed mode pt2 (#2502) --- esphome/components/ili9341/display.py | 66 +++++++++++++++++-- .../components/ili9341/ili9341_display.cpp | 7 +- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/esphome/components/ili9341/display.py b/esphome/components/ili9341/display.py index 3122b45bbe..0b87a0c4eb 100644 --- a/esphome/components/ili9341/display.py +++ b/esphome/components/ili9341/display.py @@ -1,6 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome import pins +from esphome import core, pins from esphome.components import display, spi from esphome.const import ( CONF_COLOR_PALETTE, @@ -12,10 +12,11 @@ from esphome.const import ( CONF_RAW_DATA_ID, CONF_RESET_PIN, ) -from esphome.core import HexInt +from esphome.core import CORE, HexInt DEPENDENCIES = ["spi"] +CONF_COLOR_PALETTE_IMAGES = "color_palette_images" CONF_LED_PIN = "led_pin" ili9341_ns = cg.esphome_ns.namespace("ili9341") @@ -37,7 +38,25 @@ MODELS = { ILI9341_MODEL = cv.enum(MODELS, upper=True, space="_") -COLOR_PALETTE = cv.one_of("NONE", "GRAYSCALE") +COLOR_PALETTE = cv.one_of("NONE", "GRAYSCALE", "IMAGE_ADAPTIVE") + + +def _validate(config): + if config.get(CONF_COLOR_PALETTE) == "IMAGE_ADAPTIVE" and not config.get( + CONF_COLOR_PALETTE_IMAGES + ): + raise cv.Invalid( + "Color palette in IMAGE_ADAPTIVE mode requires at least one 'color_palette_images' entry to generate palette" + ) + if ( + config.get(CONF_COLOR_PALETTE_IMAGES) + and config.get(CONF_COLOR_PALETTE) != "IMAGE_ADAPTIVE" + ): + raise cv.Invalid( + "Providing color palette images requires palette mode to be 'IMAGE_ADAPTIVE'" + ) + return config + CONFIG_SCHEMA = cv.All( display.FULL_DISPLAY_SCHEMA.extend( @@ -48,12 +67,16 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_LED_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_COLOR_PALETTE, default="NONE"): COLOR_PALETTE, + cv.Optional(CONF_COLOR_PALETTE_IMAGES, default=[]): cv.ensure_list( + cv.file_ + ), cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), } ) .extend(cv.polling_component_schema("1s")) .extend(spi.spi_device_schema(False)), cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), + _validate, ) @@ -86,12 +109,45 @@ async def to_code(config): led_pin = await cg.gpio_pin_expression(config[CONF_LED_PIN]) cg.add(var.set_led_pin(led_pin)) + rhs = None if config[CONF_COLOR_PALETTE] == "GRAYSCALE": cg.add(var.set_buffer_color_mode(ILI9341ColorMode.BITS_8_INDEXED)) rhs = [] for x in range(256): rhs.extend([HexInt(x), HexInt(x), HexInt(x)]) + elif config[CONF_COLOR_PALETTE] == "IMAGE_ADAPTIVE": + cg.add(var.set_buffer_color_mode(ILI9341ColorMode.BITS_8_INDEXED)) + from PIL import Image + + def load_image(filename): + path = CORE.relative_config_path(filename) + try: + return Image.open(path) + except Exception as e: + raise core.EsphomeError(f"Could not load image file {path}: {e}") + + # make a wide horizontal combined image. + images = [load_image(x) for x in config[CONF_COLOR_PALETTE_IMAGES]] + total_width = sum(i.width for i in images) + max_height = max(i.height for i in images) + + ref_image = Image.new("RGB", (total_width, max_height)) + x = 0 + for i in images: + ref_image.paste(i, (x, 0)) + x = x + i.width + + # reduce the colors on combined image to 256. + converted = ref_image.convert("P", palette=Image.ADAPTIVE, colors=256) + # if you want to verify how the images look use + # ref_image.save("ref_in.png") + # converted.save("ref_out.png") + palette = converted.getpalette() + assert len(palette) == 256 * 3 + rhs = palette + else: + cg.add(var.set_buffer_color_mode(ILI9341ColorMode.BITS_8)) + + if rhs is not None: prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.add(var.set_palette(prog_arr)) - else: - pass diff --git a/esphome/components/ili9341/ili9341_display.cpp b/esphome/components/ili9341/ili9341_display.cpp index 117de3de89..9f9edcf21f 100644 --- a/esphome/components/ili9341/ili9341_display.cpp +++ b/esphome/components/ili9341/ili9341_display.cpp @@ -122,7 +122,12 @@ void ILI9341Display::display_() { } void ILI9341Display::fill(Color color) { - uint8_t color332 = display::ColorUtil::color_to_332(color, display::ColorOrder::COLOR_ORDER_RGB); + uint8_t color332 = 0; + if (this->buffer_color_mode_ == BITS_8) { + color332 = display::ColorUtil::color_to_332(color); + } else { // if (this->buffer_color_mode_ == BITS_8_INDEXED) + color332 = display::ColorUtil::color_to_index8_palette888(color, this->palette_); + } memset(this->buffer_, color332, this->get_buffer_length_()); this->x_low_ = 0; this->y_low_ = 0;