Added PNG and, adding tests.

This commit is contained in:
nitko12 2020-09-18 10:16:14 +02:00
parent 57a406f57a
commit 1fd65df81b
61 changed files with 269 additions and 76 deletions

View File

@ -1,17 +1,16 @@
#include "Image.h" #include "Image.h"
#include "../libs/TJpeg/TJpg_Decoder.h" #include "../libs/TJpeg/TJpg_Decoder.h"
#include "defines.h"
#include "pgmspace.h" #include "pgmspace.h"
#define RED(a) ((((a)&0xf800) >> 11) << 3)
#define GREEN(a) ((((a)&0x07e0) >> 5) << 2)
#define BLUE(a) (((a)&0x001f) << 3)
Image *_imagePtrJpeg = nullptr; Image *_imagePtrJpeg = nullptr;
Image *_imagePtrPng = nullptr;
Image::Image(int16_t w, int16_t h) : Adafruit_GFX(w, h) Image::Image(int16_t w, int16_t h) : Adafruit_GFX(w, h)
{ {
_imagePtrJpeg = this; _imagePtrJpeg = this;
_imagePtrPng = this;
} }
bool Image::drawImage(const String path, int x, int y, bool dither, bool invert) bool Image::drawImage(const String path, int x, int y, bool dither, bool invert)
@ -28,7 +27,7 @@ bool Image::drawImage(const char *path, int x, int y, bool dither, bool invert)
if (strstr(path, ".jpg") != NULL || strstr(path, ".jpeg") != NULL) if (strstr(path, ".jpg") != NULL || strstr(path, ".jpeg") != NULL)
return drawJpegFromWeb(path, x, y, dither, invert); return drawJpegFromWeb(path, x, y, dither, invert);
if (strstr(path, ".png") != NULL) if (strstr(path, ".png") != NULL)
return drawJpegFromWeb(path, x, y, dither, invert); return drawPngFromWeb(path, x, y, dither, invert);
} }
else else
{ {
@ -37,7 +36,7 @@ bool Image::drawImage(const char *path, int x, int y, bool dither, bool invert)
if (strstr(path, ".jpg") != NULL || strstr(path, ".jpeg") != NULL) if (strstr(path, ".jpg") != NULL || strstr(path, ".jpeg") != NULL)
return drawJpegFromSd(path, x, y, dither, invert); return drawJpegFromSd(path, x, y, dither, invert);
if (strstr(path, ".png") != NULL) if (strstr(path, ".png") != NULL)
return drawJpegFromSd(path, x, y, dither, invert); return drawPngFromSd(path, x, y, dither, invert);
} }
return 0; return 0;
}; };

View File

@ -10,7 +10,7 @@
class Image : virtual public NetworkClient, virtual public Adafruit_GFX class Image : virtual public NetworkClient, virtual public Adafruit_GFX
{ {
public: public:
Image(int16_t w, int16_t h); Image(int16_t w, int16_t h);
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0; virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
@ -33,27 +33,45 @@ public:
bool drawBitmapFromBuffer(uint8_t *buf, int x, int y, bool dither, bool invert); bool drawBitmapFromBuffer(uint8_t *buf, int x, int y, bool dither, bool invert);
[[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawBitmapFromSd(const char *fileName, int x, int y, bool dither = 0, bool invert = 0); [[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawBitmapFromSd(
const char *fileName, int x, int y, bool dither = 0, bool invert = 0);
bool drawBitmapFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0); bool drawBitmapFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0);
[[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawBitmapFromWeb(const char *url, int x, int y, bool dither = 0, bool invert = 0); [[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawBitmapFromWeb(const char *url,
int x, int y,
bool dither = 0,
bool invert = 0);
bool drawBitmapFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither = 0, bool invert = 0); bool drawBitmapFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither = 0, bool invert = 0);
bool drawJpegFromBuffer(uint8_t *buf, int32_t len, int x, int y, bool dither, bool invert); bool drawJpegFromBuffer(uint8_t *buf, int32_t len, int x, int y, bool dither, bool invert);
[[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawJpegFromSd(const char *fileName, int x, int y, bool dither = 0, bool invert = 0); [[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawJpegFromSd(
const char *fileName, int x, int y, bool dither = 0, bool invert = 0);
bool drawJpegFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0); bool drawJpegFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0);
[[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawJpegFromWeb(const char *url, int x, int y, bool dither = 0, bool invert = 0); [[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawJpegFromWeb(const char *url,
int x, int y,
bool dither = 0,
bool invert = 0);
bool drawJpegFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither = 0, bool invert = 0); bool drawJpegFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither = 0, bool invert = 0);
[[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawPngFromSd(const char *fileName, int x, int y, bool dither = 0, bool invert = 0); [[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawPngFromSd(const char *fileName,
int x, int y,
bool dither = 0,
bool invert = 0);
bool drawPngFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0); bool drawPngFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0);
[[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawPngFromWeb(const char *url, int x, int y, bool dither = 0, bool invert = 0); [[deprecated("Use drawImage, as this will soon become a private method.")]] bool drawPngFromWeb(const char *url,
int x, int y,
bool dither = 0,
bool invert = 0);
bool drawPngFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither = 0, bool invert = 0); bool drawPngFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither = 0, bool invert = 0);
private: // Should be private, but needed in a png callback :(
void ditherSwap(int w);
uint8_t ditherGetPixelBmp(uint8_t px, int i, int w, bool paletted);
private:
virtual void startWrite(void) = 0; virtual void startWrite(void) = 0;
virtual void writePixel(int16_t x, int16_t y, uint16_t color) = 0; virtual void writePixel(int16_t x, int16_t y, uint16_t color) = 0;
virtual void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) = 0; virtual void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) = 0;
@ -75,9 +93,7 @@ private:
bool legalBmp(bitmapHeader *bmpHeader); bool legalBmp(bitmapHeader *bmpHeader);
uint8_t ditherGetPixelBmp(uint8_t px, int i, int w, bool paletted);
uint8_t ditherGetPixelJpeg(uint8_t px, int i, int j, int x, int y, int w, int h); uint8_t ditherGetPixelJpeg(uint8_t px, int i, int j, int x, int y, int w, int h);
void ditherSwap(int w);
void ditherSwapBlockJpeg(int x); void ditherSwapBlockJpeg(int x);
void readBmpHeader(uint8_t *buf, bitmapHeader *_h); void readBmpHeader(uint8_t *buf, bitmapHeader *_h);

View File

@ -73,7 +73,6 @@ void Image::readBmpHeader(uint8_t *buf, bitmapHeader *_h)
} }
}; };
bool Image::drawBitmapFromSd(const char *fileName, int x, int y, bool dither, bool invert) bool Image::drawBitmapFromSd(const char *fileName, int x, int y, bool dither, bool invert)
{ {
SdFile dat; SdFile dat;
@ -167,7 +166,8 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
writePixel(x + j, y, (invert ^ (palette[0] < palette[1])) ^ !!(pixelBuffer[j >> 3] & (1 << (7 - (j & 7))))); writePixel(x + j, y, (invert ^ (palette[0] < palette[1])) ^ !!(pixelBuffer[j >> 3] & (1 << (7 - (j & 7)))));
break; break;
// as for 2 bit, literally cannot find an example online or in PS, so skipped // as for 2 bit, literally cannot find an example online or in PS, so skipped
case 4: { case 4:
{
uint8_t px = pixelBuffer[j >> 1] & (j & 1 ? 0x0F : 0xF0) >> (j & 1 ? 0 : 4); uint8_t px = pixelBuffer[j >> 1] & (j & 1 ? 0x0F : 0xF0) >> (j & 1 ? 0 : 4);
uint8_t val; uint8_t val;
@ -183,7 +183,8 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
writePixel(x + j, y, val); writePixel(x + j, y, val);
break; break;
} }
case 8: { case 8:
{
uint8_t px = pixelBuffer[j]; uint8_t px = pixelBuffer[j];
uint8_t val; uint8_t val;
@ -199,7 +200,8 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
writePixel(x + j, y, val); writePixel(x + j, y, val);
break; break;
} }
case 16: { case 16:
{
uint16_t px = ((uint16_t)pixelBuffer[(j << 1) | 1] << 8) | pixelBuffer[(j << 1)]; uint16_t px = ((uint16_t)pixelBuffer[(j << 1) | 1] << 8) | pixelBuffer[(j << 1)];
uint8_t r = (px & 0x7C00) >> 7; uint8_t r = (px & 0x7C00) >> 7;
@ -220,7 +222,8 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
writePixel(x + j, y, val); writePixel(x + j, y, val);
break; break;
} }
case 24: { case 24:
{
uint8_t r = pixelBuffer[j * 3]; uint8_t r = pixelBuffer[j * 3];
uint8_t g = pixelBuffer[j * 3 + 1]; uint8_t g = pixelBuffer[j * 3 + 1];
uint8_t b = pixelBuffer[j * 3 + 2]; uint8_t b = pixelBuffer[j * 3 + 2];

View File

@ -1,23 +1,138 @@
#include "Image.h" #include "Image.h"
#include "../libs/pngle/pngle.h" #include "../libs/pngle/pngle.h"
#include "defines.h"
extern Image *_imagePtrPng;
static bool _pngInvert = 0;
static bool _pngDither = 0;
static int16_t lastY = -1;
void pngle_on_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4])
{
if (rgba[3])
for (int j = 0; j < h; ++j)
for (int i = 0; i < w; ++i)
{
uint8_t px = RGB3BIT(rgba[0], rgba[1], rgba[2]);
if (_pngDither)
px = _imagePtrPng->ditherGetPixelBmp(RGB8BIT(rgba[0], rgba[1], rgba[2]), x + i,
_imagePtrPng->width(), 0);
if (_pngInvert)
px = 7 - px;
if (_imagePtrPng->getDisplayMode() == INKPLATE_1BIT)
px = (~px >> 2) & 1;
_imagePtrPng->drawPixel(x + i, y + j, px);
}
if (lastY != y)
{
lastY = y;
_imagePtrPng->ditherSwap(_imagePtrPng->width());
}
}
bool Image::drawPngFromSd(const char *fileName, int x, int y, bool dither, bool invert) bool Image::drawPngFromSd(const char *fileName, int x, int y, bool dither, bool invert)
{ {
SdFile dat;
if (dat.open(fileName, O_RDONLY))
{
return drawPngFromSd(&dat, x, y, dither, invert);
}
return 0; return 0;
} }
bool Image::drawPngFromSd(SdFile *p, int x, int y, bool dither, bool invert) bool Image::drawPngFromSd(SdFile *p, int x, int y, bool dither, bool invert)
{ {
return 0; _pngDither = dither;
_pngInvert = invert;
lastY = y;
bool ret = 1;
uint32_t remain = 0;
if (dither)
memset(ditherBuffer, 0, sizeof ditherBuffer);
pngle_t *pngle = pngle_new();
pngle_set_draw_callback(pngle, pngle_on_draw);
uint32_t total = p->fileSize();
uint8_t buff[2048];
uint32_t pnt = 0;
while (pnt < total)
{
uint32_t toread = p->available();
if (toread > 0)
{
int len = p->read(buff, min((uint32_t)2048, toread));
int fed = pngle_feed(pngle, buff, len);
if (fed < 0)
{
ret = 0;
break;
}
remain = remain + len - fed;
pnt += len;
}
}
p->close();
pngle_destroy(pngle);
return ret;
} }
bool Image::drawPngFromWeb(const char *url, int x, int y, bool dither, bool invert) bool Image::drawPngFromWeb(const char *url, int x, int y, bool dither, bool invert)
{ {
return 0; _pngDither = dither;
_pngInvert = invert;
lastY = y;
bool ret = 1;
if (dither)
memset(ditherBuffer, 0, sizeof ditherBuffer);
pngle_t *pngle = pngle_new();
pngle_set_draw_callback(pngle, pngle_on_draw);
int32_t defaultLen = 800 * 600 * 4 + 100;
uint8_t *buff = downloadFile(url, &defaultLen);
if (!buff)
return 0;
if (pngle_feed(pngle, buff, defaultLen) < 0)
ret = 0;
pngle_destroy(pngle);
free(buff);
return ret;
} }
bool Image::drawPngFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither, bool invert) bool Image::drawPngFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither, bool invert)
{ {
return 0; _pngDither = dither;
_pngInvert = invert;
lastY = y;
bool ret = 1;
if (dither)
memset(ditherBuffer, 0, sizeof ditherBuffer);
pngle_t *pngle = pngle_new();
pngle_set_draw_callback(pngle, pngle_on_draw);
uint8_t *buff = downloadFile(s, len);
if (!buff)
return 0;
if (pngle_feed(pngle, buff, len) < 0)
ret = 0;
pngle_destroy(pngle);
free(buff);
return ret;
} }

View File

@ -22,4 +22,8 @@
#define READ16(c) (uint16_t)(*(c) | (*((c) + 1) << 8)) #define READ16(c) (uint16_t)(*(c) | (*((c) + 1) << 8))
#define ROWSIZE(w, c) (((int16_t)c * w + 31) >> 5) << 2 #define ROWSIZE(w, c) (((int16_t)c * w + 31) >> 5) << 2
#define RED(a) ((((a)&0xf800) >> 11) << 3)
#define GREEN(a) ((((a)&0x07e0) >> 5) << 2)
#define BLUE(a) (((a)&0x001f) << 3)
#endif #endif

BIN
test/drawImage/Lenna.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -8,9 +8,9 @@ Inkplate display(INKPLATE_1BIT);
#define DELAYMS 1000 #define DELAYMS 1000
const char *images[] = {"1bit.bmp", "4bit.bmp", "8bit.bmp", "16bit.bmp", const char *imagesBmp[] = {"1bit.bmp", "4bit.bmp", "8bit.bmp", "16bit.bmp",
"24bit.bmp", "32bit.bmp", "Lenna.jpg", "Lenna.jpg"}; "24bit.bmp", "32bit.bmp", "Lenna.jpg", "Lenna.jpg"};
const char *imageUrls[] = { const char *imagesBmpUrls[] = {
"https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/1bit.bmp", "https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/1bit.bmp",
"https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/4bit.bmp", "https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/4bit.bmp",
"https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/8bit.bmp", "https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/8bit.bmp",
@ -86,14 +86,16 @@ void loop()
bool dither = i & 1; bool dither = i & 1;
bool invert = i >> 1; bool invert = i >> 1;
for (int j = 0; j < 6; ++j) for (int i = 0; i < 4; ++i)
{ {
display.selectDisplayMode(depth[j]); bool dither = i & 1;
bool invert = i >> 1;
display.selectDisplayMode(INKPLATE_1BIT);
display.setTextSize(2); display.setTextSize(2);
display.setTextColor(1); display.setTextColor(1);
display.setCursor(100, 100); display.setCursor(100, 100);
display.print("Displaying "); display.print("Displaying Lenna.jpg 1bit");
display.print(images[j]);
if (!dither) if (!dither)
display.print(" non"); display.print(" non");
display.print(" dithered and"); display.print(" dithered and");
@ -105,27 +107,22 @@ void loop()
display.clearDisplay(); display.clearDisplay();
delay(5000); delay(5000);
display.drawImage(images[j], 0, 0, dither, invert); display.drawImage("Lenna.jpg", 0, 0, dither, invert);
display.display(); display.display();
display.clearDisplay(); display.clearDisplay();
delay(5000); delay(5000);
} }
}
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{
bool dither = i & 1;
bool invert = i >> 1;
for (int j = 0; j < 6; ++j)
{ {
display.selectDisplayMode(depth[j]); bool dither = i & 1;
bool invert = i >> 1;
display.selectDisplayMode(INKPLATE_3BIT);
display.setTextSize(2); display.setTextSize(2);
display.setTextColor(1); display.setTextColor(1);
display.setCursor(100, 100); display.setCursor(100, 100);
display.print("Displaying "); display.print("Displaying Lenna.jpg 3bit");
display.print(images[j]);
display.print(" from web");
if (!dither) if (!dither)
display.print(" non"); display.print(" non");
display.print(" dithered and"); display.print(" dithered and");
@ -137,12 +134,97 @@ void loop()
display.clearDisplay(); display.clearDisplay();
delay(5000); delay(5000);
display.drawImage(imageUrls[j], 0, 0, dither, invert); display.drawImage("Lenna.jpg", 0, 0, dither, invert);
display.display(); display.display();
display.clearDisplay(); display.clearDisplay();
delay(5000); delay(5000);
} }
}
delay(5000); for (int i = 0; i < 4; ++i)
} {
bool dither = i & 1;
bool invert = i >> 1;
display.selectDisplayMode(INKPLATE_1BIT);
display.setTextSize(2);
display.setTextColor(1);
display.setCursor(100, 100);
display.print("Displaying png.png 1bit");
if (!dither)
display.print(" non");
display.print(" dithered and");
if (!invert)
display.print(" non");
display.print(" inverted.");
display.display();
display.clearDisplay();
delay(5000);
display.drawImage("png.jpg", 0, 0, dither, invert);
display.display();
display.clearDisplay();
delay(5000);
}
for (int i = 0; i < 4; ++i)
{
bool dither = i & 1;
bool invert = i >> 1;
display.selectDisplayMode(INKPLATE_3BIT);
display.setTextSize(2);
display.setTextColor(1);
display.setCursor(100, 100);
display.print("Displaying png.png 3bit");
if (!dither)
display.print(" non");
display.print(" dithered and");
if (!invert)
display.print(" non");
display.print(" inverted.");
display.display();
display.clearDisplay();
delay(5000);
display.drawImage("png.jpg", 0, 0, dither, invert);
display.display();
display.clearDisplay();
delay(5000);
}
for (int i = 0; i < 4; ++i)
{
bool dither = i & 1;
bool invert = i >> 1;
for (int j = 0; j < 6; ++j)
{
display.selectDisplayMode(depth[j]);
display.setTextSize(2);
display.setTextColor(1);
display.setCursor(100, 100);
display.print("Displaying ");
display.print(images[j]);
display.print(" from web");
if (!dither)
display.print(" non");
display.print(" dithered and");
if (!invert)
display.print(" non");
display.print(" inverted.");
display.display();
display.clearDisplay();
delay(5000);
display.drawImage(imageUrls[j], 0, 0, dither, invert);
display.display();
display.clearDisplay();
delay(5000);
}
}
delay(5000);
}

BIN
test/drawImage/png.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 KiB

View File

@ -3,7 +3,7 @@
const int n = 500; const int n = 500;
Inkplate display(INKPLATE_1BIT); Inkplate display(INKPLATE_3BIT);
void setup() void setup()
{ {
@ -13,7 +13,6 @@ void setup()
display.joinAP("e-radionica.com", "croduino"); display.joinAP("e-radionica.com", "croduino");
Serial.println("aaaa");
delay(500); delay(500);
} }
@ -21,34 +20,9 @@ void loop()
{ {
display.clearDisplay(); display.clearDisplay();
// Code block for generating random points and sorting them in a counter display.sdCardInit();
// clockwise direction. display.drawPngFromSd("png.png", 0, 0, 1, 0);
int xt[n];
int yt[n];
for (int i = 0; i < n; ++i)
{
xt[i] = random(100, 700);
yt[i] = random(100, 500);
}
int k;
for (int i = 0; i < n - 1; ++i)
for (int j = i + 1; j < n; ++j)
if (atan2(yt[j] - 300, xt[j] - 400) < atan2(yt[i] - 300, xt[i] - 400))
{
k = xt[i], xt[i] = xt[j], xt[j] = k;
k = yt[i], yt[i] = yt[j], yt[j] = k;
}
display.clearDisplay();
display.drawPolygon(xt, yt, n, 1);
display.display();
delay(5000);
display.clearDisplay();
display.fillPolygon(xt, yt, n, 1);
display.display(); display.display();
delay(5000); delay(5000);
} }