Am very thankful for your time, and the Code fix has worked, pictures are showing up much better now, for a minute thought i was doing some mistake in some setting.
So is this like something specific that was required for ili9488 chip.
David or Bodmer
Please answer only when free, it was taking 350ms max to display full image on 2.8 display, but with 3.5 inch display, it's taking 1200ms to display full image, is this normal, both cases spi is operating at 27Mhz
This means 1050ms for the bigger picture. Purely because of more SPI traffic.
Obviously a fixed pushImage() will be faster than the individual pushColor() calls in my kludge.
There is plenty of scope for optimisation. Actually the SPI traffic maths calculation is naive. The bulk of the time is spent decoding JPG and creating the 16-bit or 24-bit pixel.
Thanks David, actually it was taking 1.7 to 2.2 seconds, depending on picture, but 1.686 is minimum on Esp32, The spi frequency change did not make much of difference hardly 100ms. so looks like it is taking lot of cpu for jpeg decode conversion. Well It should be ok for now.
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
#define tft_Write_16S(C) spi.transfer(C & 0xF8); \
spi.transfer((C & 0xE0)>>11 | (C & 0x07)<<5); \
spi.transfer((C & 0x1F00)>>5)
to:
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
#define tft_Write_16S(C) spi.transfer(C & 0xF8); \
spi.transfer((C & 0xE000)>>11 | (C & 0x07)<<5); \
spi.transfer((C & 0x1F00)>>5)
It makes little difference using pushRect(), pushImage(), pushColors(..., false) or pushColor() in a loop.
sunfl.jpg takes 2293ms, 2293ms, 2287ms, 2293ms on an ESP8266
Most of the time is spent in decoding JPEG.
ESP32 will be faster than ESP8266.
There might be optimisations for the JPEG decode algorithm.
Personally, I find the convenience of SPIFFS to be impressive. You can get lots of JPEGS into a 1MB SPIFFS. Of course an SD card gives you unlimited quantity of pictures and you can use RAW pixel dumps.
On balance, a compressed JPG avoids the SPI transfer time of a RAW file from SD.
The ESP32 supports QSPI SD card. I have never tried QSPI.
David, am gonna try that fix first in the morning, yes am using SPIFFS only, and 1MB is enough to rotate like 10 pics, and any supported graphic files. SD card is not required at this point, The time taken for JPEG C Array is at 700ms so the important one file am gonna call from Array for now and rest from SPIFFS, that would solve the time issue.
I have removed the old fix and applied new one by changing the below line , the images are fine , displaying normally, the jpeg which was taking 2.2 sec is now taking just one second, this has lot of detail etc.
Thank you again, the problem is solved.
I am impressed. I only ran it on ESP8266. I would not expect such a big difference.
If you tried the ZIP that I had attached, it reports files found on SPIFFS. And the rendering time for each file that matches the strstr() line. e.g. strstr("sunfl.jpg")
In other words. You could quote the actual number of milliseconds for "sunfl.jpg"
We could compare the same JPEG image.
David, the kbv code required changes to run on esp32, so I have used the old same sketch to display sunfl.jpg , SPIFFS_Jpeg sketch from examples of jpegdecoder , the performance difference between esp32 and esp8266 should not be that much but the time is 700ms
This is the result from the ESP8266 using ESP8266 v2.4.2 Core
NodeMCU decoder test!
Initialisation done.
SPIFFS files found:
=====================================
File name Size
=====================================
/Baboon40.jpg 24384 bytes
/waterlily.jpg 44762 bytes
/bapa.jpg 26797 bytes
/betty_8.jpg 17422 bytes
/chinese_girl.jpg 46034 bytes
/woof.jpg 19000 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
/tiger_320x200x24.jpg 29484 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
/angry_16.jpg 18267 bytes
=====================================
1: /Baboon40.jpg 320x480 2320 ms
2: /waterlily.jpg 400x300 2052 ms
3: /bapa.jpg 250x315 1245 ms
4: /betty_8.jpg 204x252 823 ms
5: /chinese_girl.jpg 320x480 2502 ms
6: /woof.jpg 240x320 1218 ms
7: /dog.jpg 284x177 824 ms
8: /EagleEye.jpg 300x300 1336 ms
9: /flower.jpg 240x320 1261 ms
10: /flower3.jpg 320x240 1329 ms
11: /flower4.jpg 320x240 1310 ms
12: /hibiscus.jpg 240x320 1282 ms
13: /lena20k.jpg 320x480 2247 ms
14: /tiger_320x200x24.jpg 320x200 1154 ms
15: /marilyn_240x240.jpg 240x240 861 ms
16: /MOTO_CORRIDA.jpg 320x240 1211 ms
17: /Mouse480.jpg 480x320 2078 ms
18: /Parrot2.jpg 261x200 875 ms
19: /Penguins.jpg 320x240 1305 ms
20: /purple.jpg 240x320 1333 ms
21: /rose.jpg 176x220 611 ms
22: /sunfl.jpg 320x480 2292 ms
23: /tiger.jpg 320x240 1330 ms
24: /angry_16.jpg 240x320 1179 ms
I had already updated ESP32 to ESP32 Core v1.0.2
I had to amend the SPIFFS calls to suit v1.0.2
and this is the result for ESP32 using ESP32 Core v1.0.2 @ 240MHz SPI=27MHz
NodeMCU decoder test!
Initialisation done.
Listing directory: /
FILE: /angry_16.jpg SIZE: 18267
FILE: /Baboon40.jpg SIZE: 24384
FILE: /bapa.jpg SIZE: 26797
FILE: /betty_8.jpg SIZE: 17422
FILE: /chinese_girl.jpg SIZE: 46034
FILE: /dog.jpg SIZE: 18163
FILE: /EagleEye.jpg SIZE: 20838
FILE: /flower.jpg SIZE: 23879
FILE: /flower3.jpg SIZE: 32385
FILE: /flower4.jpg SIZE: 30836
FILE: /hibiscus.jpg SIZE: 26372
FILE: /lena20k.jpg SIZE: 19414
FILE: /marilyn_240x240.jpg SIZE: 9402
FILE: /MOTO_CORRIDA.jpg SIZE: 18450
FILE: /Mouse480.jpg SIZE: 6609
FILE: /Parrot2.jpg SIZE: 17393
FILE: /Penguins.jpg SIZE: 29719
FILE: /purple.jpg SIZE: 32042
FILE: /rose.jpg SIZE: 9243
FILE: /sunfl.jpg SIZE: 32187
FILE: /tiger.jpg SIZE: 31171
FILE: /tiger_320x200x24.jpg SIZE: 29484
FILE: /waterlily.jpg SIZE: 44762
FILE: /woof.jpg SIZE: 19000
1: /angry_16.jpg 240x320 394 ms
2: /Baboon40.jpg 320x480 771 ms
3: /bapa.jpg 250x315 453 ms
4: /betty_8.jpg 204x252 273 ms
5: /chinese_girl.jpg 320x480 868 ms
6: /dog.jpg 284x177 275 ms
7: /EagleEye.jpg 300x300 445 ms
8: /flower.jpg 240x320 418 ms
9: /flower3.jpg 320x240 478 ms
10: /flower4.jpg 320x240 473 ms
11: /hibiscus.jpg 240x320 463 ms
12: /lena20k.jpg 320x480 750 ms
13: /marilyn_240x240.jpg 240x240 287 ms
14: /MOTO_CORRIDA.jpg 320x240 401 ms
15: /Mouse480.jpg 480x320 695 ms
16: /Parrot2.jpg 261x200 289 ms
17: /Penguins.jpg 320x240 470 ms
18: /purple.jpg 240x320 479 ms
19: /rose.jpg 176x220 203 ms
20: /sunfl.jpg 320x480 802 ms
21: /tiger.jpg 320x240 477 ms
22: /tiger_320x200x24.jpg 320x200 415 ms
23: /waterlily.jpg 400x300 712 ms
24: /woof.jpg 240x320 403 ms
Note that the ESP32 was faster than ESP8266 but I did not get 730 ms
20: /sunfl.jpg 320x480 802 ms
I updated my ESP8266 installation to v2.5.1 but could not get any TFT_eSPI examples to compile.
I will try installing v2.5.0. Otherwise I will have to go back to v2.4.2
David.
Edit. Woo-hoo. ESP8266 v2.5.0 will compile and run but it is very SLOW. e.g. sunfl.jpg: 3677 ms @ 160MHz. 4418 ms @ 80MHz ( SPI=27MHz )
Using library JPEGDecoder at version 1.8.0 in folder: C:\Users\David Prentice\Documents\Arduino\libraries\JPEGDecoder
Using library SD at version 1.0.5 in folder: C:\Users\David Prentice\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\SD
Using library SPI at version 1.0 in folder: C:\Users\David Prentice\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\SPI
Using library TFT_eSPI at version 1.4.9 in folder: C:\Users\David Prentice\Documents\Arduino\libraries\TFT_eSPI
"C:\\Users\\David Prentice\\AppData\\Local\\Arduino15\\packages\\esp8266\\tools\\xtensa-lx106-elf-gcc\\2.5.0-3-20ed2b9/bin/xtensa-lx106-elf-size" -A "C:\\Users\\DAVIDP~1\\AppData\\Local\\Temp\\arduino_build_573353/TFT_SPIFFS_Jpeg_kbv.ino.elf"
Sketch uses 332688 bytes (31%) of program storage space. Maximum is 1044464 bytes.
Global variables use 31364 bytes (38%) of dynamic memory, leaving 50556 bytes for local variables. Maximum is 81920 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
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:
// 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.
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.
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.
================================================
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
/*====================================================================================
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:
the new ESP32 decode is about 10% faster than the JPEGDecoder version
the JPEGDecoder version still has issues with part tiles e.g. betty_8 and bapa
the new version crops landscape Mouse and waterlily to width=320
my sketch crashes after a while on ESP8266. I have not investigated yet