feat(lcd): migrate driver to platform and replace jpg demo with png

This commit is contained in:
admin
2026-02-28 13:34:39 +08:00
parent 46a800c499
commit 8a55ca0005
16 changed files with 1378 additions and 311 deletions

View File

@@ -0,0 +1,113 @@
#include "display_lcd_decode_image.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "esp_check.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "lvgl.h"
#include "png.h"
static const char *TAG = "lcd_png_dec";
extern const uint8_t lcd_demo_png_start[] asm("_binary_lcd_demo_png_start");
extern const uint8_t lcd_demo_png_end[] asm("_binary_lcd_demo_png_end");
static void lcd_fill_err(char *err, size_t err_len, const char *msg)
{
if (err != NULL && err_len > 0) {
snprintf(err, err_len, "%s", msg != NULL ? msg : "unknown");
}
}
esp_err_t platform_lcd_decode_demo_png(uint16_t **out_pixels,
uint16_t *out_width,
uint16_t *out_height,
char *err,
size_t err_len)
{
esp_err_t ret = ESP_OK;
ESP_RETURN_ON_FALSE(out_pixels != NULL && out_width != NULL && out_height != NULL,
ESP_ERR_INVALID_ARG,
TAG,
"invalid output args");
*out_pixels = NULL;
*out_width = 0;
*out_height = 0;
const size_t png_len = (size_t)(lcd_demo_png_end - lcd_demo_png_start);
ESP_RETURN_ON_FALSE(png_len > 0, ESP_ERR_INVALID_SIZE, TAG, "empty png data");
png_image image;
memset(&image, 0, sizeof(image));
image.version = PNG_IMAGE_VERSION;
ESP_RETURN_ON_FALSE(png_image_begin_read_from_memory(&image, lcd_demo_png_start, png_len),
ESP_FAIL,
TAG,
"png header decode failed: %s",
image.message);
ESP_GOTO_ON_FALSE(image.width > 0 && image.height > 0, ESP_ERR_INVALID_SIZE, fail, TAG, "invalid png size");
ESP_GOTO_ON_FALSE(image.width <= UINT16_MAX && image.height <= UINT16_MAX,
ESP_ERR_INVALID_SIZE,
fail,
TAG,
"png dimensions too large");
ESP_GOTO_ON_FALSE(image.width <= SIZE_MAX / image.height, ESP_ERR_INVALID_SIZE, fail, TAG, "png too large");
image.format = PNG_FORMAT_RGB;
png_alloc_size_t rgb_size = PNG_IMAGE_SIZE(image);
ESP_GOTO_ON_FALSE(rgb_size > 0, ESP_ERR_INVALID_SIZE, fail, TAG, "png output size invalid");
uint8_t *rgb = (uint8_t *)heap_caps_malloc((size_t)rgb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
if (rgb == NULL) {
rgb = (uint8_t *)heap_caps_malloc((size_t)rgb_size, MALLOC_CAP_8BIT);
}
ESP_GOTO_ON_FALSE(rgb != NULL, ESP_ERR_NO_MEM, fail, TAG, "alloc rgb buffer failed");
png_alloc_size_t stride = PNG_IMAGE_ROW_STRIDE(image);
if (!png_image_finish_read(&image, NULL, rgb, stride, NULL)) {
const char *png_err = image.message[0] != '\0' ? image.message : "png decode failed";
lcd_fill_err(err, err_len, png_err);
heap_caps_free(rgb);
png_image_free(&image);
return ESP_FAIL;
}
png_image_free(&image);
size_t pixel_count = (size_t)image.width * (size_t)image.height;
uint16_t *pixels = (uint16_t *)heap_caps_malloc(pixel_count * sizeof(uint16_t),
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
if (pixels == NULL) {
pixels = (uint16_t *)heap_caps_malloc(pixel_count * sizeof(uint16_t), MALLOC_CAP_8BIT);
}
if (pixels == NULL) {
lcd_fill_err(err, err_len, "alloc rgb565 buffer failed");
heap_caps_free(rgb);
return ESP_ERR_NO_MEM;
}
for (size_t i = 0; i < pixel_count; ++i) {
const size_t base = i * 3u;
lv_color_t color = lv_color_make(rgb[base], rgb[base + 1u], rgb[base + 2u]);
pixels[i] = (uint16_t)color.full;
}
heap_caps_free(rgb);
*out_pixels = pixels;
*out_width = (uint16_t)image.width;
*out_height = (uint16_t)image.height;
return ESP_OK;
fail:
lcd_fill_err(err, err_len, "invalid png");
png_image_free(&image);
if (ret == ESP_OK) {
ret = ESP_FAIL;
}
return ret;
}