Go Down

Topic: 3.5 SPI Display problem of displaying Jpeg images (Read 470 times) previous topic - next topic

david_prentice

I have amended the sketch for conditional ESP32 / ESP8266 SPIFFS methods
Tested on ESP32 v1.0.2 and ESP8266 v2.4.2

ESP8266 v2.5.0 builds but is SLOW
ESP8266 v2.5.1 does not compile any TFT_eSPI examples

Please can you try it on your ESP32.

There is conditional code for rendering individual JPEG tile.
I have fixed the odd-width tile display.   Look at betty_8.jpg or bapa.jpg

David.

ketineni

Looks like am at these versions as per Board manager, should I update them, did not want to break stuff.

Esp8266  2.4.2
Esp32 on 1.0.1

Test output  ESP32 / 3.5 Inch SPI display  320x480


⸮ ⸮,$C⸮*⸮P⸮⸮⸮⸮M⸮NodeMCU decoder test!

Initialisation done.

SPIFFS files found:
=====================================
  File name               Size
=====================================
/angry_16.jpg            18267 bytes
/Baboon40.jpg            24384 bytes
/bapa.jpg                26797 bytes
/betty_8.jpg             17422 bytes
/chinese_girl.jpg        46034 bytes
/dog.jpg                 18163 bytes
/EagleEye.jpg            20838 bytes
/flower.jpg              23879 bytes
/flower3.jpg             32385 bytes
/flower4.jpg             30836 bytes
/hibiscus.jpg            26372 bytes
/lena20k.jpg             19414 bytes
/marilyn_240x240.jpg     9402 bytes
/MOTO_CORRIDA.jpg        18450 bytes
/Mouse480.jpg            6609 bytes
/Parrot2.jpg             17393 bytes
/Penguins.jpg            29719 bytes
/purple.jpg              32042 bytes
/rose.jpg                9243 bytes
/sunfl.jpg               32187 bytes
/tiger.jpg               31171 bytes
/tiger_320x200x24.jpg    29484 bytes
/waterlily.jpg           44762 bytes
/woof.jpg                19000 bytes
=====================================

  1: /angry_16.jpg        240x320 394 ms
  2: /Baboon40.jpg        320x480 773 ms
  3: /bapa.jpg            250x315 458 ms
  4: /betty_8.jpg         204x252 277 ms
  5: /chinese_girl.jpg    320x480 870 ms
  6: /dog.jpg             284x177 279 ms
  7: /EagleEye.jpg        300x300 450 ms
  8: /flower.jpg          240x320 419 ms
  9: /flower3.jpg         320x240 479 ms
 10: /flower4.jpg         320x240 474 ms
 11: /hibiscus.jpg        240x320 465 ms
 12: /lena20k.jpg         320x480 751 ms
 13: /marilyn_240x240.jpg 240x240 287 ms
 14: /MOTO_CORRIDA.jpg    320x240 402 ms
 15: /Mouse480.jpg        480x320 696 ms
 16: /Parrot2.jpg         261x200 294 ms
 17: /Penguins.jpg        320x240 471 ms
 18: /purple.jpg          240x320 480 ms
 19: /rose.jpg            176x220 203 ms
 20: /sunfl.jpg           320x480 802 ms
 21: /tiger.jpg           320x240 479 ms
 22: /tiger_320x200x24.jpg 320x200 416 ms
 23: /waterlily.jpg       400x300 715 ms
 24: /woof.jpg            240x320 405 ms

david_prentice

Stick with ESP8266 v2.4.2

At least the sketch appears to have worked out of the box.

"output.h" contains my results.

SPIFFS is "built-in" to the ESP8266 core.
SPIFFS is a "built-in" library for ESP32

It is unfortunate that you have to use different calls to walk a directory.
I would be happier if I could avoid conditional code.

David.

bodmer

I recommend using the jpeg rendering code incorporated into the TFT_eFEX extension library which can be added to the start of a sketch like this:

Code: [Select]

// Invoke TFT library
TFT_eSPI tft = TFT_eSPI();

// https://github.com/Bodmer/TFT_eFEX
#include <TFT_eFEX.h>              // Include the extension graphics functions library
TFT_eFEX  fex = TFT_eFEX(&tft);    // Create TFT_eFX object "efx" with pointer to "tft" object


The examples show the use of the rendering functions.

It is simplest to use pushImage() for rendering MCU blocks as this function will crop blocks correctly if they overlap the edges of the screen.

Since images may not have a width and/or height that is a whole number of MCU blocks (for example dividable by 16) so in the worst case may only contain 1 pixel. Early versions of the jpeg rendering code did not take this into account, but this is handled in the TFT_eFEX library.

The ESP32 board package includes a native jpeg decoder that is slightly (~12%) faster than the JPEGDecoder library but is less memory efficient. The TFT_eFEX "Jpeg_ESP32" demonstrates the new functions and includes cropping and scaling of the jpeg.

The TFT_eSPI library has been tweaked to be compatible with the ESP8266 latest board package. This version is not yet available via te IDE library manager so you would need to download direct from Git.

david_prentice

Havve you ever tried Chan's tjpgd decoder?
Is it faster than picojpeg ?

It would be nice to use with Xmega or smaller M0 chips.

David.

bodmer

Hi David, Espressif appear to have used the tjpgd decoder code and embedded it in the board package. Based on ESP32 experience it is ~12% faster probably because picojpeg uses 8 bit variables where possible (as it targeted 8 bit MCUs).

Use of the tjpgd decoder with Xmega and M0 would be possible but I am not a user of those processors so it is not something I plan to investigate.

david_prentice

Ah-ha.  I have just Forked TFTeFEX.   So I can write an equivalent "show all JPEGs on SPIFFS" sketch.

If it looks promising,  I can port from ESP32 C++ code easier than fiddling with Chan's example in C.

Chan's examples are very much tied to specific hardware.

On a different subject.   When I attempted to install ESP8266 2.5.1 or 2.5.0 the rendering speed became very SLOW.    I have not investigated.

David.

david_prentice

#22
May 21, 2019, 12:32 am Last Edit: May 21, 2019, 11:23 am by david_prentice
Here is a test sketch that should run on both ESP32 and ESP8266
ESP32 version compares both styles of Jpeg method.
ESP8266 only uses the JPEGDecoder method.

Code: [Select]

================================================
ESP32 v1.02 @ 240MHz
Using library JPEGDecoder at version 1.8.0
Using library TFT_eSPI at version 1.4.9
Using library TFT_eFEX at version 0.0.4
User Setup: SPI=27MHz ILI9488=320x480
================================================

ESP8266 / ESP32 Jpeg decoder test!

Initialisation done.

Listing SPIFFS files:
=================================================
  File name                Size
=================================================
  /angry_16.jpg                         18267 bytes
  /Baboon40.jpg                         24384 bytes
  /bapa.jpg                             26797 bytes
  /betty_8.jpg                          17422 bytes
  /chinese_girl.jpg                     46034 bytes
  /dog.jpg                              18163 bytes
  /EagleEye.jpg                         20838 bytes
  /flower.jpg                           23879 bytes
  /flower3.jpg                          32385 bytes
  /flower4.jpg                          30836 bytes
  /hibiscus.jpg                         26372 bytes
  /lena20k.jpg                          19414 bytes
  /marilyn_240x240.jpg                   9402 bytes
  /MOTO_CORRIDA.jpg                     18450 bytes
  /Mouse480.jpg                          6609 bytes
  /Parrot2.jpg                          17393 bytes
  /Penguins.jpg                         29719 bytes
  /purple.jpg                           32042 bytes
  /rose.jpg                              9243 bytes
  /sunfl.jpg                            32187 bytes
  /tiger.jpg                            31171 bytes
  /tiger_320x200x24.jpg                 29484 bytes
  /waterlily.jpg                        44762 bytes
  /woof.jpg                             19000 bytes
=================================================

render from array in Flash
scaled and cropped from array in Flash

render files from SPIFFS:
  1: /angry_16.jpg        240x320 392 ms [348 ms]
  2: /Baboon40.jpg        320x480 767 ms [674 ms]
  3: /bapa.jpg            250x315 452 ms [417 ms]
  4: /betty_8.jpg         204x252 273 ms [247 ms]
  5: /chinese_girl.jpg    320x480 864 ms [763 ms]
  6: /dog.jpg             284x177 275 ms [248 ms]
  7: /EagleEye.jpg        300x300 455 ms [392 ms]
  8: /flower.jpg          240x320 417 ms [364 ms]
  9: /flower3.jpg         320x240 477 ms [424 ms]
 10: /flower4.jpg         320x240 472 ms [419 ms]
 11: /hibiscus.jpg        240x320 463 ms [410 ms]
 12: /lena20k.jpg         320x480 746 ms [661 ms]
 13: /marilyn_240x240.jpg 240x240 286 ms [253 ms]
 14: /MOTO_CORRIDA.jpg    320x240 400 ms [352 ms]
 15: /Mouse480.jpg        480x320 692 ms [451 ms]
 16: /Parrot2.jpg         261x200 290 ms [253 ms]
 17: /Penguins.jpg        320x240 470 ms [417 ms]
 18: /purple.jpg          240x320 478 ms [423 ms]
 19: /rose.jpg            176x220 203 ms [177 ms]
 20: /sunfl.jpg           320x480 810 ms [711 ms]
 21: /tiger.jpg           320x240 476 ms [421 ms]
 22: /tiger_320x200x24.jpg 320x200 414 ms [367 ms]
 23: /waterlily.jpg       400x300 710 ms [543 ms]
 24: /woof.jpg            240x320 402 ms [353 ms]




TFT_FEX_SPIFFS_Jpeg.ino
Code: [Select]

/*====================================================================================

           Test jpeg rendering with ESP8266 and JPEGDecoder library

  ==================================================================================*/

// The Jpeg library required can be found here:
// https://github.com/Bodmer/JPEGDecoder

// The example images used to test this sketch can be found in the sketch
// Data folder, press Ctrl+K to see this folder. Use the IDE "Tools" menu
// "ESP8266 Sketch Data Upload" option to upload the images to SPIFFS.

// An image is also stored as an array in a header file attached to this sketch
#include "jpeg_arrays.h"

//====================================================================================
//                                  Libraries
//====================================================================================
// Call up the SPIFFS FLASH filing system this is part of the ESP Core
#define FS_NO_GLOBALS
#include <FS.h>

#include <SPI.h>

// https://github.com/Bodmer/TFT_eSPI
#include <TFT_eSPI.h>                 // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();            // Invoke custom library

// https://github.com/Bodmer/TFT_eFEX
#include <TFT_eFEX.h>              // Include the extension graphics functions library
TFT_eFEX  fex = TFT_eFEX(&tft);    // Create TFT_eFX object "efx" with pointer to "tft" object


//====================================================================================
//                                    Setup
//====================================================================================
void setup()
{
    //Serial.begin(250000); // Used for messages and the C array generator
    Serial.begin(9600); // Used for messages

    delay(10);
    Serial.println("\nESP8266 / ESP32 Jpeg decoder test!");

    tft.begin();

    tft.setRotation(0);  // 0 & 2 Portrait. 1 & 3 landscape

    tft.fillScreen(TFT_BLACK);

    if (!SPIFFS.begin()) {
        Serial.println("SPIFFS initialisation failed!");
        while (1) yield(); // Stay here twiddling thumbs waiting
    }
    Serial.println("\r\nInitialisation done.");

    fex.listSPIFFS(); // Lists the files so you can see what is in the SPIFFS

    Serial.println("render from array in Flash");
    fex.drawJpeg(EagleEye, sizeof(EagleEye), 0, 0);

#if defined(ESP32)
    Serial.println("scaled and cropped from array in Flash");
    // Power of 2 scale factors
    /*0  JPEG_DIV_NONE,
      1  JPEG_DIV_2,
      2  JPEG_DIV_4,
      3  JPEG_DIV_8,
      4  JPEG_DIV_MAX // = DIV_16 */

    // Scaled and cropped from array
    fex.drawJpg(EagleEye, sizeof(EagleEye), 0, 240,
                120, 120, 60, 60, JPEG_DIV_2);
#endif
    delay(2000);
    Serial.println("");
    Serial.println("render files from SPIFFS:");
}

//====================================================================================
//                                    Loop
//====================================================================================
int imagecnt;
void doSomething(const char *name)
{
    boolean decoded = JpegDec.decodeFsFile(name);
    if (decoded == false) return;
    tft.setRotation(JpegDec.width > JpegDec.height ? 1 : 0);
    tft.fillScreen(random(0xFFFF));
    int t1 = millis(), t2 = 0;
    fex.drawJpeg(name, 0, 0);
    t1 = millis() - t1;
#if defined(ESP32)
    delay(1000);
    tft.fillScreen(random(0xFFFF));
    t2 = millis();
    fex.drawJpgFile(SPIFFS, name, 0, 0);
    t2 = millis() - t2;
#endif
    char buf[80];
    sprintf(buf, "%3d: %-20s %dx%d %d ms [%d ms]",
            ++imagecnt, name, JpegDec.width, JpegDec.height, t1, t2);
    Serial.println(buf);
    delay(2000);
}

//====================================================================================
//                                    Loop
//====================================================================================
#if defined(ESP32)
void loop()
{
    File directory = SPIFFS.open("/");
    File f;
    while (f = directory.openNextFile()) {
        String bum = f.name();
        const char *s = bum.c_str();
        if (strstr(s, ".jpg") != NULL) {
            doSomething(s);
        }
    }
}
#else   //old ESP8266 has different SPIFFS methods
void loop()
{
    fs::Dir directory = SPIFFS.openDir("/");
    while (directory.next()) {
        String bum = directory.fileName();
        const char *s = bum.c_str();
        if (strstr(s, ".jpg") != NULL) {
            doSomething(s);
        }
    }
}
#endif
//====================================================================================


Edit.  Another day.  I have concluded:
1.  the new ESP32 decode is about 10% faster than the JPEGDecoder version
2.  the JPEGDecoder version still has issues with part tiles e.g. betty_8 and bapa
3.  the new version crops landscape Mouse and waterlily to width=320
4.  my sketch crashes after a while on ESP8266.  I have not investigated yet

Go Up