JPG on SPI display not showing

Buonasera, ho creato un progetto in cui volevo far apparire sul mio display tft 480x320 SPI un immagine jpg a tutto schermo, che ho, tramite photoshop, ridimensionato proprio a 480x320 e salvato in jpg. Grazie alla libreria JPEGDecoder pensavo di decomprimere l'immagine e farla visualizzare sul mio schermo, ma tutto cio che si vede è quello che allego nella foto. Qualcuno saprebbe dirmi il motivo? Aggiungo anche il codice che ho caricato sul mio ESP32.

#include <SPI.h>
#include <SD.h>
#include <TFT_eSPI.h>
#include <JPEGDecoder.h>

#define SD_CS      5    // Chip Select per SD
#define DISPLAY_CS 15   // Chip Select per TFT
#define TOUCH_CS   21   // Chip Select per Touch (se presente)

TFT_eSPI tft = TFT_eSPI();

// ============================
// Disattiva tutti i CS
// ============================
void disattivaTuttiCS() {
  digitalWrite(SD_CS, HIGH);
  digitalWrite(DISPLAY_CS, HIGH);
  digitalWrite(TOUCH_CS, HIGH);
}

// ============================
// Setup
// ============================
void setup() {
  Serial.begin(115200);
  delay(500);

  pinMode(SD_CS, OUTPUT);
  pinMode(DISPLAY_CS, OUTPUT);
  pinMode(TOUCH_CS, OUTPUT);
  disattivaTuttiCS();

  tft.begin();

  Serial.println("🔧 Inizializzazione SD...");
  digitalWrite(SD_CS, LOW);

  delay(500);

  if (!SD.begin(SD_CS, tft.getSPIinstance())) {
    Serial.println("❌ Errore: SD non montata!");
    return;
  }

  uint8_t cardType = SD.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("❌ Nessuna SD rilevata.");
    return;
  }

  Serial.print("📀 SD trovata: ");
  switch (cardType) {
    case CARD_MMC:  Serial.println("MMC"); break;
    case CARD_SD:   Serial.println("SDSC"); break;
    case CARD_SDHC: Serial.println("SDHC"); break;
    default:        Serial.println("Sconosciuto"); break;
  }

  Serial.print("📏 Dimensione: ");
  Serial.print(SD.cardSize() / (1024 * 1024));
  Serial.println(" MB");

  tft.setRotation(1);  // landscape
  tft.fillScreen(TFT_BLACK);
}

// ============================
// Loop
// ============================
void loop() {
  mostraJPEG("/masarlogo_sd.jpg", 0, 0);  // Carica solo l'immagine masarlogo.jpg
  delay(3000);  // Rimuovi altre immagini e lascia solo questa
}

// ===================================
// Mostra immagine JPG
// ===================================
void mostraJPEG(const char *filename, int xpos, int ypos) {
  disattivaTuttiCS();
  digitalWrite(SD_CS, LOW);

  File jpegFile = SD.open(filename, FILE_READ);
  if (!jpegFile) {
    Serial.print("❌ Errore apertura file: ");
    Serial.println(filename);
    return;
  }

  Serial.println("===========================");
  Serial.print("📂 Disegno file: "); Serial.println(filename);
  Serial.println("===========================");

  bool decoded = JpegDec.decodeSdFile(jpegFile);
  jpegFile.close();
  digitalWrite(SD_CS, HIGH);
  digitalWrite(DISPLAY_CS, LOW);

  if (decoded) {
    jpegInfo();  // stampa informazioni
    jpegRender(xpos, ypos);
  } else {
    Serial.println("❌ Formato JPEG non supportato.");
  }

  digitalWrite(DISPLAY_CS, HIGH);
  disattivaTuttiCS();
}

// ===================================
// Rendering JPEG
// ===================================
void jpegRender(int xpos, int ypos) {
  uint16_t *pImg;
  uint16_t mcu_w = JpegDec.MCUWidth;
  uint16_t mcu_h = JpegDec.MCUHeight;
  uint32_t max_x = JpegDec.width + xpos;
  uint32_t max_y = JpegDec.height + ypos;
  uint32_t min_w = (JpegDec.width % mcu_w == 0) ? mcu_w : JpegDec.width % mcu_w;
  uint32_t min_h = (JpegDec.height % mcu_h == 0) ? mcu_h : JpegDec.height % mcu_h;
  uint32_t win_w, win_h;

  // Calcola la scala per ridimensionare l'immagine allo schermo
  uint16_t screenWidth = tft.width();
  uint16_t screenHeight = tft.height();
  float scaleX = (float)screenWidth / JpegDec.width;
  float scaleY = (float)screenHeight / JpegDec.height;
  float scale = min(scaleX, scaleY);  // Adatta l'immagine mantenendo il rapporto

  // Ridimensiona l'immagine se è troppo grande
  uint16_t newWidth = JpegDec.width * scale;
  uint16_t newHeight = JpegDec.height * scale;

  if (newWidth > screenWidth) newWidth = screenWidth;
  if (newHeight > screenHeight) newHeight = screenHeight;

  bool swap = tft.getSwapBytes();
  tft.setSwapBytes(true);

  uint32_t drawTime = millis();

  while (JpegDec.read()) {
    pImg = JpegDec.pImage;
    int mcu_x = JpegDec.MCUx * mcu_w + xpos;
    int mcu_y = JpegDec.MCUy * mcu_h + ypos;

    win_w = (mcu_x + mcu_w <= max_x) ? mcu_w : min_w;
    win_h = (mcu_y + mcu_h <= max_y) ? mcu_h : min_h;

    // Adatta i blocchi dell'immagine alla dimensione dello schermo
    if ((mcu_x + win_w <= newWidth) && (mcu_y + win_h <= newHeight)) {
      tft.pushImage(mcu_x, mcu_y, win_w, win_h, pImg);
    } else if ((mcu_y + win_h) >= newHeight) {
      JpegDec.abort();
    }
  }

  tft.setSwapBytes(swap);
  showTime(millis() - drawTime);
}

// ===================================
// Info JPEG
// ===================================
void jpegInfo() {
  Serial.println("📷 JPEG Info");
  Serial.print("📏 Dimensione: "); Serial.print(JpegDec.width); Serial.print(" x "); Serial.println(JpegDec.height);
  Serial.print("🧩 MCU: "); Serial.print(JpegDec.MCUWidth); Serial.print(" x "); Serial.println(JpegDec.MCUHeight);
  Serial.print("🧱 Blocchi per riga: "); Serial.println(JpegDec.MCUSPerRow);
  Serial.print("🧱 Blocchi per colonna: "); Serial.println(JpegDec.MCUSPerCol);
}

// ===================================
// Tempo di rendering
// ===================================
void showTime(uint32_t msTime) {
  Serial.print("⏱️ Disegno completato in ");
  Serial.print(msTime);
  Serial.println(" ms");
}

@masarelectric ,

:warning:
Ti segnalo che, nella sezione in lingua Inglese, si può scrivere SOLO in Inglese ... quindi, per favore, la prossima volta presta più attenzione in quale sezione metti i tuoi post; questa volta esso è stato spostato, da un moderatore della sezione di lingua Inglese, nella sezione di lingua Italiana ... la prossima volta potrebbe venire direttamente eliminato. Grazie.

A quanto detto da PerryBebbington aggiungo ...

... cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO della sezione Italiana del forum, (... e, per evitare future possibili discussioni/incomprensioni, prestando sempre molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE (... quello che vedi in blu è un link, fai click su di esso per raggiungere la discussione) spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

P.P.S.: Evitate di utilizzare la traduzione automatica fatta dal browser ... vi impedisce di capire la lingua della sezione dove andate a scrivere ...