bitbank2 / PNGdec

An optimized PNG decoder suitable for microcontrollers and PCs
Apache License 2.0
182 stars 29 forks source link

how read png from sdcard #16

Closed Maverik1408 closed 1 year ago

Maverik1408 commented 1 year ago

hi, i want read png from sdcard but not work you can help me

bitbank2 commented 1 year ago

I'm confident that the code works correctly. Can you provide a complete example which demonstrates the problem you encountered?

Maverik1408 commented 1 year ago

ok sure error my this is my code, sorry for formatting

`

include

// Include the PNG decoder library

include

PNG png;

define MAX_IMAGE_WDITH 240 // Adjust for your images

int16_t xpos = 0; int16_t ypos = 0;

// Include the TFT library https://github.com/Bodmer/TFT_eSPI

include "SPI.h"

include // Hardware-specific library

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

//==================================================================================== // Setup //==================================================================================== void setup() { Serial.begin(115200); Serial.println("\n\n Using the PNGdec library");

if (!SD.begin()) { Serial.println("Card Mount Failed"); return; } uint64_t cardSize = SD.cardSize() / (1024 * 1024); Serial.printf("SD Card Size: %lluMB\n", cardSize);

// Initialise the TFT tft.begin(); tft.fillScreen(TFT_BLACK); //tft.initDMA();

char namebuf[32] = "/"; File root; int pathlen;

root = SD.open(namebuf); pathlen = strlen(namebuf);

char *nm = namebuf + pathlen; File f = root.openNextFile(); //Serial.println(f.name()); f = root.openNextFile(); Serial.println(f.name()); uint8_t ret; uint32_t start;

if (f != NULL) { Serial.println("OK APERTURA FILE"); strcpy(nm, (char *)f.name()); f.close(); strlwr(nm); Serial.print(namebuf); Serial.print(F(" - ")); int16_t rc = png.open(namebuf, pngOpen, pngClose, pngRead, pngSeek, pngDraw); Serial.println(rc); if (rc == PNG_SUCCESS) { tft.startWrite(); Serial.printf("image specs: (%d x %d), %d bpp, pixel type: %d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType()); uint32_t dt = millis(); if (png.getWidth() > MAX_IMAGE_WDITH) { Serial.println("Image too wide for allocated lin buffer!"); } else { rc = png.decode(NULL, 0); png.close(); } tft.endWrite(); // How long did rendering take... Serial.print(millis()-dt); Serial.println("ms"); } } else { Serial.println("ERRORE APERTURA FILE"); }

Serial.println("\r\nInitialisation done."); }

//==================================================================================== // Loop //==================================================================================== void loop() { }

uint8_t readFile(const char filename) { uint8_t pBuffer; // Declare a pointer to your buffer. File myFile = SD.open(F(filename)); // Open file for reading. if (myFile) { unsigned int fileSize = myFile.size(); // Get the file size. pBuffer = (uint8_t)malloc(fileSize + 1); // Allocate memory for the file and a terminating null char. myFile.read(pBuffer, fileSize); // Read the file into the buffer. pBuffer[fileSize] = '\0'; // Add the terminating null char. //Serial.print("PROV:"); //Serial.println(pBuffer); // Print the file to the serial monitor. String str = (char*)pBuffer; Serial.println(str); myFile.close(); // Close the file. } // Use the buffer as needed here. free(pBuffer);

return pBuffer;  

}

//=========================================v========================================== // pngDraw //==================================================================================== // This next function will be called during decoding of the png file to // render each image line to the TFT. If you use a different TFT library // you will need to adapt this function to suit. // Callback function to draw pixels to the display void pngDraw(PNGDRAW *pDraw) { Serial.println("pngDraw"); //uint16_t lineBuffer[MAX_IMAGE_WDITH]; //static uint16_t dmaBuffer[MAX_IMAGE_WDITH]; // static so buffer persists after fn exit //png.getLineAsRGB565(pDraw, lineBuffer, PNG_RGB565_BIG_ENDIAN, 0xffffffff); //tft.pushImageDMA(xpos, ypos + pDraw->y, pDraw->iWidth, 1, lineBuffer, dmaBuffer);

uint16_t lineBuffer[MAX_IMAGE_WDITH]; png.getLineAsRGB565(pDraw, lineBuffer, PNG_RGB565_BIG_ENDIAN, 0xffffffff); tft.pushImage(xpos, ypos + pDraw->y, pDraw->iWidth, 1, lineBuffer); } `

bitbank2 commented 1 year ago

The readFile() function has many errors in it, and I don't see your implementations of the pngOpen/Read/Seek functions. Does the PNG open successfully? Does it display the file size/bpp info? Your readFile() implementation indicates that you don't have a solid grasp of C pointers. I'll help if I can, but it looks like the problem is in your code.

Maverik1408 commented 1 year ago

Sorry for my english and my code ... The function readfile i not used in regused code. The PNG Is open the program stopped on seek function

This Is log

Image.png Attempting to open /image.png read 0 success file image specs: (200 x 200), 8 bpp, pixel type: 3 seek:8

bitbank2 commented 1 year ago

Se può fornire tutto il code (incluendo i method pngRead/pngSeek), posso auitarvi. In questa forma, prenderá molto più tempo.

Maverik1408 commented 1 year ago

thank you!! this is my code! if execute the PNG FLASH example fine work

include

// Include the PNG decoder library

include

PNG png; // PNG decoder inatance

define MAX_IMAGE_WDITH 240 // Adjust for your images

int16_t xpos = 0; int16_t ypos = 0;

// Include the TFT library https://github.com/Bodmer/TFT_eSPI

include "SPI.h"

include // Hardware-specific library

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

// Functions to access a file on the SD card File myfile;

const char *filename;

int16_t w, h, xOffset, yOffset; //==================================================================================== // Setup //==================================================================================== void setup() { Serial.begin(115200); Serial.println("\n\n Using the PNGdec library");

// Set all chip selects high to avoid bus contention during initialisation of each peripheral digitalWrite(22, HIGH); // Touch controller chip select (if used) digitalWrite(15, HIGH); // TFT screen chip select digitalWrite( 5, HIGH); // SD card chips select, must use GPIO 5 (ESP32 SS)

// Initialise the TFT tft.begin(); tft.fillScreen(TFT_BLACK);

if (!SD.begin()) { Serial.println("Card Mount Failed"); return; } uint8_t cardType = SD.cardType();

if (cardType == CARD_NONE) { Serial.println("No SD card attached"); return; }

Serial.print("SD Card Type: "); if (cardType == CARD_MMC) { Serial.println("MMC"); } else if (cardType == CARD_SD) { Serial.println("SDSC"); } else if (cardType == CARD_SDHC) { Serial.println("SDHC"); } else { Serial.println("UNKNOWN"); }

uint64_t cardSize = SD.cardSize() / (1024 * 1024); Serial.printf("SD Card Size: %lluMB\n", cardSize);

File dir = SD.open("/"); while (true) { File entry = dir.openNextFile(); if (!entry) break; if (entry.isDirectory() == false) { const char *name = entry.name(); const int len = strlen(name); Serial.print("File: "); Serial.println(name); if (len > 3 && strcmp(name + len - 3, "png") == 0) { Serial.print("File: "); Serial.println(name); filename = name; }
// close the file: entry.close();

  }
}

String strname = filename; strname = "/" + strname; int16_t rc = png.open(strname.c_str(), myOpen, myClose, myRead, mySeek, pngDraw); Serial.println(rc); if(rc == PNG_INVALID_FILE){ Serial.println("invalid file"); }

if (rc == PNG_SUCCESS) { Serial.println("success file"); tft.startWrite(); Serial.printf("image specs: (%d x %d), %d bpp, pixel type: %d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType()); uint32_t dt = millis(); if (png.getWidth() > MAX_IMAGE_WDITH) { Serial.println("Image too wide for allocated lin buffer!"); } else { rc = png.decode(NULL, 0); png.close(); } tft.endWrite(); // How long did rendering take... Serial.print(millis()-dt); Serial.println("ms"); }

Serial.println("\r\nInitialisation done."); }

//==================================================================================== // Loop //==================================================================================== void loop() {

}

void myOpen(const char filename, int32_t size) { Serial.printf("Attempting to open %s\n", filename); myfile = SD.open(filename); if (!myfile) { Serial.println("Failed to open file"); } size = myfile.size(); return &myfile; } void myClose(void handle) { Serial.println("close"); if (myfile) myfile.close(); } int32_t myRead(PNGFILE handle, uint8_t buffer, int32_t length) { Serial.println("read"); if (!myfile) return 0; return myfile.read(buffer, length); } int32_t mySeek(PNGFILE handle, int32_t position) { Serial.println("seek"); if (!myfile) return 0; return myfile.seek(position); }

//=========================================v========================================== // pngDraw //==================================================================================== // This next function will be called during decoding of the png file to // render each image line to the TFT. If you use a different TFT library // you will need to adapt this function to suit. // Callback function to draw pixels to the display void pngDraw(PNGDRAW *pDraw) { Serial.println("pDraw"); uint16_t usPixels[png.getWidth()];
uint16_t lineBuffer[MAX_IMAGE_WDITH]; png.getLineAsRGB565(pDraw, usPixels, PNG_RGB565_BIG_ENDIAN, 0xffffffff); tft.pushImage(0, 0 + pDraw->y, pDraw->iWidth, 1, usPixels); }

bitbank2 commented 1 year ago

It's difficult to see what's wrong from the code you sent. Can you send me the image you're trying to open? I'll run it on an ESP32 from my collection.

Maverik1408 commented 1 year ago

this is image

EagleEye

thank you

bitbank2 commented 1 year ago

I did some tests on my $10 ESP32 LCD board and PNGdec works correctly. Here is my sample code (see photo below):

include

include

include "FS.h"

include "SD.h"

include "SPI.h"

PNG png;

define MAX_IMAGE_WDITH 240 // Adjust for your images

BB_SPI_LCD lcd;

define PIN_CS 15

define PIN_DC 2

define PIN_MOSI 13

define PIN_MISO -1 //12

define PIN_RESET -1

define PIN_SCK 14

define PIN_LED 21

define PIN_SD_CS 5

define PIN_SD_MOSI 23

define PIN_SD_MISO 19

define PIN_SD_SCK 18

// Functions to access a file on the SD card File myfile;

void myOpen(const char filename, int32_t size) { Serial.printf("Attempting to open %s\n", filename); myfile = SD.open(filename); size = myfile.size(); return &myfile; } void myClose(void handle) { if (myfile) myfile.close(); } int32_t myRead(PNGFILE handle, uint8_t buffer, int32_t length) { if (!myfile) return 0; return myfile.read(buffer, length); } int32_t mySeek(PNGFILE handle, int32_t position) { if (!myfile) return 0; return myfile.seek(position); }

// Function to draw pixels to the display void PNGDraw(PNGDRAW *pDraw) { uint16_t usPixels[MAX_IMAGE_WDITH];

png.getLineAsRGB565(pDraw, usPixels, PNG_RGB565_BIG_ENDIAN, 0xffffffff); lcd.pushImage(0, pDraw->y, pDraw->iWidth, 1, usPixels); }

void setup() { Serial.begin(115200); //begin(int iType, int iFlags, int iFreq, int iCSPin, int iDCPin, int iResetPin, int iLEDPin, int iMISOPin, int iMOSIPin, int iCLKPin); lcd.begin(LCD_ILI9341, FLAGS_NONE, 40000000, PIN_CS, PIN_DC, PIN_RESET, PIN_LED, PIN_MISO, PIN_MOSI, PIN_SCK); lcd.setRotation(90); lcd.fillScreen(0); lcd.setFont(FONT_12x16); lcd.setTextColor(0x7e0,0x0000); SPI.begin(PIN_SD_SCK, PIN_SD_MISO, PIN_SD_MOSI); lcd.println("About to access SD Card"); while (!SD.begin(PIN_SD_CS, SPI, 10000000)) { // change this to the appropriate value for your setup lcd.println("Unable to access SD Card"); delay(1000); } lcd.println("SD card success!");

} / setup() /

// Main loop, scan for all .PNG files on the card and display them void loop() { char szPath[256]; int rc, filecount = 0; File dir = SD.open("/"); while (true) { File entry = dir.openNextFile(); if (!entry) break; if (entry.isDirectory() == false) { const char name = entry.name(); const int len = strlen(name); if (name[0] != '.' && name[0] != '_' && len > 3 && (strcmp(name + len - 3, "PNG") == 0 || strcmp(name+len-3, "png") == 0)) { Serial.print("File: "); Serial.println(name); lcd.fillScreen(TFT_BLACK); lcd.setCursor(0, 224); lcd.print("File: "); lcd.println(name); strcpy(szPath, "/"); strcat(szPath, name); rc = png.open((const char )szPath, myOpen, myClose, myRead, mySeek, PNGDraw); if (rc == PNG_SUCCESS) { Serial.printf("image specs: (%d x %d), %d bpp, pixel type: %d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType()); rc = png.decode(NULL, 0); png.close(); } filecount = filecount + 1; // if (digitalRead(34) == LOW) { // skip delay between images when pushbutton is pressed delay(2000); // } } } entry.close(); } if (filecount == 0) { Serial.println("No .PNG files found"); lcd.println("No .PNG files found"); delay(2000); } } 20221201_141012

tnetwork96 commented 1 year ago

include

// Include the PNG decoder library #include

PNG png; // PNG decoder inatance

define MAX_IMAGE_WDITH 240 // Adjust for your images

int16_t xpos = 0; int16_t ypos = 0;

// Include the TFT library https://github.com/Bodmer/TFT_eSPI #include "SPI.h" #include // Hardware-specific library TFT_eSPI tft = TFT_eSPI(); // Invoke custom library

// Functions to access a file on the SD card File myfile;

const char *filename;

int16_t w, h, xOffset, yOffset; //==================================================================================== // Setup //==================================================================================== void setup() { Serial.begin(115200); Serial.println("\n\n Using the PNGdec library");

// Set all chip selects high to avoid bus contention during initialisation of each peripheral digitalWrite(22, HIGH); // Touch controller chip select (if used) digitalWrite(15, HIGH); // TFT screen chip select digitalWrite( 5, HIGH); // SD card chips select, must use GPIO 5 (ESP32 SS)

// Initialise the TFT tft.begin(); tft.fillScreen(TFT_BLACK);

if (!SD.begin()) { Serial.println("Card Mount Failed"); return; } uint8_t cardType = SD.cardType();

if (cardType == CARD_NONE) { Serial.println("No SD card attached"); return; }

Serial.print("SD Card Type: "); if (cardType == CARD_MMC) { Serial.println("MMC"); } else if (cardType == CARD_SD) { Serial.println("SDSC"); } else if (cardType == CARD_SDHC) { Serial.println("SDHC"); } else { Serial.println("UNKNOWN"); }

uint64_t cardSize = SD.cardSize() / (1024 * 1024); Serial.printf("SD Card Size: %lluMB\n", cardSize);

File dir = SD.open("/"); while (true) { File entry = dir.openNextFile(); if (!entry) break; if (entry.isDirectory() == false) { const char *name = entry.name(); const int len = strlen(name); Serial.print("File: "); Serial.println(name); if (len > 3 && strcmp(name + len - 3, "png") == 0) { Serial.print("File: "); Serial.println(name); filename = name; } // close the file: entry.close();

  }
}

String strname = filename; strname = "/" + strname; int16_t rc = png.open(strname.c_str(), myOpen, myClose, myRead, mySeek, pngDraw); Serial.println(rc); if(rc == PNG_INVALID_FILE){ Serial.println("invalid file"); }

if (rc == PNG_SUCCESS) { Serial.println("success file"); tft.startWrite(); Serial.printf("image specs: (%d x %d), %d bpp, pixel type: %d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType()); uint32_t dt = millis(); if (png.getWidth() > MAX_IMAGE_WDITH) { Serial.println("Image too wide for allocated lin buffer!"); } else { rc = png.decode(NULL, 0); png.close(); } tft.endWrite(); // How long did rendering take... Serial.print(millis()-dt); Serial.println("ms"); }

Serial.println("\r\nInitialisation done."); }

//==================================================================================== // Loop //==================================================================================== void loop() {

}

void myOpen(const char filename, int32_t size) { Serial.printf("Attempting to open %s\n", filename); myfile = SD.open(filename); if (!myfile) { Serial.println("Failed to open file"); } size = myfile.size(); return &myfile; } void myClose(void handle) { Serial.println("close"); if (myfile) myfile.close(); } int32_t myRead(PNGFILE handle, uint8_t buffer, int32_t length) { Serial.println("read"); if (!myfile) return 0; return myfile.read(buffer, length); } int32_t mySeek(PNGFILE handle, int32_t position) { Serial.println("seek"); if (!myfile) return 0; return myfile.seek(position); }

//=========================================v========================================== // pngDraw //==================================================================================== // This next function will be called during decoding of the png file to // render each image line to the TFT. If you use a different TFT library // you will need to adapt this function to suit. // Callback function to draw pixels to the display void pngDraw(PNGDRAW *pDraw) { Serial.println("pDraw"); uint16_t usPixels[png.getWidth()]; uint16_t lineBuffer[MAX_IMAGE_WDITH]; png.getLineAsRGB565(pDraw, usPixels, PNG_RGB565_BIG_ENDIAN, 0xffffffff); tft.pushImage(0, 0 + pDraw->y, pDraw->iWidth, 1, usPixels); }

I have tried your code on the TFT ST7735 80x160, but it was not successful

bitbank2 commented 1 year ago

I'm not going to fix your project code. You are using someone else's LCD library. Suffice it to say that the PNGdec library works and you probably did something wrong in your code.