Skip to content

Commit da87be9

Browse files
kikuchanEeeeBin
authored andcommitted
Add PNG loader (#184)
1 parent f9953af commit da87be9

File tree

4 files changed

+1148
-0
lines changed

4 files changed

+1148
-0
lines changed

src/M5Display.cpp

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,3 +429,181 @@ void M5Display::drawJpgFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y
429429

430430
file.close();
431431
}
432+
433+
434+
/*
435+
* PNG
436+
*/
437+
438+
#include "utility/pngle.h"
439+
#include <HTTPClient.h>
440+
441+
typedef struct _png_draw_params {
442+
uint16_t x;
443+
uint16_t y;
444+
uint16_t maxWidth;
445+
uint16_t maxHeight;
446+
uint16_t offX;
447+
uint16_t offY;
448+
double scale;
449+
uint8_t alphaThreshold;
450+
451+
M5Display *tft;
452+
} png_file_decoder_t;
453+
454+
static void pngle_draw_callback(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4])
455+
{
456+
png_file_decoder_t *p = (png_file_decoder_t *)pngle_get_user_data(pngle);
457+
uint16_t color = jpgColor(rgba); // XXX: It's PNG ;)
458+
459+
if (x < p->offX || y < p->offY) return ;
460+
x -= p->offX;
461+
y -= p->offY;
462+
463+
// An interlaced file with alpha channel causes disaster, so use 1 here for simplicity
464+
w = 1;
465+
h = 1;
466+
467+
if (p->scale != 1.0) {
468+
x = (uint32_t)ceil(x * p->scale);
469+
y = (uint32_t)ceil(y * p->scale);
470+
w = (uint32_t)ceil(w * p->scale);
471+
h = (uint32_t)ceil(h * p->scale);
472+
}
473+
474+
if (x >= p->maxWidth || y >= p->maxHeight) return ;
475+
if (x + w >= p->maxWidth) w = p->maxWidth - x;
476+
if (y + h >= p->maxHeight) h = p->maxHeight - y;
477+
478+
x += p->x;
479+
y += p->y;
480+
481+
if (rgba[3] >= p->alphaThreshold) {
482+
p->tft->fillRect(x, y, w, h, color);
483+
}
484+
}
485+
486+
void M5Display::drawPngFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y,
487+
uint16_t maxWidth, uint16_t maxHeight, uint16_t offX,
488+
uint16_t offY, double scale, uint8_t alphaThreshold)
489+
{
490+
File file = fs.open(path);
491+
if (!file) {
492+
log_e("Failed to open file for reading");
493+
return ;
494+
}
495+
496+
pngle_t *pngle = pngle_new();
497+
498+
png_file_decoder_t png;
499+
500+
if (!maxWidth) {
501+
maxWidth = width() - x;
502+
}
503+
if (!maxHeight) {
504+
maxHeight = height() - y;
505+
}
506+
507+
png.x = x;
508+
png.y = y;
509+
png.maxWidth = maxWidth;
510+
png.maxHeight = maxHeight;
511+
png.offX = offX;
512+
png.offY = offY;
513+
png.scale = scale;
514+
png.alphaThreshold = alphaThreshold;
515+
png.tft = this;
516+
517+
pngle_set_user_data(pngle, &png);
518+
pngle_set_draw_callback(pngle, pngle_draw_callback);
519+
520+
// Feed data to pngle
521+
uint8_t buf[1024];
522+
int remain = 0;
523+
int len;
524+
while ((len = file.read(buf + remain, sizeof(buf) - remain)) > 0) {
525+
int fed = pngle_feed(pngle, buf, remain + len);
526+
if (fed < 0) {
527+
log_e("[pngle error] %s", pngle_error(pngle));
528+
break;
529+
}
530+
531+
remain = remain + len - fed;
532+
if (remain > 0) memmove(buf, buf + fed, remain);
533+
}
534+
535+
pngle_destroy(pngle);
536+
file.close();
537+
}
538+
539+
void M5Display::drawPngUrl(const char *url, uint16_t x, uint16_t y,
540+
uint16_t maxWidth, uint16_t maxHeight, uint16_t offX,
541+
uint16_t offY, double scale, uint8_t alphaThreshold)
542+
{
543+
HTTPClient http;
544+
545+
if (WiFi.status() != WL_CONNECTED) {
546+
log_e("Not connected");
547+
return ;
548+
}
549+
550+
http.begin(url);
551+
552+
int httpCode = http.GET();
553+
if (httpCode != HTTP_CODE_OK) {
554+
log_e("HTTP ERROR: %d\n", httpCode);
555+
http.end();
556+
return ;
557+
}
558+
559+
WiFiClient *stream = http.getStreamPtr();
560+
561+
pngle_t *pngle = pngle_new();
562+
563+
png_file_decoder_t png;
564+
565+
if (!maxWidth) {
566+
maxWidth = width() - x;
567+
}
568+
if (!maxHeight) {
569+
maxHeight = height() - y;
570+
}
571+
572+
573+
png.x = x;
574+
png.y = y;
575+
png.maxWidth = maxWidth;
576+
png.maxHeight = maxHeight;
577+
png.offX = offX;
578+
png.offY = offY;
579+
png.scale = scale;
580+
png.alphaThreshold = alphaThreshold;
581+
png.tft = this;
582+
583+
pngle_set_user_data(pngle, &png);
584+
pngle_set_draw_callback(pngle, pngle_draw_callback);
585+
586+
// Feed data to pngle
587+
uint8_t buf[1024];
588+
int remain = 0;
589+
int len;
590+
while (http.connected()) {
591+
size_t size = stream->available();
592+
if (!size) { delay(1); continue; }
593+
594+
if (size > sizeof(buf) - remain) size = sizeof(buf) - remain;
595+
if ((len = stream->readBytes(buf + remain, size)) > 0) {
596+
int fed = pngle_feed(pngle, buf, remain + len);
597+
if (fed < 0) {
598+
log_e("[pngle error] %s", pngle_error(pngle));
599+
break;
600+
}
601+
602+
remain = remain + len - fed;
603+
if (remain > 0) memmove(buf, buf + fed, remain);
604+
}
605+
}
606+
607+
pngle_destroy(pngle);
608+
http.end();
609+
}

src/M5Display.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@
8282
uint16_t offX = 0, uint16_t offY = 0,
8383
jpeg_div_t scale = JPEG_DIV_NONE);
8484

85+
void drawPngFile(fs::FS &fs, const char *path, uint16_t x = 0, uint16_t y = 0,
86+
uint16_t maxWidth = 0, uint16_t maxHeight = 0,
87+
uint16_t offX = 0, uint16_t offY = 0,
88+
double scale = 1.0, uint8_t alphaThreshold = 127);
89+
90+
void drawPngUrl(const char *url, uint16_t x = 0, uint16_t y = 0,
91+
uint16_t maxWidth = 0, uint16_t maxHeight = 0,
92+
uint16_t offX = 0, uint16_t offY = 0,
93+
double scale = 1.0, uint8_t alphaThreshold = 127);
94+
8595
private:
8696
};
8797
#endif

0 commit comments

Comments
 (0)