Closed han-fastolfe closed 2 years ago
Can you send me at least 1 example of a png file that you're not able to decode? With just your sketch code, it doesn't give me enough info to act on. Have you tried the sample sketches with the sample image data provided by my library? Did they properly decode the images?
I tested your files with the latest PNGdec and it works fine. Here it is running on my TinyS2 test rig. I didn't do anything special except not dynamically allocate the structures. That could be what's getting you in trouble.
Also... those weather images are stored in a very wasteful pixel format. They don't have many unique colors, so reducing them to 8-bit palette (with transparency) reduces the file size to 1/10th of the original.
I turned everything into global variables, got rid of the dynamic allocation, even made the PNG data buffer a statically allocated array, but the PNGDraw() function still does not get called.
WiFiClient wifi;
HttpClient httpWeatherData = HttpClient(wifi, "api.openweathermap.org", 80);
HttpClient httpIconData = HttpClient(wifi, "openweathermap.org", 80);
StaticJsonDocument<400> doc;
StaticJsonDocument<200> filter;
char currentTemperature[11] = "-99C (-99)";
char maximumTemperature[5] = "-99C";
char minimumTemperature[5] = "-99C";
char humidity[5] = "100%";
char pressure[7] = "199kpa";
char url[32] = "";
uint8_t pngData[1024];
void getCurrentWeather()
{
Serial.println("Trying to get data from OpenWeaterMap...");
httpWeatherData.get("/data/2.5/weather?q=Kitchener,+CA&appid=**REDACTED**");
if (httpWeatherData.responseStatusCode() == 200)
{
String response = httpWeatherData.responseBody();
deserializeJson(doc, response, DeserializationOption::Filter(filter));
serializeJsonPretty(doc, Serial);
Serial.println();
snprintf(currentTemperature, 11, "%-.fC (%-.f)", doc["main"]["temp"].as<double>() - 273.5, doc["main"]["feels_like"].as<double>() - 273.5);
snprintf(maximumTemperature, 5, "%-.fC", doc["main"]["temp_max"].as<double>() - 273.5);
snprintf(minimumTemperature, 5, "%-.fC", doc["main"]["temp_min"].as<double>() - 273.5);
snprintf(humidity, 5, "%.f%%", doc["main"]["humidity"].as<double>());
snprintf(pressure, 7, "%.fkPa", doc["main"]["pressure"].as<double>() / 10.0);
snprintf(url, 32, "/img/wn/%s.png", doc["weather"][0]["icon"].as<String>().c_str());
Serial.printf("Icon URL: %s\n", url);
httpIconData.get(url);
if (httpIconData.responseStatusCode() == 200)
{
Serial.println("Icon successfully retrieved");
if (httpIconData.isResponseChunked() == true)
{
}
else
{
unsigned int length = httpIconData.contentLength();
Serial.printf("Icon size is %d\nAllocatibng memory.\n", length);
httpIconData.responseBody().getBytes(pngData, length, 0);
Serial.println("About to show icon");
ShowPNG(pngData, length, dma_display, 0, 0);
Serial.println("Freeing PNG data buffer");
}
}
else
{
Serial.printf("Failed to retrieve icon: %d\n", httpWeatherData.responseStatusCode());
}
}
else
{
Serial.println("Getting data from OpenWeatherMap failed!");
}
}
#include <PNGdec.h>
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
#include "png.h"
MatrixPanel_I2S_DMA *panel = NULL;
PNG png;
uint16_t png_x_offset, png_y_offset;
void PNGDraw(PNGDRAW *pDraw)
{
Serial.println("About to draw PNG line");
uint16_t usPixels[pDraw->iWidth];
uint8_t ucMask[40];
png.getLineAsRGB565(pDraw, usPixels, PNG_RGB565_BIG_ENDIAN, 0xffffffff);
for (uint16_t x = 0; x < pDraw->iWidth; x++)
{
panel->drawPixel(x + png_x_offset, pDraw->y + png_y_offset, usPixels[x]);
Serial.printf("(%d+%d, %d+%d): %0x%04x\n ", x, png_x_offset, pDraw->y, png_y_offset, usPixels[x]);
}
}
void ShowPNG(uint8_t *pngData, uint16_t length, MatrixPanel_I2S_DMA *display, int16_t x, int16_t y)
{
Serial.printf("Preparing to show icon of length %d\n", length);
panel = display;
int rc = png.openRAM(pngData, length, PNGDraw);
if (rc == PNG_SUCCESS)
{
Serial.println("Successfully opened icon from buffer");
if (x == -1)
{
png_x_offset = (64 - png.getWidth()) / 2;
}
else
{
png_x_offset = x;
}
if (y == -1)
{
png_y_offset = (32 - png.getHeight()) / 2;
}
else
{
png_y_offset = y;
}
Serial.printf("Offsets calculated: (%d, %d)\n", png_x_offset, png_y_offset);
Serial.println("Drawing PNG now!");
rc = png.decode(NULL, 0);
Serial.printf("Draw result: %d\n", rc);
}
}
The library is able to decode the images you provided and display them on a SPI LCD. I structured my sample app the same way as yours and pass it a custom structure to center the image. Start with a simpler example and work your way up. Your code has a lot going on with WiFi, openweather, etc. PNG decoding requires a lot of RAM. Even an ESP32 can have trouble with it if other parts of your code are using lots of RAM.
I started from the png_transparency.ino sketch as a base, and I am trying to load a PNG from OpenWatherMap.org. The PNG data is opened and stored in a buffer
Serial output:
That buffer is then sent to the code derived from png_transparency.ino:
Serial output: