esphome 2024.12.3__py3-none-any.whl → 2025.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +16 -3
- esphome/components/adc/__init__.py +17 -11
- esphome/components/adc/adc_sensor.h +17 -0
- esphome/components/adc/adc_sensor_common.cpp +55 -0
- esphome/components/adc/adc_sensor_esp32.cpp +8 -5
- esphome/components/adc/adc_sensor_esp8266.cpp +10 -6
- esphome/components/adc/adc_sensor_libretiny.cpp +11 -6
- esphome/components/adc/adc_sensor_rp2040.cpp +13 -10
- esphome/components/adc/sensor.py +9 -3
- esphome/components/ads1115/ads1115.cpp +56 -7
- esphome/components/ads1115/ads1115.h +13 -1
- esphome/components/ads1115/sensor/__init__.py +16 -0
- esphome/components/ads1115/sensor/ads1115_sensor.cpp +2 -1
- esphome/components/ads1115/sensor/ads1115_sensor.h +2 -0
- esphome/components/animation/__init__.py +23 -261
- esphome/components/animation/animation.cpp +2 -2
- esphome/components/animation/animation.h +2 -1
- esphome/components/api/api_pb2.cpp +14 -0
- esphome/components/api/api_pb2.h +1 -0
- esphome/components/api/client.py +8 -3
- esphome/components/audio/__init__.py +112 -0
- esphome/components/audio/audio.cpp +67 -0
- esphome/components/audio/audio.h +125 -7
- esphome/components/audio/audio_decoder.cpp +361 -0
- esphome/components/audio/audio_decoder.h +135 -0
- esphome/components/audio/audio_reader.cpp +308 -0
- esphome/components/audio/audio_reader.h +85 -0
- esphome/components/audio/audio_resampler.cpp +159 -0
- esphome/components/audio/audio_resampler.h +101 -0
- esphome/components/audio/audio_transfer_buffer.cpp +165 -0
- esphome/components/audio/audio_transfer_buffer.h +139 -0
- esphome/components/audio_adc/__init__.py +41 -0
- esphome/components/audio_adc/audio_adc.h +17 -0
- esphome/components/audio_adc/automation.h +23 -0
- esphome/components/bk72xx/__init__.py +1 -0
- esphome/components/ble_client/ble_client.cpp +1 -2
- esphome/components/ble_client/sensor/__init__.py +1 -1
- esphome/components/ble_client/text_sensor/__init__.py +1 -1
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +5 -0
- esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -0
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +5 -0
- esphome/components/ch422g/ch422g.h +2 -0
- esphome/components/climate/__init__.py +1 -1
- esphome/components/climate_ir/climate_ir.cpp +2 -1
- esphome/components/coolix/coolix.cpp +2 -1
- esphome/components/cse7766/cse7766.cpp +8 -16
- esphome/components/custom/__init__.py +0 -3
- esphome/components/custom/binary_sensor/__init__.py +2 -28
- esphome/components/custom/climate/__init__.py +2 -27
- esphome/components/custom/cover/__init__.py +2 -27
- esphome/components/custom/light/__init__.py +2 -27
- esphome/components/custom/output/__init__.py +2 -58
- esphome/components/custom/sensor/__init__.py +2 -24
- esphome/components/custom/switch/__init__.py +2 -24
- esphome/components/custom/text_sensor/__init__.py +2 -29
- esphome/components/custom_component/__init__.py +3 -27
- esphome/components/daly_bms/daly_bms.cpp +6 -0
- esphome/components/daly_bms/daly_bms.h +2 -0
- esphome/components/daly_bms/sensor.py +6 -0
- esphome/components/debug/debug_component.cpp +4 -0
- esphome/components/debug/debug_component.h +14 -0
- esphome/components/debug/debug_esp32.cpp +154 -74
- esphome/components/dfplayer/dfplayer.cpp +15 -2
- esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp +2 -1
- esphome/components/dht/dht.cpp +4 -2
- esphome/components/dht/sensor.py +1 -1
- esphome/components/display/__init__.py +18 -5
- esphome/components/display/display.cpp +16 -3
- esphome/components/display/rect.cpp +2 -1
- esphome/components/es7210/__init__.py +0 -0
- esphome/components/es7210/audio_adc.py +51 -0
- esphome/components/es7210/es7210.cpp +228 -0
- esphome/components/es7210/es7210.h +62 -0
- esphome/components/es7210/es7210_const.h +129 -0
- esphome/components/es7243e/__init__.py +0 -0
- esphome/components/es7243e/audio_adc.py +34 -0
- esphome/components/es7243e/es7243e.cpp +125 -0
- esphome/components/es7243e/es7243e.h +37 -0
- esphome/components/es7243e/es7243e_const.h +54 -0
- esphome/components/es8156/__init__.py +0 -0
- esphome/components/es8156/audio_dac.py +27 -0
- esphome/components/es8156/es8156.cpp +87 -0
- esphome/components/es8156/es8156.h +51 -0
- esphome/components/es8156/es8156_const.h +68 -0
- esphome/components/es8311/audio_dac.py +1 -2
- esphome/components/esp32/__init__.py +1 -0
- esphome/components/esp32/core.cpp +5 -1
- esphome/components/esp32/gpio.h +2 -0
- esphome/components/esp32_ble/__init__.py +39 -0
- esphome/components/esp32_ble/queue.h +4 -4
- esphome/components/esp32_ble_client/ble_client_base.cpp +46 -0
- esphome/components/esp32_ble_client/ble_client_base.h +2 -0
- esphome/components/esp32_ble_server/__init__.py +582 -12
- esphome/components/esp32_ble_server/ble_characteristic.cpp +48 -60
- esphome/components/esp32_ble_server/ble_characteristic.h +24 -17
- esphome/components/esp32_ble_server/ble_descriptor.cpp +21 -9
- esphome/components/esp32_ble_server/ble_descriptor.h +17 -6
- esphome/components/esp32_ble_server/ble_server.cpp +62 -67
- esphome/components/esp32_ble_server/ble_server.h +28 -32
- esphome/components/esp32_ble_server/ble_server_automations.cpp +77 -0
- esphome/components/esp32_ble_server/ble_server_automations.h +115 -0
- esphome/components/esp32_ble_server/ble_service.cpp +17 -15
- esphome/components/esp32_ble_server/ble_service.h +10 -14
- esphome/components/esp32_ble_tracker/__init__.py +6 -39
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +33 -10
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +8 -4
- esphome/components/esp32_dac/esp32_dac.cpp +16 -7
- esphome/components/esp32_dac/esp32_dac.h +8 -0
- esphome/components/esp32_dac/output.py +16 -4
- esphome/components/esp32_improv/__init__.py +2 -8
- esphome/components/esp32_improv/esp32_improv_component.cpp +21 -20
- esphome/components/esp32_improv/esp32_improv_component.h +3 -4
- esphome/components/esp32_rmt/__init__.py +28 -3
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +73 -6
- esphome/components/esp32_rmt_led_strip/led_strip.h +21 -3
- esphome/components/esp32_rmt_led_strip/light.py +72 -7
- esphome/components/esp32_touch/esp32_touch.cpp +5 -0
- esphome/components/esp8266/__init__.py +1 -0
- esphome/components/esp8266/gpio.h +1 -0
- esphome/components/ethernet/__init__.py +10 -10
- esphome/components/event/event.cpp +4 -2
- esphome/components/event/event.h +2 -0
- esphome/components/event_emitter/__init__.py +5 -0
- esphome/components/event_emitter/event_emitter.cpp +14 -0
- esphome/components/event_emitter/event_emitter.h +63 -0
- esphome/components/font/__init__.py +1 -1
- esphome/components/gcja5/gcja5.cpp +2 -1
- esphome/components/graph/graph.cpp +4 -9
- esphome/components/haier/haier_base.cpp +2 -1
- esphome/components/haier/hon_climate.cpp +2 -1
- esphome/components/heatpumpir/heatpumpir.cpp +2 -1
- esphome/components/host/__init__.py +1 -0
- esphome/components/host/gpio.h +1 -0
- esphome/components/http_request/http_request.h +2 -2
- esphome/components/http_request/http_request_arduino.cpp +1 -1
- esphome/components/http_request/http_request_idf.cpp +1 -1
- esphome/components/i2c/i2c_bus_esp_idf.cpp +4 -0
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +7 -5
- esphome/components/i2s_audio/speaker/__init__.py +53 -6
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +92 -46
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -0
- esphome/components/ili9xxx/display.py +29 -11
- esphome/components/ili9xxx/ili9xxx_display.cpp +2 -5
- esphome/components/ili9xxx/ili9xxx_display.h +2 -1
- esphome/components/image/__init__.py +443 -255
- esphome/components/image/image.cpp +115 -61
- esphome/components/image/image.h +15 -24
- esphome/components/json/json_util.cpp +8 -34
- esphome/components/libretiny/__init__.py +1 -0
- esphome/components/libretiny/gpio_arduino.h +1 -0
- esphome/components/light/light_color_values.h +1 -1
- esphome/components/logger/__init__.py +45 -9
- esphome/components/logger/logger.cpp +16 -14
- esphome/components/logger/logger.h +11 -7
- esphome/components/logger/select/__init__.py +29 -0
- esphome/components/logger/select/logger_level_select.cpp +27 -0
- esphome/components/logger/select/logger_level_select.h +15 -0
- esphome/components/lvgl/__init__.py +96 -73
- esphome/components/lvgl/automation.py +39 -7
- esphome/components/lvgl/defines.py +8 -2
- esphome/components/lvgl/lvgl_esphome.cpp +8 -15
- esphome/components/lvgl/lvgl_esphome.h +20 -5
- esphome/components/lvgl/schemas.py +25 -14
- esphome/components/lvgl/trigger.py +27 -3
- esphome/components/lvgl/widgets/dropdown.py +1 -1
- esphome/components/lvgl/widgets/keyboard.py +8 -1
- esphome/components/lvgl/widgets/meter.py +2 -1
- esphome/components/lvgl/widgets/msgbox.py +1 -1
- esphome/components/lvgl/widgets/obj.py +1 -12
- esphome/components/lvgl/widgets/page.py +37 -2
- esphome/components/lvgl/widgets/tabview.py +1 -1
- esphome/components/max6956/max6956.h +2 -0
- esphome/components/mcp23016/mcp23016.h +2 -0
- esphome/components/mcp23xxx_base/mcp23xxx_base.h +2 -0
- esphome/components/mdns/__init__.py +1 -1
- esphome/components/media_player/__init__.py +37 -8
- esphome/components/media_player/automation.h +11 -2
- esphome/components/media_player/media_player.cpp +8 -0
- esphome/components/media_player/media_player.h +8 -4
- esphome/components/micronova/switch/micronova_switch.cpp +4 -2
- esphome/components/midea/ac_automations.h +3 -1
- esphome/components/midea/air_conditioner.cpp +7 -5
- esphome/components/midea/air_conditioner.h +1 -1
- esphome/components/midea/climate.py +4 -2
- esphome/components/midea/ir_transmitter.h +36 -5
- esphome/components/mixer/__init__.py +0 -0
- esphome/components/mixer/speaker/__init__.py +172 -0
- esphome/components/mixer/speaker/automation.h +19 -0
- esphome/components/mixer/speaker/mixer_speaker.cpp +624 -0
- esphome/components/mixer/speaker/mixer_speaker.h +207 -0
- esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp +7 -13
- esphome/components/mpr121/mpr121.h +2 -0
- esphome/components/mqtt/__init__.py +1 -1
- esphome/components/mqtt/mqtt_client.cpp +7 -1
- esphome/components/mqtt/mqtt_client.h +1 -1
- esphome/components/mqtt/mqtt_climate.cpp +2 -2
- esphome/components/network/ip_address.h +2 -0
- esphome/components/nextion/automation.h +17 -0
- esphome/components/nextion/display.py +42 -17
- esphome/components/nextion/nextion.cpp +4 -10
- esphome/components/nextion/nextion.h +89 -82
- esphome/components/nextion/nextion_commands.cpp +10 -10
- esphome/components/ntc/sensor.py +2 -4
- esphome/components/online_image/__init__.py +98 -46
- esphome/components/online_image/bmp_image.cpp +101 -0
- esphome/components/online_image/bmp_image.h +40 -0
- esphome/components/online_image/image_decoder.cpp +31 -2
- esphome/components/online_image/image_decoder.h +24 -15
- esphome/components/online_image/jpeg_image.cpp +92 -0
- esphome/components/online_image/jpeg_image.h +34 -0
- esphome/components/online_image/online_image.cpp +118 -58
- esphome/components/online_image/online_image.h +39 -9
- esphome/components/online_image/png_image.cpp +7 -3
- esphome/components/online_image/png_image.h +2 -1
- esphome/components/opentherm/__init__.py +73 -7
- esphome/components/opentherm/automation.h +25 -0
- esphome/components/opentherm/const.py +1 -0
- esphome/components/opentherm/generate.py +39 -6
- esphome/components/opentherm/hub.cpp +117 -79
- esphome/components/opentherm/hub.h +31 -15
- esphome/components/opentherm/opentherm.cpp +47 -23
- esphome/components/opentherm/opentherm.h +27 -6
- esphome/components/opentherm/opentherm_macros.h +11 -0
- esphome/components/opentherm/schema.py +78 -1
- esphome/components/opentherm/validate.py +7 -2
- esphome/components/pca6416a/pca6416a.h +2 -0
- esphome/components/pca9554/pca9554.h +2 -0
- esphome/components/pcf8574/pcf8574.h +2 -0
- esphome/components/preferences/__init__.py +2 -4
- esphome/components/preferences/syncer.h +10 -3
- esphome/components/prometheus/prometheus_handler.cpp +313 -0
- esphome/components/prometheus/prometheus_handler.h +48 -7
- esphome/components/psram/psram.cpp +8 -1
- esphome/components/pulse_counter/pulse_counter_sensor.cpp +14 -9
- esphome/components/pulse_counter/pulse_counter_sensor.h +4 -4
- esphome/components/pulse_meter/pulse_meter_sensor.cpp +2 -0
- esphome/components/qspi_dbi/__init__.py +3 -0
- esphome/components/qspi_dbi/display.py +74 -47
- esphome/components/qspi_dbi/models.py +245 -2
- esphome/components/qspi_dbi/qspi_dbi.cpp +9 -16
- esphome/components/qspi_dbi/qspi_dbi.h +2 -2
- esphome/components/remote_base/__init__.py +77 -25
- esphome/components/remote_base/remote_base.cpp +1 -1
- esphome/components/remote_base/remote_base.h +20 -2
- esphome/components/remote_base/toto_protocol.cpp +100 -0
- esphome/components/remote_base/toto_protocol.h +45 -0
- esphome/components/remote_receiver/__init__.py +55 -10
- esphome/components/remote_receiver/remote_receiver.h +36 -3
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +145 -6
- esphome/components/remote_transmitter/__init__.py +62 -4
- esphome/components/remote_transmitter/remote_transmitter.h +21 -2
- esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +140 -4
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +3 -3
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +3 -3
- esphome/components/resampler/__init__.py +0 -0
- esphome/components/resampler/speaker/__init__.py +103 -0
- esphome/components/resampler/speaker/resampler_speaker.cpp +318 -0
- esphome/components/resampler/speaker/resampler_speaker.h +107 -0
- esphome/components/resistance/resistance_sensor.h +2 -3
- esphome/components/resistance/sensor.py +2 -9
- esphome/components/rotary_encoder/rotary_encoder.cpp +8 -4
- esphome/components/rp2040/__init__.py +1 -0
- esphome/components/rp2040/gpio.h +1 -0
- esphome/components/rtl87xx/__init__.py +2 -0
- esphome/components/scd30/sensor.py +1 -1
- esphome/components/sdl/binary_sensor.py +270 -0
- esphome/components/sdl/sdl_esphome.cpp +16 -0
- esphome/components/sdl/sdl_esphome.h +9 -0
- esphome/components/seeed_mr60bha2/binary_sensor.py +25 -0
- esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +26 -2
- esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +9 -20
- esphome/components/seeed_mr60bha2/sensor.py +9 -1
- esphome/components/sn74hc165/sn74hc165.h +3 -0
- esphome/components/sn74hc595/sn74hc595.h +3 -0
- esphome/components/speaker/__init__.py +5 -4
- esphome/components/speaker/media_player/__init__.py +458 -0
- esphome/components/speaker/media_player/audio_pipeline.cpp +568 -0
- esphome/components/speaker/media_player/audio_pipeline.h +159 -0
- esphome/components/speaker/media_player/automation.h +26 -0
- esphome/components/speaker/media_player/speaker_media_player.cpp +577 -0
- esphome/components/speaker/media_player/speaker_media_player.h +160 -0
- esphome/components/speaker/speaker.h +20 -0
- esphome/components/spi/__init__.py +1 -5
- esphome/components/spi/spi.cpp +7 -1
- esphome/components/spi/spi.h +21 -2
- esphome/components/spi_led_strip/light.py +3 -5
- esphome/components/spi_led_strip/spi_led_strip.cpp +67 -0
- esphome/components/spi_led_strip/spi_led_strip.h +8 -60
- esphome/components/sprinkler/sprinkler.cpp +3 -1
- esphome/components/sx1509/sx1509_gpio_pin.h +2 -0
- esphome/components/tca9555/tca9555.h +2 -0
- esphome/components/toshiba/toshiba.cpp +2 -1
- esphome/components/tuya/light/tuya_light.cpp +4 -2
- esphome/components/uart/uart_component_esp32_arduino.cpp +2 -2
- esphome/components/uart/uart_component_esp_idf.cpp +2 -2
- esphome/components/udp/__init__.py +8 -2
- esphome/components/udp/udp_component.cpp +25 -56
- esphome/components/udp/udp_component.h +3 -0
- esphome/components/uponor_smatrix/sensor/__init__.py +14 -4
- esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +5 -0
- esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.h +1 -0
- esphome/components/uptime/text_sensor/__init__.py +19 -0
- esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +63 -0
- esphome/components/uptime/text_sensor/uptime_text_sensor.h +25 -0
- esphome/components/voice_assistant/voice_assistant.cpp +24 -14
- esphome/components/voice_assistant/voice_assistant.h +8 -0
- esphome/components/waveshare_epaper/display.py +22 -1
- esphome/components/waveshare_epaper/waveshare_213v3.cpp +9 -3
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +1155 -44
- esphome/components/waveshare_epaper/waveshare_epaper.h +208 -7
- esphome/components/web_server/web_server.cpp +28 -6
- esphome/components/weikai/weikai.h +2 -0
- esphome/components/wifi/__init__.py +6 -6
- esphome/components/wifi/wifi_component.cpp +1 -1
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -1
- esphome/components/wireguard/__init__.py +2 -2
- esphome/components/xl9535/xl9535.h +2 -0
- esphome/components/xxtea/__init__.py +3 -0
- esphome/components/xxtea/xxtea.cpp +46 -0
- esphome/components/xxtea/xxtea.h +26 -0
- esphome/components/yashima/yashima.cpp +2 -1
- esphome/config.py +9 -5
- esphome/config_validation.py +55 -17
- esphome/const.py +7 -10
- esphome/core/__init__.py +6 -13
- esphome/core/base_automation.h +1 -0
- esphome/core/config.py +59 -72
- esphome/core/defines.h +9 -1
- esphome/core/gpio.h +7 -0
- esphome/core/helpers.cpp +19 -15
- esphome/core/helpers.h +57 -8
- esphome/core/log.h +9 -7
- esphome/cpp_generator.py +2 -2
- esphome/dashboard/web_server.py +1 -1
- esphome/espota2.py +3 -2
- esphome/loader.py +12 -4
- esphome/log.py +5 -7
- esphome/yaml_util.py +2 -2
- {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/METADATA +14 -9
- {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/RECORD +349 -300
- esphome/components/custom/binary_sensor/custom_binary_sensor.cpp +0 -16
- esphome/components/custom/binary_sensor/custom_binary_sensor.h +0 -26
- esphome/components/custom/climate/custom_climate.h +0 -22
- esphome/components/custom/cover/custom_cover.h +0 -21
- esphome/components/custom/light/custom_light_output.h +0 -24
- esphome/components/custom/output/custom_output.h +0 -37
- esphome/components/custom/sensor/custom_sensor.cpp +0 -16
- esphome/components/custom/sensor/custom_sensor.h +0 -24
- esphome/components/custom/switch/custom_switch.cpp +0 -16
- esphome/components/custom/switch/custom_switch.h +0 -24
- esphome/components/custom/text_sensor/custom_text_sensor.cpp +0 -16
- esphome/components/custom/text_sensor/custom_text_sensor.h +0 -26
- esphome/components/custom_component/custom_component.h +0 -28
- esphome/components/esp32_ble_server/ble_2901.cpp +0 -18
- esphome/components/esp32_ble_server/ble_2901.h +0 -19
- esphome/components/resistance_sampler/__init__.py +0 -6
- esphome/components/resistance_sampler/resistance_sampler.h +0 -10
- esphome/components/uptime/{sensor.py → sensor/__init__.py} +3 -3
- /esphome/components/uptime/{uptime_seconds_sensor.cpp → sensor/uptime_seconds_sensor.cpp} +0 -0
- /esphome/components/uptime/{uptime_seconds_sensor.h → sensor/uptime_seconds_sensor.h} +0 -0
- /esphome/components/uptime/{uptime_timestamp_sensor.cpp → sensor/uptime_timestamp_sensor.cpp} +0 -0
- /esphome/components/uptime/{uptime_timestamp_sensor.h → sensor/uptime_timestamp_sensor.h} +0 -0
- {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/LICENSE +0 -0
- {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/WHEEL +0 -0
- {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/entry_points.txt +0 -0
- {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,15 @@
|
|
1
1
|
#pragma once
|
2
|
-
#include "esphome/core/defines.h"
|
3
2
|
#include "esphome/core/color.h"
|
4
3
|
|
5
4
|
namespace esphome {
|
6
5
|
namespace online_image {
|
7
6
|
|
7
|
+
enum DecodeError : int {
|
8
|
+
DECODE_ERROR_INVALID_TYPE = -1,
|
9
|
+
DECODE_ERROR_UNSUPPORTED_FORMAT = -2,
|
10
|
+
DECODE_ERROR_OUT_OF_MEMORY = -3,
|
11
|
+
};
|
12
|
+
|
8
13
|
class OnlineImage;
|
9
14
|
|
10
15
|
/**
|
@@ -23,9 +28,13 @@ class ImageDecoder {
|
|
23
28
|
/**
|
24
29
|
* @brief Initialize the decoder.
|
25
30
|
*
|
26
|
-
* @param download_size The total number of bytes that need to be
|
31
|
+
* @param download_size The total number of bytes that need to be downloaded for the image.
|
32
|
+
* @return int Returns 0 on success, a {@see DecodeError} value in case of an error.
|
27
33
|
*/
|
28
|
-
virtual
|
34
|
+
virtual int prepare(size_t download_size) {
|
35
|
+
this->download_size_ = download_size;
|
36
|
+
return 0;
|
37
|
+
}
|
29
38
|
|
30
39
|
/**
|
31
40
|
* @brief Decode a part of the image. It will try reading from the buffer.
|
@@ -38,7 +47,7 @@ class ImageDecoder {
|
|
38
47
|
* @return int The amount of bytes read. It can be 0 if the buffer does not have enough content to meaningfully
|
39
48
|
* decode anything, or negative in case of a decoding error.
|
40
49
|
*/
|
41
|
-
virtual int decode(uint8_t *buffer, size_t size);
|
50
|
+
virtual int decode(uint8_t *buffer, size_t size) = 0;
|
42
51
|
|
43
52
|
/**
|
44
53
|
* @brief Request the image to be resized once the actual dimensions are known.
|
@@ -46,11 +55,12 @@ class ImageDecoder {
|
|
46
55
|
*
|
47
56
|
* @param width The image's width.
|
48
57
|
* @param height The image's height.
|
58
|
+
* @return true if the image was resized, false otherwise.
|
49
59
|
*/
|
50
|
-
|
60
|
+
bool set_size(int width, int height);
|
51
61
|
|
52
62
|
/**
|
53
|
-
* @brief
|
63
|
+
* @brief Fill a rectangle on the display_buffer using the defined color.
|
54
64
|
* Will check the given coordinates for out-of-bounds, and clip the rectangle accordingly.
|
55
65
|
* In case of binary displays, the color will be converted to binary as well.
|
56
66
|
* Called by the callback functions, to be able to access the parent Image class.
|
@@ -59,7 +69,7 @@ class ImageDecoder {
|
|
59
69
|
* @param y The top-most coordinate of the rectangle.
|
60
70
|
* @param w The width of the rectangle.
|
61
71
|
* @param h The height of the rectangle.
|
62
|
-
* @param color The color
|
72
|
+
* @param color The fill color
|
63
73
|
*/
|
64
74
|
void draw(int x, int y, int w, int h, const Color &color);
|
65
75
|
|
@@ -67,20 +77,17 @@ class ImageDecoder {
|
|
67
77
|
|
68
78
|
protected:
|
69
79
|
OnlineImage *image_;
|
70
|
-
// Initializing to 1, to ensure it is
|
80
|
+
// Initializing to 1, to ensure it is distinguishable from initial "decoded_bytes_".
|
71
81
|
// Will be overwritten anyway once the download size is known.
|
72
|
-
|
73
|
-
|
82
|
+
size_t download_size_ = 1;
|
83
|
+
size_t decoded_bytes_ = 0;
|
74
84
|
double x_scale_ = 1.0;
|
75
85
|
double y_scale_ = 1.0;
|
76
86
|
};
|
77
87
|
|
78
88
|
class DownloadBuffer {
|
79
89
|
public:
|
80
|
-
DownloadBuffer(size_t size)
|
81
|
-
this->buffer_ = this->allocator_.allocate(size);
|
82
|
-
this->reset();
|
83
|
-
}
|
90
|
+
DownloadBuffer(size_t size);
|
84
91
|
|
85
92
|
virtual ~DownloadBuffer() { this->allocator_.deallocate(this->buffer_, this->size_); }
|
86
93
|
|
@@ -100,8 +107,10 @@ class DownloadBuffer {
|
|
100
107
|
|
101
108
|
void reset() { this->unread_ = 0; }
|
102
109
|
|
110
|
+
size_t resize(size_t size);
|
111
|
+
|
103
112
|
protected:
|
104
|
-
|
113
|
+
RAMAllocator<uint8_t> allocator_{};
|
105
114
|
uint8_t *buffer_;
|
106
115
|
size_t size_;
|
107
116
|
/** Total number of downloaded bytes not yet read. */
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#include "jpeg_image.h"
|
2
|
+
#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT
|
3
|
+
|
4
|
+
#include "esphome/components/display/display_buffer.h"
|
5
|
+
#include "esphome/core/application.h"
|
6
|
+
#include "esphome/core/helpers.h"
|
7
|
+
#include "esphome/core/log.h"
|
8
|
+
|
9
|
+
#include "online_image.h"
|
10
|
+
static const char *const TAG = "online_image.jpeg";
|
11
|
+
|
12
|
+
namespace esphome {
|
13
|
+
namespace online_image {
|
14
|
+
|
15
|
+
/**
|
16
|
+
* @brief Callback method that will be called by the JPEGDEC engine when a chunk
|
17
|
+
* of the image is decoded.
|
18
|
+
*
|
19
|
+
* @param jpeg The JPEGDRAW object, including the context data.
|
20
|
+
*/
|
21
|
+
static int draw_callback(JPEGDRAW *jpeg) {
|
22
|
+
ImageDecoder *decoder = (ImageDecoder *) jpeg->pUser;
|
23
|
+
|
24
|
+
// Some very big images take too long to decode, so feed the watchdog on each callback
|
25
|
+
// to avoid crashing.
|
26
|
+
App.feed_wdt();
|
27
|
+
size_t position = 0;
|
28
|
+
for (size_t y = 0; y < jpeg->iHeight; y++) {
|
29
|
+
for (size_t x = 0; x < jpeg->iWidth; x++) {
|
30
|
+
auto rg = decode_value(jpeg->pPixels[position++]);
|
31
|
+
auto ba = decode_value(jpeg->pPixels[position++]);
|
32
|
+
Color color(rg[1], rg[0], ba[1], ba[0]);
|
33
|
+
|
34
|
+
if (!decoder) {
|
35
|
+
ESP_LOGE(TAG, "Decoder pointer is null!");
|
36
|
+
return 0;
|
37
|
+
}
|
38
|
+
decoder->draw(jpeg->x + x, jpeg->y + y, 1, 1, color);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
return 1;
|
42
|
+
}
|
43
|
+
|
44
|
+
int JpegDecoder::prepare(size_t download_size) {
|
45
|
+
ImageDecoder::prepare(download_size);
|
46
|
+
auto size = this->image_->resize_download_buffer(download_size);
|
47
|
+
if (size < download_size) {
|
48
|
+
ESP_LOGE(TAG, "Download buffer resize failed!");
|
49
|
+
return DECODE_ERROR_OUT_OF_MEMORY;
|
50
|
+
}
|
51
|
+
return 0;
|
52
|
+
}
|
53
|
+
|
54
|
+
int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
|
55
|
+
if (size < this->download_size_) {
|
56
|
+
ESP_LOGV(TAG, "Download not complete. Size: %d/%d", size, this->download_size_);
|
57
|
+
return 0;
|
58
|
+
}
|
59
|
+
|
60
|
+
if (!this->jpeg_.openRAM(buffer, size, draw_callback)) {
|
61
|
+
ESP_LOGE(TAG, "Could not open image for decoding: %d", this->jpeg_.getLastError());
|
62
|
+
return DECODE_ERROR_INVALID_TYPE;
|
63
|
+
}
|
64
|
+
auto jpeg_type = this->jpeg_.getJPEGType();
|
65
|
+
if (jpeg_type == JPEG_MODE_INVALID) {
|
66
|
+
ESP_LOGE(TAG, "Unsupported JPEG image");
|
67
|
+
return DECODE_ERROR_INVALID_TYPE;
|
68
|
+
} else if (jpeg_type == JPEG_MODE_PROGRESSIVE) {
|
69
|
+
ESP_LOGE(TAG, "Progressive JPEG images not supported");
|
70
|
+
return DECODE_ERROR_INVALID_TYPE;
|
71
|
+
}
|
72
|
+
ESP_LOGD(TAG, "Image size: %d x %d, bpp: %d", this->jpeg_.getWidth(), this->jpeg_.getHeight(), this->jpeg_.getBpp());
|
73
|
+
|
74
|
+
this->jpeg_.setUserPointer(this);
|
75
|
+
this->jpeg_.setPixelType(RGB8888);
|
76
|
+
if (!this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight())) {
|
77
|
+
return DECODE_ERROR_OUT_OF_MEMORY;
|
78
|
+
}
|
79
|
+
if (!this->jpeg_.decode(0, 0, 0)) {
|
80
|
+
ESP_LOGE(TAG, "Error while decoding.");
|
81
|
+
this->jpeg_.close();
|
82
|
+
return DECODE_ERROR_UNSUPPORTED_FORMAT;
|
83
|
+
}
|
84
|
+
this->decoded_bytes_ = size;
|
85
|
+
this->jpeg_.close();
|
86
|
+
return size;
|
87
|
+
}
|
88
|
+
|
89
|
+
} // namespace online_image
|
90
|
+
} // namespace esphome
|
91
|
+
|
92
|
+
#endif // USE_ONLINE_IMAGE_JPEG_SUPPORT
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "image_decoder.h"
|
4
|
+
#include "esphome/core/defines.h"
|
5
|
+
#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT
|
6
|
+
#include <JPEGDEC.h>
|
7
|
+
|
8
|
+
namespace esphome {
|
9
|
+
namespace online_image {
|
10
|
+
|
11
|
+
/**
|
12
|
+
* @brief Image decoder specialization for JPEG images.
|
13
|
+
*/
|
14
|
+
class JpegDecoder : public ImageDecoder {
|
15
|
+
public:
|
16
|
+
/**
|
17
|
+
* @brief Construct a new JPEG Decoder object.
|
18
|
+
*
|
19
|
+
* @param display The image to decode the stream into.
|
20
|
+
*/
|
21
|
+
JpegDecoder(OnlineImage *image) : ImageDecoder(image) {}
|
22
|
+
~JpegDecoder() override {}
|
23
|
+
|
24
|
+
int prepare(size_t download_size) override;
|
25
|
+
int HOT decode(uint8_t *buffer, size_t size) override;
|
26
|
+
|
27
|
+
protected:
|
28
|
+
JPEGDEC jpeg_{};
|
29
|
+
};
|
30
|
+
|
31
|
+
} // namespace online_image
|
32
|
+
} // namespace esphome
|
33
|
+
|
34
|
+
#endif // USE_ONLINE_IMAGE_JPEG_SUPPORT
|
@@ -6,6 +6,12 @@ static const char *const TAG = "online_image";
|
|
6
6
|
|
7
7
|
#include "image_decoder.h"
|
8
8
|
|
9
|
+
#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
|
10
|
+
#include "bmp_image.h"
|
11
|
+
#endif
|
12
|
+
#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT
|
13
|
+
#include "jpeg_image.h"
|
14
|
+
#endif
|
9
15
|
#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT
|
10
16
|
#include "png_image.h"
|
11
17
|
#endif
|
@@ -25,10 +31,11 @@ inline bool is_color_on(const Color &color) {
|
|
25
31
|
}
|
26
32
|
|
27
33
|
OnlineImage::OnlineImage(const std::string &url, int width, int height, ImageFormat format, ImageType type,
|
28
|
-
uint32_t download_buffer_size)
|
29
|
-
: Image(nullptr, 0, 0, type),
|
34
|
+
image::Transparency transparency, uint32_t download_buffer_size)
|
35
|
+
: Image(nullptr, 0, 0, type, transparency),
|
30
36
|
buffer_(nullptr),
|
31
37
|
download_buffer_(download_buffer_size),
|
38
|
+
download_buffer_initial_size_(download_buffer_size),
|
32
39
|
format_(format),
|
33
40
|
fixed_width_(width),
|
34
41
|
fixed_height_(height) {
|
@@ -45,7 +52,7 @@ void OnlineImage::draw(int x, int y, display::Display *display, Color color_on,
|
|
45
52
|
|
46
53
|
void OnlineImage::release() {
|
47
54
|
if (this->buffer_) {
|
48
|
-
|
55
|
+
ESP_LOGV(TAG, "Deallocating old buffer...");
|
49
56
|
this->allocator_.deallocate(this->buffer_, this->get_buffer_size_());
|
50
57
|
this->data_start_ = nullptr;
|
51
58
|
this->buffer_ = nullptr;
|
@@ -57,53 +64,72 @@ void OnlineImage::release() {
|
|
57
64
|
}
|
58
65
|
}
|
59
66
|
|
60
|
-
|
67
|
+
size_t OnlineImage::resize_(int width_in, int height_in) {
|
61
68
|
int width = this->fixed_width_;
|
62
69
|
int height = this->fixed_height_;
|
63
|
-
if (this->
|
70
|
+
if (this->is_auto_resize_()) {
|
64
71
|
width = width_in;
|
65
72
|
height = height_in;
|
66
73
|
if (this->width_ != width && this->height_ != height) {
|
67
74
|
this->release();
|
68
75
|
}
|
69
76
|
}
|
77
|
+
size_t new_size = this->get_buffer_size_(width, height);
|
70
78
|
if (this->buffer_) {
|
71
|
-
|
79
|
+
// Buffer already allocated => no need to resize
|
80
|
+
return new_size;
|
72
81
|
}
|
73
|
-
|
74
|
-
ESP_LOGD(TAG, "Allocating new buffer of %d Bytes...", new_size);
|
75
|
-
delay_microseconds_safe(2000);
|
82
|
+
ESP_LOGD(TAG, "Allocating new buffer of %zu bytes", new_size);
|
76
83
|
this->buffer_ = this->allocator_.allocate(new_size);
|
77
|
-
if (this->buffer_) {
|
78
|
-
|
79
|
-
|
80
|
-
this->width_ = width;
|
81
|
-
ESP_LOGD(TAG, "New size: (%d, %d)", width, height);
|
82
|
-
} else {
|
83
|
-
#if defined(USE_ESP8266)
|
84
|
-
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
85
|
-
int max_block = ESP.getMaxFreeBlockSize();
|
86
|
-
#elif defined(USE_ESP32)
|
87
|
-
int max_block = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
|
88
|
-
#else
|
89
|
-
int max_block = -1;
|
90
|
-
#endif
|
91
|
-
ESP_LOGE(TAG, "allocation failed. Biggest block in heap: %d Bytes", max_block);
|
84
|
+
if (this->buffer_ == nullptr) {
|
85
|
+
ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", new_size,
|
86
|
+
this->allocator_.get_max_free_block_size());
|
92
87
|
this->end_connection_();
|
93
|
-
return
|
88
|
+
return 0;
|
94
89
|
}
|
95
|
-
|
90
|
+
this->buffer_width_ = width;
|
91
|
+
this->buffer_height_ = height;
|
92
|
+
this->width_ = width;
|
93
|
+
ESP_LOGV(TAG, "New size: (%d, %d)", width, height);
|
94
|
+
return new_size;
|
96
95
|
}
|
97
96
|
|
98
97
|
void OnlineImage::update() {
|
99
98
|
if (this->decoder_) {
|
100
99
|
ESP_LOGW(TAG, "Image already being updated.");
|
101
100
|
return;
|
102
|
-
} else {
|
103
|
-
ESP_LOGI(TAG, "Updating image");
|
104
101
|
}
|
102
|
+
ESP_LOGI(TAG, "Updating image %s", this->url_.c_str());
|
103
|
+
|
104
|
+
std::list<http_request::Header> headers = {};
|
105
|
+
|
106
|
+
http_request::Header accept_header;
|
107
|
+
accept_header.name = "Accept";
|
108
|
+
std::string accept_mime_type;
|
109
|
+
switch (this->format_) {
|
110
|
+
#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
|
111
|
+
case ImageFormat::BMP:
|
112
|
+
accept_mime_type = "image/bmp";
|
113
|
+
break;
|
114
|
+
#endif // ONLINE_IMAGE_BMP_SUPPORT
|
115
|
+
#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT
|
116
|
+
case ImageFormat::JPEG:
|
117
|
+
accept_mime_type = "image/jpeg";
|
118
|
+
break;
|
119
|
+
#endif // USE_ONLINE_IMAGE_JPEG_SUPPORT
|
120
|
+
#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT
|
121
|
+
case ImageFormat::PNG:
|
122
|
+
accept_mime_type = "image/png";
|
123
|
+
break;
|
124
|
+
#endif // ONLINE_IMAGE_PNG_SUPPORT
|
125
|
+
default:
|
126
|
+
accept_mime_type = "image/*";
|
127
|
+
}
|
128
|
+
accept_header.value = accept_mime_type + ",*/*;q=0.8";
|
129
|
+
|
130
|
+
headers.push_back(accept_header);
|
105
131
|
|
106
|
-
this->downloader_ = this->parent_->get(this->url_);
|
132
|
+
this->downloader_ = this->parent_->get(this->url_, headers);
|
107
133
|
|
108
134
|
if (this->downloader_ == nullptr) {
|
109
135
|
ESP_LOGE(TAG, "Download failed.");
|
@@ -128,20 +154,39 @@ void OnlineImage::update() {
|
|
128
154
|
ESP_LOGD(TAG, "Starting download");
|
129
155
|
size_t total_size = this->downloader_->content_length;
|
130
156
|
|
157
|
+
#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
|
158
|
+
if (this->format_ == ImageFormat::BMP) {
|
159
|
+
ESP_LOGD(TAG, "Allocating BMP decoder");
|
160
|
+
this->decoder_ = make_unique<BmpDecoder>(this);
|
161
|
+
}
|
162
|
+
#endif // ONLINE_IMAGE_BMP_SUPPORT
|
163
|
+
#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT
|
164
|
+
if (this->format_ == ImageFormat::JPEG) {
|
165
|
+
ESP_LOGD(TAG, "Allocating JPEG decoder");
|
166
|
+
this->decoder_ = esphome::make_unique<JpegDecoder>(this);
|
167
|
+
}
|
168
|
+
#endif // USE_ONLINE_IMAGE_JPEG_SUPPORT
|
131
169
|
#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT
|
132
170
|
if (this->format_ == ImageFormat::PNG) {
|
133
|
-
|
171
|
+
ESP_LOGD(TAG, "Allocating PNG decoder");
|
172
|
+
this->decoder_ = make_unique<PngDecoder>(this);
|
134
173
|
}
|
135
174
|
#endif // ONLINE_IMAGE_PNG_SUPPORT
|
136
175
|
|
137
176
|
if (!this->decoder_) {
|
138
|
-
ESP_LOGE(TAG, "Could not instantiate decoder. Image format unsupported
|
177
|
+
ESP_LOGE(TAG, "Could not instantiate decoder. Image format unsupported: %d", this->format_);
|
139
178
|
this->end_connection_();
|
140
179
|
this->download_error_callback_.call();
|
141
180
|
return;
|
142
181
|
}
|
143
|
-
this->decoder_->prepare(total_size);
|
144
|
-
|
182
|
+
auto prepare_result = this->decoder_->prepare(total_size);
|
183
|
+
if (prepare_result < 0) {
|
184
|
+
this->end_connection_();
|
185
|
+
this->download_error_callback_.call();
|
186
|
+
return;
|
187
|
+
}
|
188
|
+
ESP_LOGI(TAG, "Downloading image (Size: %d)", total_size);
|
189
|
+
this->start_time_ = ::time(nullptr);
|
145
190
|
}
|
146
191
|
|
147
192
|
void OnlineImage::loop() {
|
@@ -150,10 +195,12 @@ void OnlineImage::loop() {
|
|
150
195
|
return;
|
151
196
|
}
|
152
197
|
if (!this->downloader_ || this->decoder_->is_finished()) {
|
153
|
-
ESP_LOGD(TAG, "Image fully downloaded");
|
154
198
|
this->data_start_ = buffer_;
|
155
199
|
this->width_ = buffer_width_;
|
156
200
|
this->height_ = buffer_height_;
|
201
|
+
ESP_LOGD(TAG, "Image fully downloaded, read %zu bytes, width/height = %d/%d", this->downloader_->get_bytes_read(),
|
202
|
+
this->width_, this->height_);
|
203
|
+
ESP_LOGD(TAG, "Total time: %lds", ::time(nullptr) - this->start_time_);
|
157
204
|
this->end_connection_();
|
158
205
|
this->download_finished_callback_.call();
|
159
206
|
return;
|
@@ -164,6 +211,10 @@ void OnlineImage::loop() {
|
|
164
211
|
}
|
165
212
|
size_t available = this->download_buffer_.free_capacity();
|
166
213
|
if (available) {
|
214
|
+
// Some decoders need to fully download the image before downloading.
|
215
|
+
// In case of huge images, don't wait blocking until the whole image has been downloaded,
|
216
|
+
// use smaller chunks
|
217
|
+
available = std::min(available, this->download_buffer_initial_size_);
|
167
218
|
auto len = this->downloader_->read(this->download_buffer_.append(), available);
|
168
219
|
if (len > 0) {
|
169
220
|
this->download_buffer_.write(len);
|
@@ -179,6 +230,19 @@ void OnlineImage::loop() {
|
|
179
230
|
}
|
180
231
|
}
|
181
232
|
|
233
|
+
void OnlineImage::map_chroma_key(Color &color) {
|
234
|
+
if (this->transparency_ == image::TRANSPARENCY_CHROMA_KEY) {
|
235
|
+
if (color.g == 1 && color.r == 0 && color.b == 0) {
|
236
|
+
color.g = 0;
|
237
|
+
}
|
238
|
+
if (color.w < 0x80) {
|
239
|
+
color.r = 0;
|
240
|
+
color.g = this->type_ == ImageType::IMAGE_TYPE_RGB565 ? 4 : 1;
|
241
|
+
color.b = 0;
|
242
|
+
}
|
243
|
+
}
|
244
|
+
}
|
245
|
+
|
182
246
|
void OnlineImage::draw_pixel_(int x, int y, Color color) {
|
183
247
|
if (!this->buffer_) {
|
184
248
|
ESP_LOGE(TAG, "Buffer not allocated!");
|
@@ -192,57 +256,53 @@ void OnlineImage::draw_pixel_(int x, int y, Color color) {
|
|
192
256
|
switch (this->type_) {
|
193
257
|
case ImageType::IMAGE_TYPE_BINARY: {
|
194
258
|
const uint32_t width_8 = ((this->width_ + 7u) / 8u) * 8u;
|
195
|
-
|
196
|
-
|
197
|
-
|
259
|
+
pos = x + y * width_8;
|
260
|
+
auto bitno = 0x80 >> (pos % 8u);
|
261
|
+
pos /= 8u;
|
262
|
+
auto on = is_color_on(color);
|
263
|
+
if (this->has_transparency() && color.w < 0x80)
|
264
|
+
on = false;
|
265
|
+
if (on) {
|
266
|
+
this->buffer_[pos] |= bitno;
|
198
267
|
} else {
|
199
|
-
this->buffer_[pos
|
268
|
+
this->buffer_[pos] &= ~bitno;
|
200
269
|
}
|
201
270
|
break;
|
202
271
|
}
|
203
272
|
case ImageType::IMAGE_TYPE_GRAYSCALE: {
|
204
273
|
uint8_t gray = static_cast<uint8_t>(0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b);
|
205
|
-
if (this->
|
274
|
+
if (this->transparency_ == image::TRANSPARENCY_CHROMA_KEY) {
|
206
275
|
if (gray == 1) {
|
207
276
|
gray = 0;
|
208
277
|
}
|
209
278
|
if (color.w < 0x80) {
|
210
279
|
gray = 1;
|
211
280
|
}
|
281
|
+
} else if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) {
|
282
|
+
if (color.w != 0xFF)
|
283
|
+
gray = color.w;
|
212
284
|
}
|
213
285
|
this->buffer_[pos] = gray;
|
214
286
|
break;
|
215
287
|
}
|
216
288
|
case ImageType::IMAGE_TYPE_RGB565: {
|
289
|
+
this->map_chroma_key(color);
|
217
290
|
uint16_t col565 = display::ColorUtil::color_to_565(color);
|
218
291
|
this->buffer_[pos + 0] = static_cast<uint8_t>((col565 >> 8) & 0xFF);
|
219
292
|
this->buffer_[pos + 1] = static_cast<uint8_t>(col565 & 0xFF);
|
220
|
-
if (this->
|
293
|
+
if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) {
|
221
294
|
this->buffer_[pos + 2] = color.w;
|
295
|
+
}
|
222
296
|
break;
|
223
297
|
}
|
224
|
-
case ImageType::
|
298
|
+
case ImageType::IMAGE_TYPE_RGB: {
|
299
|
+
this->map_chroma_key(color);
|
225
300
|
this->buffer_[pos + 0] = color.r;
|
226
301
|
this->buffer_[pos + 1] = color.g;
|
227
302
|
this->buffer_[pos + 2] = color.b;
|
228
|
-
this->
|
229
|
-
|
230
|
-
}
|
231
|
-
case ImageType::IMAGE_TYPE_RGB24:
|
232
|
-
default: {
|
233
|
-
if (this->has_transparency()) {
|
234
|
-
if (color.b == 1 && color.r == 0 && color.g == 0) {
|
235
|
-
color.b = 0;
|
236
|
-
}
|
237
|
-
if (color.w < 0x80) {
|
238
|
-
color.r = 0;
|
239
|
-
color.g = 0;
|
240
|
-
color.b = 1;
|
241
|
-
}
|
303
|
+
if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) {
|
304
|
+
this->buffer_[pos + 3] = color.w;
|
242
305
|
}
|
243
|
-
this->buffer_[pos + 0] = color.r;
|
244
|
-
this->buffer_[pos + 1] = color.g;
|
245
|
-
this->buffer_[pos + 2] = color.b;
|
246
306
|
break;
|
247
307
|
}
|
248
308
|
}
|
@@ -1,10 +1,10 @@
|
|
1
1
|
#pragma once
|
2
2
|
|
3
|
+
#include "esphome/components/http_request/http_request.h"
|
4
|
+
#include "esphome/components/image/image.h"
|
3
5
|
#include "esphome/core/component.h"
|
4
6
|
#include "esphome/core/defines.h"
|
5
7
|
#include "esphome/core/helpers.h"
|
6
|
-
#include "esphome/components/http_request/http_request.h"
|
7
|
-
#include "esphome/components/image/image.h"
|
8
8
|
|
9
9
|
#include "image_decoder.h"
|
10
10
|
|
@@ -23,10 +23,12 @@ using t_http_codes = enum {
|
|
23
23
|
enum ImageFormat {
|
24
24
|
/** Automatically detect from MIME type. Not supported yet. */
|
25
25
|
AUTO,
|
26
|
-
/** JPEG format.
|
26
|
+
/** JPEG format. */
|
27
27
|
JPEG,
|
28
28
|
/** PNG format. */
|
29
29
|
PNG,
|
30
|
+
/** BMP format. */
|
31
|
+
BMP,
|
30
32
|
};
|
31
33
|
|
32
34
|
/**
|
@@ -48,12 +50,13 @@ class OnlineImage : public PollingComponent,
|
|
48
50
|
* @param buffer_size Size of the buffer used to download the image.
|
49
51
|
*/
|
50
52
|
OnlineImage(const std::string &url, int width, int height, ImageFormat format, image::ImageType type,
|
51
|
-
uint32_t buffer_size);
|
53
|
+
image::Transparency transparency, uint32_t buffer_size);
|
52
54
|
|
53
55
|
void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override;
|
54
56
|
|
55
57
|
void update() override;
|
56
58
|
void loop() override;
|
59
|
+
void map_chroma_key(Color &color);
|
57
60
|
|
58
61
|
/** Set the URL to download the image from. */
|
59
62
|
void set_url(const std::string &url) {
|
@@ -76,23 +79,42 @@ class OnlineImage : public PollingComponent,
|
|
76
79
|
*/
|
77
80
|
void release();
|
78
81
|
|
82
|
+
/**
|
83
|
+
* Resize the download buffer
|
84
|
+
*
|
85
|
+
* @param size The new size for the download buffer.
|
86
|
+
*/
|
87
|
+
size_t resize_download_buffer(size_t size) { return this->download_buffer_.resize(size); }
|
88
|
+
|
79
89
|
void add_on_finished_callback(std::function<void()> &&callback);
|
80
90
|
void add_on_error_callback(std::function<void()> &&callback);
|
81
91
|
|
82
92
|
protected:
|
83
93
|
bool validate_url_(const std::string &url);
|
84
94
|
|
85
|
-
|
86
|
-
Allocator allocator_{Allocator::Flags::ALLOW_FAILURE};
|
95
|
+
RAMAllocator<uint8_t> allocator_{};
|
87
96
|
|
88
97
|
uint32_t get_buffer_size_() const { return get_buffer_size_(this->buffer_width_, this->buffer_height_); }
|
89
98
|
int get_buffer_size_(int width, int height) const { return (this->get_bpp() * width + 7u) / 8u * height; }
|
90
99
|
|
91
100
|
int get_position_(int x, int y) const { return (x + y * this->buffer_width_) * this->get_bpp() / 8; }
|
92
101
|
|
93
|
-
ESPHOME_ALWAYS_INLINE bool
|
102
|
+
ESPHOME_ALWAYS_INLINE bool is_auto_resize_() const { return this->fixed_width_ == 0 || this->fixed_height_ == 0; }
|
94
103
|
|
95
|
-
|
104
|
+
/**
|
105
|
+
* @brief Resize the image buffer to the requested dimensions.
|
106
|
+
*
|
107
|
+
* The buffer will be allocated if not existing.
|
108
|
+
* If the dimensions have been fixed in the yaml config, the buffer will be created
|
109
|
+
* with those dimensions and not resized, even on request.
|
110
|
+
* Otherwise, the old buffer will be deallocated and a new buffer with the requested
|
111
|
+
* allocated
|
112
|
+
*
|
113
|
+
* @param width
|
114
|
+
* @param height
|
115
|
+
* @return 0 if no memory could be allocated, the size of the new buffer otherwise.
|
116
|
+
*/
|
117
|
+
size_t resize_(int width, int height);
|
96
118
|
|
97
119
|
/**
|
98
120
|
* @brief Draw a pixel into the buffer.
|
@@ -117,6 +139,12 @@ class OnlineImage : public PollingComponent,
|
|
117
139
|
|
118
140
|
uint8_t *buffer_;
|
119
141
|
DownloadBuffer download_buffer_;
|
142
|
+
/**
|
143
|
+
* This is the *initial* size of the download buffer, not the current size.
|
144
|
+
* The download buffer can be resized at runtime; the download_buffer_initial_size_
|
145
|
+
* will *not* change even if the download buffer has been resized.
|
146
|
+
*/
|
147
|
+
size_t download_buffer_initial_size_;
|
120
148
|
|
121
149
|
const ImageFormat format_;
|
122
150
|
image::Image *placeholder_{nullptr};
|
@@ -146,7 +174,9 @@ class OnlineImage : public PollingComponent,
|
|
146
174
|
*/
|
147
175
|
int buffer_height_;
|
148
176
|
|
149
|
-
|
177
|
+
time_t start_time_;
|
178
|
+
|
179
|
+
friend bool ImageDecoder::set_size(int width, int height);
|
150
180
|
friend void ImageDecoder::draw(int x, int y, int w, int h, const Color &color);
|
151
181
|
};
|
152
182
|
|
@@ -2,7 +2,6 @@
|
|
2
2
|
#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT
|
3
3
|
|
4
4
|
#include "esphome/components/display/display_buffer.h"
|
5
|
-
#include "esphome/core/application.h"
|
6
5
|
#include "esphome/core/helpers.h"
|
7
6
|
#include "esphome/core/log.h"
|
8
7
|
|
@@ -41,17 +40,22 @@ static void draw_callback(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, ui
|
|
41
40
|
decoder->draw(x, y, w, h, color);
|
42
41
|
}
|
43
42
|
|
44
|
-
|
43
|
+
int PngDecoder::prepare(size_t download_size) {
|
45
44
|
ImageDecoder::prepare(download_size);
|
45
|
+
if (!this->pngle_) {
|
46
|
+
ESP_LOGE(TAG, "PNG decoder engine not initialized!");
|
47
|
+
return DECODE_ERROR_OUT_OF_MEMORY;
|
48
|
+
}
|
46
49
|
pngle_set_user_data(this->pngle_, this);
|
47
50
|
pngle_set_init_callback(this->pngle_, init_callback);
|
48
51
|
pngle_set_draw_callback(this->pngle_, draw_callback);
|
52
|
+
return 0;
|
49
53
|
}
|
50
54
|
|
51
55
|
int HOT PngDecoder::decode(uint8_t *buffer, size_t size) {
|
52
56
|
if (!this->pngle_) {
|
53
57
|
ESP_LOGE(TAG, "PNG decoder engine not initialized!");
|
54
|
-
return
|
58
|
+
return DECODE_ERROR_OUT_OF_MEMORY;
|
55
59
|
}
|
56
60
|
if (size < 256 && size < this->download_size_ - this->decoded_bytes_) {
|
57
61
|
ESP_LOGD(TAG, "Waiting for data");
|
@@ -1,6 +1,7 @@
|
|
1
1
|
#pragma once
|
2
2
|
|
3
3
|
#include "image_decoder.h"
|
4
|
+
#include "esphome/core/defines.h"
|
4
5
|
#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT
|
5
6
|
#include <pngle.h>
|
6
7
|
|
@@ -20,7 +21,7 @@ class PngDecoder : public ImageDecoder {
|
|
20
21
|
PngDecoder(OnlineImage *image) : ImageDecoder(image), pngle_(pngle_new()) {}
|
21
22
|
~PngDecoder() override { pngle_destroy(this->pngle_); }
|
22
23
|
|
23
|
-
|
24
|
+
int prepare(size_t download_size) override;
|
24
25
|
int HOT decode(uint8_t *buffer, size_t size) override;
|
25
26
|
|
26
27
|
protected:
|