loboris / ESP32_TFT_library

Full featured TFT library for ESP32 with demo application
553 stars 219 forks source link

Loading Images from memory #28

Open glowlabs opened 6 years ago

glowlabs commented 6 years ago

Hi, great library!

I see that's its possible to load a image from memory (not spiffs), do you have an example on how this is done?

sukeshak commented 6 years ago

// tft.jpgimage(X, Y, scale, file_name, buf, size] // X & Y can be < 0 ! //============================================= void TFT_jpg_image(int x, int y, uint8_t scale, char *fname, uint8_t *buf, int size)

So you can use the 5th parameter which is a buffer to send the image to the function if (fname == NULL) { // image from buffer dev.membuff = buf; dev.bufsize = size; dev.bufptr = 0; }

SmoothWifi commented 5 years ago

Hello,

I try to load jpg img from memory too but with no success:

include "img1.h" //converted JPG into c array

memcpy(disp_buffer, (unsigned char *)img1, sizeof(img1)); TFT_jpg_image(CENTER, CENTER, 0, NULL, disp_buffer, sizeof(disp_buffer));

Do you see what am I doing wrong?

sukeshak commented 5 years ago

Don't see anything wrong. Maybe try the same image with file name to see if that works first?

SmoothWifi commented 5 years ago

Hello,

thanks for you answer! the whole project is great and works fine (also with file name), however I am trying to load other img after an OTA (the device is in another land and there is no way to flash the device manually), so I can't work with file name anymore, that is the reason why I am try to save image directly in memory. I use a jpg to c converter from: https://www.mikrocontroller.net/topic/425390 and get the c array from an image I want to use (by the way the size is much bigger than in .jpg: 704kB instead of 6,5kB for 320*240 pixels!!!). Then I save the img.h ( into the same folder where the main file is) : const unsigned char img[] = {hex converted}; then in main.c :

include "img1.h"

uint8_t disp_buffer = NULL; ...initialisation... memcpy(disp_buffer, (unsigned char )img, sizeof(img)); TFT_jpg_image(CENTER, CENTER, 0, NULL, disp_buffer, sizeof(disp_buffer));

it compiles but crashes:

Guru Meditation Error: Core 0 panic'ed (StoreProhibited) . Exception was unhandled. Register dump: PC : 0x4000c2e4 PS : 0x00060230 A0 : 0x800d28dc A1 : 0x3ffb75d0 A2 : 0x00000000 A3 : 0x3f403ec4 A4 : 0x0001c200 A5 : 0x00000000 A6 : 0xffffcfcc A7 : 0xffffffff A8 : 0x00000000 A9 : 0x3ffb7590 A10 : 0x00000000 A11 : 0x00000001 A12 : 0x3ffb0854 A13 : 0x3ffb7290 A14 : 0x3ffb7290 A15 : 0x00000004 SAR : 0x0000000e EXCCAUSE: 0x0000001d EXCVADDR: 0x00000000 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0x00001c1f Backtrace: 0x4000c2e4:0x3ffb75d0 0x400d28d9:0x3ffb75e0 0x400d0e86:0x3ffb7670 0x400d28d9: app_main at C:/msys32/home/illy/esp/esp32_wilo/main/code.c:3309 (discriminator 4) 0x400d0e86: main_task at C:/msys32/home/Illy/esp/esp-idf/components/esp32/cpu_start.c:456 CPU halted.

Any idea what I could do?

sukeshak commented 5 years ago

https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/fatal-errors.html LoadProhibited, StoreProhibited This CPU exception happens when application attempts to read from or write to an invalid memory location. The address which was written/read is found in EXCVADDR register in the register dump. If this address is zero, it usually means that application attempted to dereference a NULL pointer. If this address is close to zero, it usually means that application attempted to access member of a structure, but the pointer to the structure was NULL. If this address is something else (garbage value, not in 0x3fxxxxxx - 0x6xxxxxxx range), it likely means that the pointer used to access the data was either not initialized or was corrupted.

From your stack dump it shows this EXCVADDR: 0x00000000

So there is something wrong with the pointer being used. Maybe because of this line? uint8_t *disp_buffer = NULL;

Sorry I don't have further expertise to help in this... but above information should give some idea on where to look for a solution.

SmoothWifi commented 5 years ago

Thanks for the link sukeshak! I changed the code:

int sz=sizeof(img); uint8_t buffer = (uint8_t) malloc(sz); if (buffer == NULL) printf("stop\r\n"); else { printf("start\r\n"); memcpy(buffer, (unsigned char *)img, sz); TFT_jpg_image(CENTER, CENTER, 0, NULL, buffer, sz); } free(buffer);

The CPU doesn't crash anymore :) I try to understand the TFT_jpg_image routine but I don't know how works this function: jd_prepare(&jd, tjd_buf_input, (void *)work, sz_work, &dev); It returns 6 instead of 0. Do you know where I can find that prototype?

SmoothWifi commented 5 years ago

Ok I have found it, I am going to study it :)

SmoothWifi commented 5 years ago

Well I get JDR_FMT1 as result what means the format is wrong. I have seen in rom/tjpgd.h format is RGB888 3bytes/pixel what I have chosen. Then I have seen another project of Loboris: https://github.com/loboris/ESP32_ePaper_example which alos use images from memory (at least I believe) and took from it the img1.h. The function EPD_jpg_image is almost the same as the TFT_jpg_image. But still doesn't work :( . Have you already loaded an image from memory with success?

sukeshak commented 5 years ago

Looks like some progress made :)

I am on an international travel so don't have any hardware to try. Will be at least a week plus before I get a chance.

Did you try an image which is part of his samples for testing, to isolate it?

sukeshak commented 5 years ago

Also probably you can try this since bmp is less complicated

TFT_bmp_image

SmoothWifi commented 5 years ago

Well I won't give up with JPG :) ! I have also tried with his sample bot no success. int sz=sizeof(img); printf("size of img:%d\n\r",sz); uint8_t buffer=(uint8_t) malloc(sz); if (buffer) { memcpy(buffer, (unsigned char )img, sz); for (int i=0; i<sz; i++) {printf("%u\n\r",(buffer+i));} TFT_jpg_image(CENTER, CENTER, 0, NULL, buffer, sz); free(buffer); } The buffer is well filled with the JPG converted into RGB888 and fit the size. Then tjd_buf_input function is called but third argument (nd) is always equal to 2 (also reading 2 bytes?), instead of the size of the buffer I think? . I don't understand where comes the 3 argument of the tjd_buf_input function from. It is called with jd_prepare and use the JPGIODEV structure as far I understand. I get always JDR_FMT1 as return.

sukeshak commented 5 years ago

Using the BMP function is just to further isolate the issue...

Here is the code you need to debug... good luck :) https://github.com/loboris/ESP32_TFT_library/blob/aa21772f54a71887ec08b2e8bbaef9e304009891/components/tft/tft.c#L2376

SmoothWifi commented 5 years ago

well that is indeed the code I am trying to debug. I am stucked into the static UINT tjd_buf_input ( JDEC jd, // Decompression object BYTE buff, // Pointer to the read buffer (NULL:skip) UINT nd // Number of bytes to read/skip from input stream ). I don't understand why it only read 2 bytes also why nd is set to 2. Where is it parametrized? it should come from the buf size isn't it? but I have checked that dev.bufsize = size; is well parametrized...

SmoothWifi commented 5 years ago

when I take jpg from SPIFFS it shows the right size: static UINT tjd_buf_input ( JDEC jd, // Decompression object BYTE buff, // Pointer to the read buffer (NULL:skip) UINT nd // Number of bytes to read/skip from input stream ) { // Device identifier for the session (5th argument of jd_prepare function) JPGIODEV dev = (JPGIODEV)jd->device; printf("Reading %d bytes from pos %d\n", nd, dev->bufptr); if (!dev->membuff) return 0;

if (dev->bufptr >= (dev->bufsize + 2)) return 0; // end of stream

if ((dev->bufptr + nd) > (dev->bufsize + 2)) nd = (dev->bufsize + 2) - dev->bufptr;

if (buff) { // Read nd bytes from the input strem
    memcpy(buff, dev->membuff + dev->bufptr, nd);
    dev->bufptr += nd;
    printf("read %u bytes\n\r",nd);
    return nd;  // Returns number of bytes read
}
else {  // Remove nd bytes from the input stream
    printf("remove\n\r");
    dev->bufptr += nd;
    return nd;
}

}