Image gif jpeg esp32-s3 affichage lent

Bonjour à tous,
Je viens ici solliciter votre aide pour la compréhension de la lenteur d'affichage de mes images sur mon esp32-s3 N16R8

Déjà pour commencer j'i du dwongrade quelque bibliotheque pour enfin avoir une image qui s'affiche mais bon....
Je suis avec un ili9488 spi 3.2" de 320x480.
voici mon code user_setup.h

#define ESP32S3

#define ILI9488_DRIVER

#define TFT_MISO 13
#define TFT_MOSI 11
#define TFT_SCLK 12
#define TFT_CS   10
#define TFT_DC   2
#define TFT_RST  4

#define TFT_WIDTH  320
#define TFT_HEIGHT 480

#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF

#define SMOOTH_FONT

#define SUPPORT_TRANSACTIONS

#define SPI_FREQUENCY       40000000
#define SPI_READ_FREQUENCY  20000000
#define SPI_TOUCH_FREQUENCY 2500000

Ensuite mon code simple ino

#include <TJpg_Decoder.h>
#define FS_NO_GLOBALS
#include <FS.h>
#include "SPIFFS.h"
#include "SPI.h"
#include <TFT_eSPI.h>             
TFT_eSPI tft = TFT_eSPI();

bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap){  
  if ( y >= tft.height() ) return 0;
  tft.pushImage(x, y, w, h, bitmap);
  return 1;
}

void setup()
{
  Serial.begin(115200);
  Serial.println("\n\nTesting TJpg_Decoder library");

  if (!SPIFFS.begin()) {
    Serial.println("SPIFFS initialisation failed!");
    while (1) yield(); 
  }
  Serial.println("\r\nInitialisation done.");

  tft.begin();
  tft.setRotation(1);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.fillScreen(TFT_BLACK);

  TJpgDec.setSwapBytes(true);
  TJpgDec.setJpgScale(1);
  TJpgDec.setCallback(tft_output);

  // Afficher une seule fois l'image
  
}

void loop()
{
 TJpgDec.drawFsJpg(0, 0, "/horizon.jpg");
 delay(2000);
 TJpgDec.drawFsJpg(0, 0, "/aloy.jpg");
 delay(2000);
}

Les images s'affiche bien mais l'affichage n'est pas rapide elles défile de haut en bas en 1.5s environ je trouve ça assez long et peut élégant.

J'ai essayé avec chat GPT, Gemini et écumé pas mal d'info sur le web, mais quand on débute on trouve tout et n'importe quoi et tout ce que lis je ne le comprends pas forcement.
Donc si une personne veut bien me mettre sur la bonne voie je serai bien content !
Merci

Bonjour,
Quelle est la résolution de tes images? Plus les images sont "grandes", plus ça va s'afficher lentement. L'idéal est de les rééchantilloner à la taille de ton écran, 320x480.

Il est conseillé aussi d'utiliser des images BMP, elles ne sont pas compréssé, donc plus rapide à afficher.

En supposant que le SPI fonctionne à une vitesse de 3MHZ (il me semble que c'est un maximum.
Pour un écran de 320x480, il y a donc 153600 pixels à envoyer. Si on est en mode couleurs sur 16 bits (il y a un mode sur 18 bits moins utilisé), il faut deux octets par pixels. Il faut donc envoyer 307200 octets. Pour chaque octet, on envoie un bit de start, 8 bits de donnée en un bit de stop. Il y a donc 3072000 à envoyer. Si l'ESP se débrouille pour que les octets à envoyer soient prêts tout le temps, à 3MHZ, il faut 3072000/3MHz = 1 seconde.
Si tout est au max, il faut au moins 1 seconde pour envoyer une image. Si pendant ce temps il doit faire autre chose, lire la carte SD par exemple (qui est aussi lue en série, donc lentement) il lui faudra un peu plus de temps.

On ne peut pas descendre en dessous de la seconde, seconde et demie.

C'est pour cela que j'ai utilisé un afficheur en mode parallèle 16 bits (envoi de 16 bit à la fois) au lieu du mode SPI (1 bit à la fois).

Mes images je les est faites avec photoshop en 320x480 pour 20ko max
J'ai essayé aussi un autre code avec LittlesFS et activé DMA dans user_setup.h de tft espi
mais j'ai exactement le meme resultat 1.5s pour afficher une image. au cas ou voici le code

#include <TJpg_Decoder.h>
#define FS_NO_GLOBALS
#include <FS.h>
#include <LittleFS.h>
#include "SPI.h"
#include <TFT_eSPI.h>             

TFT_eSPI tft = TFT_eSPI();

bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap) {  
  if (y >= tft.height()) return 0;
  tft.pushImage(x, y, w, h, bitmap);
  return 1;
}

void setup() {
  Serial.begin(115200);
  Serial.println("\n\nTesting TJpg_Decoder library");
  if (!LittleFS.begin(true)) {
    Serial.println("SPIFFS initialisation failed!");
    while (1) yield(); 
  }


  tft.begin();
  tft.setRotation(1);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.fillScreen(TFT_BLACK);

  TJpgDec.setSwapBytes(true);
  TJpgDec.setJpgScale(1); // 1 = plein format
  TJpgDec.setCallback(tft_output);
}

void loop() {
  TJpgDec.drawFsJpg(0, 0, "/horizon.jpg", LittleFS);

  delay(2000);
  TJpgDec.drawFsJpg(0, 0, "/aloy.jpg", LittleFS);

  delay(2000);
}

SInon pour les BMP j'ai pas essayé je vais tenter ça. Mais sinon de voir les images apparaitre de haut en bas tu trouve ça normal ou non ?

Merci pour tes infos Vileroi ! nos message se sont croisés. Je suis dessus de cette réalité !
Cependant j'ai vue des vidéo ou une personne affiche une sorte de diapo de plusieurs images et au click sur sont écran les images change instantanément. Bref peut être y a t il un format une méthode différente pour avoir des images rapide.

Ce qui me fait un peur c'est la perf j'ai pour prjet de piloter plusieurs led environ 15, GPIO + dfminiplayers + ecran. Le but est de jouer un effet lumineux un son et une image gif. les 3 simultanément

Bref je vais voir ce qui est possible !

Je te conseille, d'utiliser un esp32 s3 pour le tft et un autre pour tes leds, servo0, capteurs, etc... et je les fais communiquer avec ESP-NOW.

Moi c'est ce que je fais et mes images (non-compressées) s'affiche rapidement mais j'utilise un tft plus petit (240x320) en SPI et avec la librairie TFT_e SPI de bodmer (c'es la bibliothèque la plus rapide que j'ai trouvé après en avoir essayé plusieurs).

L'affichage d'images prend beaucoup de ressources, je branche rien d'autres que le tft, le tactile et la carte SD.

Pour les leds, je te conseille des ws2812b, tu pourras facilement en piloter 15 ou plus simplement avec 3 fils (un fil pour les datas et deux fils pour l'alimentation).

Salut Axelmaux, 2 esp32 c'est la piste que j'envisage mais ça me plait moyen !
il faut encore que j'essaie d'autre format d'image et que j'explore les fichier hex progem (je crois) mais aussi les gifs. En meme temps je découvre ce merveilleux petit jouer en codant tous et n'importe quoi dessus. Je vais fuiner un peut partout des infos mais si j'arrive à optimisé un truc je posterai l'info !

D'accord :slightly_smiling_face:

Sinon, si tu veux un tft performant, il faut prendre un avec connexions parallèle (comme dit vileroi), mais ça va te prendre beaucoup de broche de ton esp32...

Si tu prends un tft parallèle 16 bits:

  • 21 à 22 utilisés pour le TFT
  • Il resterait donc 8 à 9 GPIOs libres
  • Tu peux descendre à 6–7 GPIOs utiles si tu laisses certains ports réservés à l’USB ou au boot

Si tu ajoutes le tactile et la carte SD, il te restera au mieux entre 3 et 7 broches de libres.

J'ai de bonnes nouvelles !! Finalement, j'ai réussi à afficher une image en 850 ms. Pfiou, c'est déjà mieux que 1.4 s. Cependant, il faut passer par la case des images en .raw.

J'ai développé un script Python qui convertit les images jpg, jpeg et png en .raw. Ce script doit être placé dans le dossier contenant vos images. Avec une ligne de commande, toutes les images sont converties en un rien de temps !!

Personnellement, j'utilise LittleFS pour stocker mes images. On verra par la suite si je mets une carte SD ou non et je ferai d'autres tests de performance.

Le bénéfice est cool car il y a moins de bibliothèques à inclure, le processeur ne travaille pas à la conversion, les données sont envoyées directement à l'écran. Mais le plus cool, c'est la qualité des images : elles sont au top sur l'écran, fidèles aux couleurs et nettes !

Avec les fichiers jpg, pour obtenir les mêmes résultats, je dois beaucoup dégrader l'image avec Photoshop et réduire la qualité à 20 %, ça passe mais ce n'est pas terrible non plus. Si l'on veut la même qualité, il faut enregistrer une image de 300 ko voire plus. Avec les bibliothèques TFT_eSPI et TJpg_Decoder en full qualité jpeg, on est à 1.4 s voire plus en qualité moyenne, tandis qu'en .raw, on arrive à 850 ms.

En conclusion, je dirais qu'avec le format .raw, nous avons le beurre et un peu plus :slight_smile:

Je ferai un zip demain avec tous les fichiers source et les informations. Là tout de suite, j'ai la flemme.

Cool! Tu affiche l'image presque deux fois plus vite :slight_smile:

Voici le dossier complet avec tous les explicatifs dedans !
Vous trouverez un dossier images pour afficher des images jpg, un autre dossier pour afficher des .raw et le dernier en bonus un script pour convertir votre jpg png en raw.
image-rawetjpg-tft-espi.zip (2,2 Mo)

Il y a un goulot d'étranglement quelque part, mais je ne sais pas d'où il vient ! je suis sur que si ou le trouve on pourrai aller encore plus vite.
J'ai augmenté la fréquence à 70Mhz du spi mais le gain est de 50ms grand max. je sais si c tft_espi le buffer par ligne ou simplement mon écran ili9488 chinois qui à une limite de dingue.

Si vous avez des informations et ou des solution pour encore optimiser, n'hésitez pas à me le faire savoir !
Aussi au cas ou pour tft_espi voici mon user_setup.h

#define ESP32S3

#define ILI9488_DRIVER

#define TFT_MISO 13
#define TFT_MOSI 11
#define TFT_SCLK 12
#define TFT_CS   10
#define TFT_DC   2
#define TFT_RST  4

#define TFT_WIDTH  480
#define TFT_HEIGHT 320

#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF

#define SMOOTH_FONT

#define SUPPORT_TRANSACTIONS

#define SPI_FREQUENCY 40000000 
#define SPI_READ_FREQUENCY  20000000

@++ Mike

Je viens de faire un autre test avec un ili9341 là ça change tout !!
Affichage de fichiers RAW RGB565 depuis LittleFS
horizon.raw affiché en 98 ms
aloy.raw affiché en 99 ms

Pfff mon ili9488 est limité sur son spi ou la tft_espi quel dommage.
Allez bonne journée

Bonjour,

  • Si la taille de la mémoire le permet, mettre en cache l'image RAW ou BMP avec la couleur de chaque pixel lors de l'écriture effective du pixel
  • Repérer dans le driver l'écriture vers le LCD et n'attaquer l'écriture effective que si la couleur du pixel est différente de celle du cache

Cette méthode est bien adaptée si les images évoluent sans trop de différences comme dans le cas d'une animation

NB: Méthode que j'utilise sur un ESP32-S3-GEEK pour optimiser le rafraichissement partiel ou total de l'écran de 240×135 pixels 65K couleurs. De plus, associé au maintien et à l'utilisation du cache, je calcule le min, la moyenne, le max et l'écart type du pourcentage du nombre de pixels trouvés dans le cache et n'ayant donc pas fait l'objet d'une écriture effective...

A suivre...

Apparemment LovyanGFX serait une alternative plus puissante et plus rapide que TFT_eSPI mais je n'ai pas encore testé...

LovyanGFX est ultra optimisée pour l'ESP32-S3 et gère très bien les écrans comme l'ILI9488 avec DMA, PSRAM, SPI rapide, etc.

Bonjour,

C'est toujours dommage de ne pas avoir de retour sur des propositions ... souhaitées

C'est à désespérer des contributions que l'on peut apporter à la communauté et à une personne particulière (mike_7762 pour ne pas le citer) ...

Un jour viendra où plus personne ne contribuera et cela sera la n-ième nuit obscure de l'IA ... j'attends avec impatience ce moment

NB: Qu'en pense notre ami axelmaux

A suivre...

Je pense pareil que toi... Souvent (pas toujour) quand un demandeur a reglé son problème, on n'a plus de retour... Sans parler de personnes qui s'inscrivent pour résoudre un problème précis et une fois résolu, on ne les voit plus. Mais heureusement, pour l'instant, il y a un noyau de membres dans la partie francophone du forum qui reste actif.

La fréquence maximum théorique du SPI sur un ESP32-S3 est de 80 MHz.
Je n'ai jamais vu d'exemple d'utilisation du SPI à cette fréquence (sauf pour la phase de flashage, mais c'est une autre fonction).

Par contre j'ai vu très souvent des bibliothèques qui imposent une fréquence de 20 MHz.
Pour moi ce n'est pas à une bibliothèque d'imposer la fréquence, car on peut être amené à devoir utiliser simultanément des composants rapides et des composants lents, mais c'est comme ça.

Pour du graphisme, avec des images un peu lourdes il faut fonctionner à la fréquence la plus élevée possible.

Cette fréquence dépend du CI qui gère l'écran : est-il capable de fonctionner à 20 MHz, à 40 MHz ?
Et aussi de la qualité du câblage.

Première opération à faire : fouiller dans le code de la bibliothèque pour savoir si la fréquence SCK est déjà réglée ou pas.

Ma vision des choses.

Certain → c'est dans la datasheet :
avr à 16 MHz, SCK (SPI) max = 16 MHz / 2 = 8 MHz

Supposé et/ou déduit :
La base : En logique synchrone, la fréquence des datas est au max la moitié de celle de l'horloge, c'est aussi le théorème de Shannon sur l'échantillonnage.

ESP32-double cœur :
H_principale = 320 MHz
Par cœur, H_secondaire = 320/2 = 160 MHz

ESP32 simple cœur :
H_principale = 160 MHz

ESP32 par cœur :
Horloge par "périphérique" (→ GPIO, UART, SPI, I2C, etc ) = 80 MHz.

D'où les 80 MHz annoncés par Espressif.

Bonjour à tous,

Je n’ai pas donné de nouvelles car je n’ai pas vraiment eu le temps de me pencher sur LoyanGFX. Il est vrai que, lorsqu’on obtient des réponses, on ne revient pas toujours sur le forum concerné.
Personnellement, mon projet est assez complexe à mon niveau : j’ai dû faire de nombreux tests sur l’audio, les images, FreeRTOS… et je ne suis pas venu vous solliciter sans raison.

Cela dit, j’ai tout de même partagé mon expérience en fournissant directement mes fichiers. Je ne peux pas non plus travailler régulièrement sur mon petit projet, notamment à cause de mon travail.
Je comprends vos réactions, ainsi que la frustration de partager des informations précieuses sans toujours recevoir de retour ou même un simple merci.

Alors, un grand MERCI à vous tous pour m’avoir aidé à débloquer certaines choses.
Et pour enrichir l’échange et me rattraper, je publierai ici l’ensemble de mon projet afin de partager pleinement mon expérience.

Bonne journée, et à très vite !

Bonjour à tous,

J'ai installé la librairie LovyanGFX et effectivement, elle est beaucoup plus rapide pour l'affichage des images que TFT_eSPI. J'ai eu un peu de mal avec les couleurs à l'écran car j'utilise des fichiers RAW et l'encodage est lu différemment avec LovyanGFX. Voici mon fichier de configuration pour un écran ILI9341, si ça peut aider. Ah oui, mes fichiers RAW sont encodés avec le code Python que j'ai fourni dans le zip du post ci-dessus et affichés avec cette fonction :

void showRawImage(const char* path) {
  File f = LittleFS.open(path, "r");
  if (!f) {
    Serial.println("Impossible d’ouvrir l’image !");
    return;
  }

  tft.startWrite();
  tft.setAddrWindow(0, 0, 240, 320);
  uint16_t buffer[240];  // Une ligne de 240 pixels (480 octets)

  for (int y = 0; y < 320; y++) {
    f.read((uint8_t*)buffer, 240 * 2);  // Lecture directe dans le buffer
    tft.pushImage(0, y, 240, 1, buffer);
  }

  tft.endWrite();
  f.close();
}
#include <LovyanGFX.hpp>

class LGFX : public lgfx::LGFX_Device {
  lgfx::Panel_ILI9341 _panel_instance;
  lgfx::Bus_SPI _bus_instance;

public:
  LGFX(void) {
    { // Bus SPI
      auto cfg = _bus_instance.config();

      cfg.spi_host = SPI2_HOST;  // ESP32-S3 HSPI
      cfg.spi_mode = 0;
      cfg.freq_write = 80000000;
      cfg.freq_read  = 16000000;
      cfg.spi_3wire  = false;
      cfg.use_lock   = true;

      cfg.pin_sclk = 12;
      cfg.pin_mosi = 11;
      cfg.pin_miso = 13;
      cfg.pin_dc   = 2;

      _bus_instance.config(cfg);
      _panel_instance.setBus(&_bus_instance); 
    }

    { // Panel
      auto cfg = _panel_instance.config();

      cfg.pin_cs   = 10;
      cfg.pin_rst  = 4;
      cfg.pin_busy = -1;

      cfg.panel_width  = 240;
      cfg.panel_height = 320;
      cfg.offset_x     = 0;
      cfg.offset_y     = 0;
      cfg.offset_rotation = 0;
      cfg.dummy_read_pixel = 8;
      cfg.dummy_read_bits  = 1;
      cfg.readable      = true;
      cfg.invert        = false;
      cfg.rgb_order     = false;
      cfg.dlen_16bit    = false;
      cfg.bus_shared    = true;

      _panel_instance.config(cfg);
    }

    setPanel(&_panel_instance);
  }
};

J'ai commandé un autre écran avec une dalle IPS, ça sera plus joli pour les couleurs et avec un meilleur angle de vue. Je ferai des photos quand je l'aurai reçu d'ici 10 jours au moins. La prochaine étape sera d'essayer de mettre un GIF pour voir si le rendu est potable ou pas :slight_smile:

Bonne journée !