bitbank2 / PNGdec

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

Attempting to push png image from SD card to sprite #17

Closed gregsqueeb closed 1 year ago

gregsqueeb commented 1 year ago

Hello,

I am attempting to push a PNG file from an SD card to a sprite. I was able to get this functioning with tft.pushImage but I am trying to get this to work using sprites so everything is a little smoother. I was wondering if there is an issue with the way I am reading the pngs into the sprite?

Here is my code below. The face sprite (Reading from flash) is showing up but the needle is not showing on top of the face.

#include <Arduino.h>
#include <AsyncTCP.h>
#include <Preferences.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <ArduinoJson.h>
#include <TFT_eSPI.h>

#include <PNGdec.h>
PNG png; // PNG decoder inatance

#include "face.h"

TFT_eSPI tft = TFT_eSPI();
TFT_eSprite faceSpr= TFT_eSprite(&tft);
TFT_eSprite needleSpr= TFT_eSprite(&tft);

#define MAX_IMAGE_WIDTH 240 // Adjust for your images

// SD Card Stuff
#define HSPI_MISO   35
#define HSPI_MOSI   18
#define HSPI_SCLK   33
#define HSPI_SS     16

SPIClass *SDspi = NULL;

void initSDCard(){
  SDspi = new SPIClass(HSPI);
  SDspi->begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS);
  Serial.print("SD Card Init");

  if(!SD.begin(HSPI_SS, *SDspi)){
    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);
}

void setup() {
  // put your setup code here, to run once:
  tft.init();
  tft.fillScreen(TFT_RED);
  tft.setRotation(1);
  tft.setSwapBytes(true);
  faceSpr.createSprite(240,240);
  needleSpr.createSprite(52,222);
  needleSpr.setColorDepth(8);
  initSDCard();
  Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  int rc;
  faceSpr.pushImage(0,0,240,240,face);
  faceSpr.setSwapBytes(true);
  needleSpr.setSwapBytes(true);
  // needleSpr.pushImage(0,0,52,222,needle);
  rc = png.open("/Gauges/HKS/WaterTemp/needle.png", 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();
       }
  needleSpr.pushRotated(&faceSpr,0,TFT_BLACK); 
  faceSpr.pushSprite(0,0, TFT_BLACK);

}

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);
}

void PNGDraw(PNGDRAW *pDraw) {
  uint16_t usPixels[MAX_IMAGE_WIDTH];

  png.getLineAsRGB565(pDraw, usPixels, PNG_RGB565_LITTLE_ENDIAN, 0xffffffff);
  needleSpr.pushImage(0, pDraw->y, pDraw->iWidth, 1, usPixels);
}
bitbank2 commented 1 year ago

I'm not the author of TFT_eSPI; I don't know what the sprite/image functions do. It looks like you're overdrawing the needle sprite with the face sprite immediately after you draw it. It looks like this problem has nothing to do with the PNGDEC library, so I'm closing it.