Display image from buffer on RGB666 display connected to ESP32 board?
As of now, I download an image (converted from jpeg to binary format using lvgl_img_conv’s clit.ts feature) from a http server into a buffer object, then save the buffer object to a file on the SPIFFs system, and then load the image from the SPIFFs system. That works perfectly fine, except that it takes about 15 seconds or so after the SPIFFs file is created to load the image onto the RGB565 display using LVGL. I’m trying to replicate the same result by directly uploading the image from the buffer object, hoping to reduce overall time to display.
Code to reproduce
void http_get(char *file){
int cum_data_read = 0;
int i = 1, j = 1;
int resp_length;
char *output_buffer = (char *)calloc(sizeof(char), MAX_HTTP_OUTPUT_BUFFER); //MAX_HTTP_OUTPUT_BUFFER defined as 2048
char uri[256];
snprintf(uri, sizeof(uri), "%s://%s:%s/esp?file=%s", httpServer, httpIpAddress, httpPort, file);
esp_http_client_config_t config = {
.url = uri
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_err_t err = ESP_OK;
// GET Request
esp_http_client_set_method(client, HTTP_METHOD_GET);
do {
esp_err_t err = esp_http_client_open(client, 0);
if (err != ESP_OK){
j++;
} else {
break;
}
}
while (j<=5);
if (j > 5){
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
} else {
int content_length = esp_http_client_fetch_headers(client);
uint8_t *image_buffer = (uint8_t *)calloc(content_length, sizeof(uint8_t));
if (content_length < 0) {
ESP_LOGE(TAG, "HTTP client fetch headers failed");
} else {
do {
resp_length = esp_http_client_read_response(client, output_buffer, MAX_HTTP_OUTPUT_BUFFER);
if (resp_length >= 0) {
memcpy(image_buffer + cum_data_read, output_buffer, resp_length);
cum_data_read += resp_length;
} else {
ESP_LOGE(TAG, "Failed to read response");
}
i++;
}
while (cum_data_read < content_length);
create_file_app(file, image_buffer, cum_data_read); //This function creates image file on SPIFFs system as expected
free(image_buffer);
xEventGroupSetBits(main_event_group, FILE_DOWNLOAD_COMPLETE_BIT);
display_img(file);
}
}
esp_http_client_close(client);
}
void display_img(char *file){
char filename[256];
snprintf(filename, sizeof(filename), "A:/spiffs/%s",file);
lv_obj_t *img1 = lv_img_create(lv_scr_act());
lv_img_set_src(img1, filename);
// Lock the mutex due to the LVGL APIs are not thread-safe
if (lvgl_port_lock(-1)) {
lvgl_port_unlock();
}
}
So far, this works well. What I’m trying to do is load image directly from the buffer instead of first saving it to a file on SPIFFs and then loading the file from SPIFFs. To do that, here’s what I’ve got:
void http_get(char *file){
int cum_data_read = 0;
int i = 1, j = 1;
int resp_length;
char *output_buffer = (char *)calloc(sizeof(char), MAX_HTTP_OUTPUT_BUFFER); //MAX_HTTP_OUTPUT_BUFFER defined as 2048
char uri[256];
snprintf(uri, sizeof(uri), "%s://%s:%s/esp?file=%s", httpServer, httpIpAddress, httpPort, file);
esp_http_client_config_t config = {
.url = uri
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_err_t err = ESP_OK;
// GET Request
esp_http_client_set_method(client, HTTP_METHOD_GET);
do {
esp_err_t err = esp_http_client_open(client, 0);
if (err != ESP_OK){
j++;
} else {
break;
}
}
while (j<=5);
if (j > 5){
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
} else {
int content_length = esp_http_client_fetch_headers(client);
uint8_t *image_buffer = (uint8_t *)calloc(content_length, sizeof(uint8_t));
if (content_length < 0) {
ESP_LOGE(TAG, "HTTP client fetch headers failed");
} else {
do {
resp_length = esp_http_client_read_response(client, output_buffer, MAX_HTTP_OUTPUT_BUFFER);
if (resp_length >= 0) {
memcpy(image_buffer + cum_data_read, output_buffer, resp_length);
cum_data_read += resp_length;
} else {
ESP_LOGE(TAG, "Failed to read response");
}
i++;
}
while (cum_data_read < content_length);
xEventGroupSetBits(main_event_group, FILE_DOWNLOAD_COMPLETE_BIT);
display_img(image_buffer);
}
}
esp_http_client_close(client);
}
void display_img(uint8_t *img_buffer){
if (img_buffer == NULL) {
ESP_LOGE(TAG, "Image buffer is NULL");
return; // Exit the function or handle the error accordingly
} else {
ESP_LOGI(TAG, "Image buffer is OK");
}
lv_obj_t *img1 = lv_img_create(lv_scr_act());
lv_img_dsc_t newImg = {
.header.always_zero = 0,
.header.w =480,
.header.h =480,
.data_size = 480 * 480 * 2,
.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,
.data = (const uint8_t *) img_buffer
};
lv_img_set_src(img1, &newImg);
// Lock the mutex due to the LVGL APIs are not thread-safe
if (lvgl_port_lock(-1)) {
lvgl_port_unlock(); // Release the mutex
}
}
Screenshot and/or video
Here’s what I get when trying to load image from buffer
Environment
- ESP32-S3 with Square RGB666 TTL TFT Display - 3.4" 480x480
- **LVGL version 8.4
