Partial speed up.

This commit is contained in:
nitko12 2020-09-10 08:04:45 +02:00
parent 82a082003a
commit c7e0781d21
14 changed files with 299 additions and 220 deletions

View File

@ -22,40 +22,48 @@
#include "Inkplate.h" //Include Inkplate library to the sketch
#include "SdFat.h" //Include library for SD card
Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome)
Inkplate display(
INKPLATE_1BIT); // Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome)
SdFile file; // Create SdFile object used for accessing files on SD card
void setup() {
void setup()
{
display.begin(); // Init Inkplate library (you should call this function ONLY ONCE)
display.clearDisplay(); // Clear frame buffer of display
display.display(); // Put clear image on display
// Init SD card. Display if SD card is init propery or not.
if (display.sdCardInit()) {
if (display.sdCardInit())
{
display.println("SD Card OK! Reading image...");
display.partialUpdate();
// If card is properly init, try to load image and display it on e-paper at position X=100, Y=0
// NOTE: These methods require you to pass a reference to the display object as first parameter.
//NOTE: Both drawJpegFromSD methods allow for an optional sixth "invert" parameter. Setting this parameter to true
//will flip all colors on the image, making black white and white black.
//fifth parameter will dither the image.
if (!display.drawJpegFromSD(&display, "pyramid.jpg", 100, 0, true, false)) {
// NOTE: Both drawJpegFromSd methods allow for an optional sixth "invert" parameter. Setting this parameter to
// true will flip all colors on the image, making black white and white black. fifth parameter will dither the
// image.
if (!display.drawJpegFromSd(&display, "pyramid.jpg", 100, 0, true, false))
{
// If is something failed (wrong filename or wrong format), write error message on the screen.
//You can turn off dithering for somewhat faster image load by changing the fifth parameter to false, or removing the parameter completely
// You can turn off dithering for somewhat faster image load by changing the fifth parameter to false, or
// removing the parameter completely
display.println("Image open error");
display.display();
}
display.display();
}
else {
else
{
// If SD card init not success, display error on screen and stop the program (using infinite loop)
display.println("SD Card error!");
display.partialUpdate();
while (true);
while (true)
;
}
}
void loop() {
void loop()
{
// Nothing...
}

View File

@ -98,6 +98,9 @@
Inkplate::Inkplate(uint8_t _mode) : GFX(E_INK_WIDTH, E_INK_HEIGHT)
{
setDisplayMode(_mode);
for (uint32_t i = 0; i < 256; ++i)
pinLUT[i] = ((i & B00000011) << 4) | (((i & B00001100) >> 2) << 18) | (((i & B00010000) >> 4) << 23) |
(((i & B11100000) >> 5) << 25);
}
void Inkplate::begin(void)
@ -141,19 +144,19 @@ void Inkplate::begin(void)
// Battery voltage Switch MOSFET
pinModeMCP(9, OUTPUT);
D_memory_new = (uint8_t *)ps_malloc(600 * 100);
DMemoryNew = (uint8_t *)ps_malloc(600 * 100);
_partial = (uint8_t *)ps_malloc(600 * 100);
_pBuffer = (uint8_t *)ps_malloc(120000);
D_memory4Bit = (uint8_t *)ps_malloc(240000);
if (D_memory_new == NULL || _partial == NULL || _pBuffer == NULL || D_memory4Bit == NULL)
if (DMemoryNew == NULL || _partial == NULL || _pBuffer == NULL || D_memory4Bit == NULL)
{
do
{
delay(100);
} while (true);
}
memset(D_memory_new, 0, 60000);
memset(DMemoryNew, 0, 60000);
memset(_partial, 0, 60000);
memset(_pBuffer, 0, 120000);
memset(D_memory4Bit, 255, 240000);
@ -189,11 +192,8 @@ void Inkplate::display()
void Inkplate::display1b()
{
for (int i = 0; i < 60000; i++)
{
*(D_memory_new + i) &= *(_partial + i);
*(D_memory_new + i) |= (*(_partial + i));
}
memcpy(DMemoryNew, _partial, 60000);
uint16_t _pos;
uint32_t _send;
uint8_t data;
@ -207,34 +207,30 @@ void Inkplate::display1b()
cleanFast(1, 12);
cleanFast(2, 1);
cleanFast(0, 11);
for (int k = 0; k < 3; k++)
for (int k = 0; k < 3; ++k)
{
_pos = 59999;
vscan_start();
for (int i = 0; i < 600; i++)
for (int i = 0; i < 600; ++i)
{
dram = *(D_memory_new + _pos);
dram = *(DMemoryNew + _pos);
data = LUTB[(dram >> 4) & 0x0F];
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
(((data & B11100000) >> 5) << 25);
_send = pinLUT[data];
hscan_start(_send);
data = LUTB[dram & 0x0F];
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
(((data & B11100000) >> 5) << 25);
_send = pinLUT[data];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
_pos--;
for (int j = 0; j < 99; j++)
for (int j = 0; j < 99; ++j)
{
dram = *(D_memory_new + _pos);
dram = *(DMemoryNew + _pos);
data = LUTB[(dram >> 4) & 0x0F];
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) |
(((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
_send = pinLUT[data];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
data = LUTB[dram & 0x0F];
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) |
(((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
_send = pinLUT[data];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
_pos--;
@ -248,30 +244,26 @@ void Inkplate::display1b()
_pos = 59999;
vscan_start();
for (int i = 0; i < 600; i++)
for (int i = 0; i < 600; ++i)
{
dram = *(D_memory_new + _pos);
dram = *(DMemoryNew + _pos);
data = LUT2[(dram >> 4) & 0x0F];
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
(((data & B11100000) >> 5) << 25);
_send = pinLUT[data];
hscan_start(_send);
data = LUT2[dram & 0x0F];
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
(((data & B11100000) >> 5) << 25);
_send = pinLUT[data];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
_pos--;
for (int j = 0; j < 99; j++)
for (int j = 0; j < 99; ++j)
{
dram = *(D_memory_new + _pos);
dram = *(DMemoryNew + _pos);
data = LUT2[(dram >> 4) & 0x0F];
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
(((data & B11100000) >> 5) << 25);
_send = pinLUT[data];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
data = LUT2[dram & 0x0F];
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
(((data & B11100000) >> 5) << 25);
_send = pinLUT[data];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
_pos--;
@ -283,18 +275,16 @@ void Inkplate::display1b()
delayMicroseconds(230);
vscan_start();
for (int i = 0; i < 600; i++)
for (int i = 0; i < 600; ++i)
{
dram = *(D_memory_new + _pos);
dram = *(DMemoryNew + _pos);
data = 0b00000000;
;
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
(((data & B11100000) >> 5) << 25);
_send = pinLUT[data];
hscan_start(_send);
data = 0b00000000;
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
for (int j = 0; j < 99; j++)
for (int j = 0; j < 99; ++j)
{
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
@ -338,8 +328,8 @@ void Inkplate::display3b()
vscan_start();
for (int i = 0; i < 600; ++i)
{
pixel = 0B00000000;
pixel2 = 0B00000000;
pixel = 0;
pixel2 = 0;
pix1 = *(dp--);
pix2 = *(dp--);
pix3 = *(dp--);
@ -349,19 +339,16 @@ void Inkplate::display3b()
pixel2 |= (waveform3Bit[pix3 & 0x07][k] << 6) | (waveform3Bit[(pix3 >> 4) & 0x07][k] << 4) |
(waveform3Bit[pix4 & 0x07][k] << 2) | (waveform3Bit[(pix4 >> 4) & 0x07][k] << 0);
_send = ((pixel & B00000011) << 4) | (((pixel & B00001100) >> 2) << 18) |
(((pixel & B00010000) >> 4) << 23) | (((pixel & B11100000) >> 5) << 25);
_send = pinLUT[pixel];
hscan_start(_send);
_send = ((pixel2 & B00000011) << 4) | (((pixel2 & B00001100) >> 2) << 18) |
(((pixel2 & B00010000) >> 4) << 23) | (((pixel2 & B11100000) >> 5) << 25);
_send = pinLUT[pixel2];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
for (int j = 0; j < 99; j++)
for (int j = 0; j < 99; ++j)
{
pixel = 0B00000000;
pixel2 = 0B00000000;
pixel = 0;
pixel2 = 0;
pix1 = *(dp--);
pix2 = *(dp--);
pix3 = *(dp--);
@ -371,13 +358,11 @@ void Inkplate::display3b()
pixel2 |= (waveform3Bit[pix3 & 0x07][k] << 6) | (waveform3Bit[(pix3 >> 4) & 0x07][k] << 4) |
(waveform3Bit[pix4 & 0x07][k] << 2) | (waveform3Bit[(pix4 >> 4) & 0x07][k] << 0);
_send = ((pixel & B00000011) << 4) | (((pixel & B00001100) >> 2) << 18) |
(((pixel & B00010000) >> 4) << 23) | (((pixel & B11100000) >> 5) << 25);
_send = pinLUT[pixel];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
_send = ((pixel2 & B00000011) << 4) | (((pixel2 & B00001100) >> 2) << 18) |
(((pixel2 & B00010000) >> 4) << 23) | (((pixel2 & B11100000) >> 5) << 25);
_send = pinLUT[pixel2];
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
}
@ -399,6 +384,7 @@ void Inkplate::partialUpdate()
return;
if (_blockPartial == 1)
display1b();
uint16_t _pos = 59999;
uint32_t _send;
uint8_t data;
@ -410,8 +396,8 @@ void Inkplate::partialUpdate()
{
for (int j = 0; j < 100; ++j)
{
diffw = ((*(D_memory_new + _pos)) ^ (*(_partial + _pos))) & (~(*(_partial + _pos)));
diffb = ((*(D_memory_new + _pos)) ^ (*(_partial + _pos))) & ((*(_partial + _pos)));
diffw = *(DMemoryNew + _pos) & ~*(_partial + _pos);
diffb = ~*(DMemoryNew + _pos) & *(_partial + _pos);
_pos--;
*(_pBuffer + n) = LUTW[diffw >> 4] & (LUTB[diffb >> 4]);
n--;
@ -428,20 +414,18 @@ void Inkplate::partialUpdate()
for (int i = 0; i < 600; ++i)
{
data = *(_pBuffer + n);
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
(((data & B11100000) >> 5) << 25);
_send = pinLUT[data];
hscan_start(_send);
n--;
for (int j = 0; j < 199; j++)
for (int j = 0; j < 199; ++j)
{
data = *(_pBuffer + n);
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) |
(((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
GPIO.out_w1ts = (_send) | CL;
_send = pinLUT[data];
GPIO.out_w1ts = _send | CL;
GPIO.out_w1tc = DATA | CL;
n--;
}
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1ts = _send | CL;
GPIO.out_w1tc = DATA | CL;
vscan_end();
}
@ -451,12 +435,8 @@ void Inkplate::partialUpdate()
cleanFast(3, 1);
vscan_start();
einkOff();
einkOff();
for (int i = 0; i < 60000; ++i)
{
*(D_memory_new + i) &= *(_partial + i);
*(D_memory_new + i) |= (*(_partial + i));
}
memcpy(DMemoryNew, _partial, 60000);
}
void Inkplate::clean()
@ -489,18 +469,16 @@ void Inkplate::cleanFast(uint8_t c, uint8_t rep)
else if (c == 3)
data = B11111111;
uint32_t _send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
(((data & B11100000) >> 5) << 25);
;
for (int k = 0; k < rep; k++)
uint32_t _send = pinLUT[data];
for (int k = 0; k < rep; ++k)
{
vscan_start();
for (int i = 0; i < 600; i++)
for (int i = 0; i < 600; ++i)
{
hscan_start(_send);
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;
for (int j = 0; j < 99; j++)
for (int j = 0; j < 99; ++j)
{
GPIO.out_w1ts = (_send) | CL;
GPIO.out_w1tc = DATA | CL;

View File

@ -38,10 +38,6 @@ class Inkplate : public System, public GFX
{
return Network::isConnected();
};
uint8_t *downloadFile(const char *url, int32_t defaultLen)
{
return Network::downloadFile(url, defaultLen);
};
private:
void precalculateGamma(uint8_t *c, float gamma);
@ -56,6 +52,7 @@ class Inkplate : public System, public GFX
void pinsZstate();
void pinsAsOutputs();
uint32_t pinLUT[256];
uint8_t _beginDone = 0;

View File

@ -172,7 +172,7 @@ void GFX::selectDisplayMode(uint8_t _mode)
if (_mode != _displayMode)
{
_displayMode = _mode & 1;
memset(D_memory_new, 0, 60000);
memset(DMemoryNew, 0, 60000);
memset(_partial, 0, 60000);
memset(_pBuffer, 0, 120000);
memset(D_memory4Bit, 255, 240000);

View File

@ -34,7 +34,7 @@ class GFX : public Shapes, public Image, public Font
void setRotation(uint8_t r);
uint8_t getRotation();
void drawPixel(int16_t x, int16_t y, uint16_t color) override;
inline void drawPixel(int16_t x, int16_t y, uint16_t color) override;
void selectDisplayMode(uint8_t _mode);
@ -43,7 +43,7 @@ class GFX : public Shapes, public Image, public Font
int16_t width() override;
int16_t height() override;
uint8_t *D_memory_new;
uint8_t *DMemoryNew;
uint8_t *_partial;
uint8_t *D_memory4Bit;
uint8_t *_pBuffer;
@ -65,7 +65,7 @@ class GFX : public Shapes, public Image, public Font
private:
void startWrite(void) override;
void writePixel(int16_t x, int16_t y, uint16_t color) override;
inline void writePixel(int16_t x, int16_t y, uint16_t color) override;
void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;

View File

@ -31,7 +31,7 @@ bool Image::drawImage(const char *path, int x, int y, bool dither, bool invert)
if (strstr(path, ".bmp") != NULL)
return drawBitmapFromSd(path, x, y, dither, invert);
if (strstr(path, ".jpg") != NULL || strstr(path, ".jpeg") != NULL)
return drawJpegFromSD(path, x, y, dither, invert);
return drawJpegFromSd(path, x, y, dither, invert);
}
};

View File

@ -28,17 +28,21 @@ class Image : virtual public Network
uint16_t bg = 0xFFFF);
void drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char *_p, int16_t _w, int16_t _h);
bool drawBitmapFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0);
bool drawBitmapFromBuffer(uint8_t *buf, int x, int y, bool dither, bool invert);
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 drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool dither = 0, bool invert = 0);
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 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 drawJpegFromBuffer(uint8_t *buf, int32_t len, int x, int y, bool dither, bool invert);
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 drawJpegFromWeb(const char *url, int x, int y, bool dither = 0, bool invert = 0);
bool drawJpegFromWeb(WiFiClient *s, int x, int y, int len, bool dither = 0, bool invert = 0);
bool drawJpegFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither = 0, bool invert = 0);
private:
@ -50,8 +54,7 @@ class Image : virtual public Network
virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) = 0;
virtual void endWrite(void) = 0;
static bool drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap, bool _dither,
bool _invert);
static bool drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap, bool dither, bool invert);
uint8_t pixelBuffer[800 * 4 + 5];
uint8_t ditherBuffer[2][800 + 5];
@ -60,9 +63,8 @@ class Image : virtual public Network
bool legalBmp(bitmapHeader *bmpHeader);
void ditherStart(uint8_t *pixelBuffer, uint8_t *bufferPtr, int w, bool invert, uint8_t bits);
void ditherLoadNextLine(uint8_t *pixelBuffer, uint8_t *bufferPtr, int w, bool invert, uint8_t bits);
uint8_t ditherGetPixel(uint8_t px, int i, int w, bool paletted);
uint8_t ditherGetPixelBmp(uint8_t px, int i, int w, bool paletted);
uint8_t ditherGetPixelJpeg(uint8_t px, int x, int y, int w);
void ditherSwap(int w);
void readBmpHeader(uint8_t *buf, bitmapHeader *_h);

View File

@ -92,14 +92,6 @@ bool Image::drawBitmapFromSd(SdFile *p, int x, int y, bool dither, bool invert)
if (!legalBmp(&bmpHeader))
return 0;
if (bmpHeader.color == 1 && getDisplayMode() != INKPLATE_1BIT)
selectDisplayMode(INKPLATE_1BIT);
if ((bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 16 || bmpHeader.color == 24 ||
bmpHeader.color == 32) &&
getDisplayMode() != INKPLATE_3BIT)
selectDisplayMode(INKPLATE_3BIT);
int16_t w = bmpHeader.width, h = bmpHeader.height;
int8_t c = bmpHeader.color;
@ -117,24 +109,38 @@ bool Image::drawBitmapFromSd(SdFile *p, int x, int y, bool dither, bool invert)
bool Image::drawBitmapFromWeb(const char *url, int x, int y, bool dither, bool invert)
{
uint8_t *buf = downloadFile(url, 800 * 600 * 4);
bool ret = 0;
int32_t defaultLen = 800 * 600 * 4;
uint8_t *buf = downloadFile(url, &defaultLen);
ret = drawBitmapFromBuffer(buf, x, y, dither, invert);
free(buf);
return 1;
}
bool Image::drawBitmapFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither, bool invert)
{
bool ret = 0;
uint8_t *buf = downloadFile(s, len);
ret = drawBitmapFromBuffer(buf, x, y, dither, invert);
free(buf);
return 1;
}
bool Image::drawBitmapFromBuffer(uint8_t *buf, int x, int y, bool dither, bool invert)
{
bitmapHeader bmpHeader;
readBmpHeader(buf, &bmpHeader);
if (!legalBmp(&bmpHeader))
return 0;
if (bmpHeader.color == 1 && getDisplayMode() != INKPLATE_1BIT)
selectDisplayMode(INKPLATE_1BIT);
if ((bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 16 || bmpHeader.color == 24 ||
bmpHeader.color == 32) &&
getDisplayMode() != INKPLATE_3BIT)
selectDisplayMode(INKPLATE_3BIT);
if (dither)
memset(ditherBuffer, 0, sizeof ditherBuffer);
uint8_t *bufferPtr = buf + bmpHeader.startRAW;
for (int i = 0; i < bmpHeader.height; ++i)
{
@ -144,7 +150,6 @@ bool Image::drawBitmapFromWeb(const char *url, int x, int y, bool dither, bool i
}
free(buf);
return 1;
}
@ -167,13 +172,14 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
uint8_t val;
if (dither)
val = ditherGetPixel(px, j, w, 1);
val = ditherGetPixelBmp(px, j, w, 1);
else
val = palette[px >> 1] & (px & 1 ? 0x0F : 0xF0) >> (px & 1 ? 0 : 4);
if (invert)
writePixel(x + j, y, 7 - val);
else
val = 7 - val;
if (getDisplayMode() == INKPLATE_1BIT)
val = (~val >> 2) & 1;
writePixel(x + j, y, val);
break;
}
@ -182,15 +188,14 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
uint8_t val;
if (dither)
val = ditherGetPixel(px, j, w, 1);
val = ditherGetPixelBmp(px, j, w, 1);
else
{
val = palette[px >> 1] & (px & 1 ? 0x0F : 0xF0) >> (px & 1 ? 0 : 4);
}
if (invert)
writePixel(x + j, y, 7 - val);
else
val = 7 - val;
if (getDisplayMode() == INKPLATE_1BIT)
val = (~val >> 2) & 1;
writePixel(x + j, y, val);
break;
}
@ -204,13 +209,14 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
uint8_t val;
if (dither)
val = ditherGetPixel(RGB8BIT(r, g, b), j, w, 0);
val = ditherGetPixelBmp(RGB8BIT(r, g, b), j, w, 0);
else
val = RGB3BIT(r, g, b);
if (invert)
writePixel(x + j, y, 7 - val);
else
val = 7 - val;
if (getDisplayMode() == INKPLATE_1BIT)
val = (~val >> 2) & 1;
writePixel(x + j, y, val);
break;
}
@ -222,13 +228,14 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
uint8_t val;
if (dither)
val = ditherGetPixel(RGB8BIT(r, g, b), j, w, 0);
val = ditherGetPixelBmp(RGB8BIT(r, g, b), j, w, 0);
else
val = RGB3BIT(r, g, b);
if (invert)
writePixel(x + j, y, 7 - val);
else
val = 7 - val;
if (getDisplayMode() == INKPLATE_1BIT)
val = (~val >> 2) & 1;
writePixel(x + j, y, val);
break;
}
@ -240,14 +247,15 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
uint8_t val;
if (dither)
val = ditherGetPixel(RGB8BIT(r, g, b), j, w, 0);
val = ditherGetPixelBmp(RGB8BIT(r, g, b), j, w, 0);
else
val = RGB3BIT(r, g, b);
if (invert)
writePixel(x + j, y, 7 - RGB3BIT(r, g, b));
else
writePixel(x + j, y, RGB3BIT(r, g, b));
val = 7 - val;
if (getDisplayMode() == INKPLATE_1BIT)
val = (~val >> 2) & 1;
writePixel(x + j, y, val);
break;
}
}

View File

@ -1,13 +1,13 @@
#include "Image.h"
uint8_t Image::ditherGetPixel(uint8_t px, int i, int w, bool paletted)
uint8_t Image::ditherGetPixelBmp(uint8_t px, int i, int w, bool paletted)
{
if (paletted)
px = ditherPalette[px];
uint8_t oldPixel = min((uint16_t)0xFF, (uint16_t)((uint16_t)ditherBuffer[0][i] + px));
uint8_t newPixel = oldPixel & B11100000;
uint8_t newPixel = oldPixel & (getDisplayMode() == INKPLATE_1BIT ? B10000000 : B11100000);
uint8_t quantError = oldPixel - newPixel;
ditherBuffer[1][i + 0] += (quantError * 5) >> 4;
@ -22,6 +22,25 @@ uint8_t Image::ditherGetPixel(uint8_t px, int i, int w, bool paletted)
return newPixel >> 5;
}
uint8_t Image::ditherGetPixelJpeg(uint8_t px, int x, int y, int w)
{
uint8_t oldPixel = min((uint16_t)0xFF, (uint16_t)((uint16_t)ditherBuffer[0][x] + px));
uint8_t newPixel = oldPixel & (getDisplayMode() == INKPLATE_1BIT ? B10000000 : B11100000);
uint8_t quantError = oldPixel - newPixel;
ditherBuffer[1][x + 0] += (quantError * 5) >> 4;
if (x != w - 1)
{
ditherBuffer[0][x + 1] += (quantError * 7) >> 4;
ditherBuffer[1][x + 1] += (quantError * 1) >> 4;
}
if (x != 0)
ditherBuffer[1][x - 1] += (quantError * 3) >> 4;
return newPixel >> 5;
}
void Image::ditherSwap(int w)
{
for (int i = 0; i < w; ++i)

View File

@ -8,7 +8,81 @@
extern Image *_imagePtrJpeg;
bool Image::drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap, bool _dither, bool _invert)
bool Image::drawJpegFromSd(const char *fileName, int x, int y, bool dither, bool invert)
{
SdFile dat;
if (dat.open(fileName, O_RDONLY))
return drawJpegFromSd(&dat, x, y, dither, invert);
return 0;
}
bool Image::drawJpegFromSd(SdFile *p, int x, int y, bool dither, bool invert)
{
uint8_t ret = 0;
TJpgDec.setJpgScale(1);
TJpgDec.setCallback(drawJpegChunk);
uint32_t pnt = 0;
uint32_t total = p->fileSize();
uint8_t *buff = (uint8_t *)ps_malloc(total);
if (buff == NULL)
return 0;
while (pnt < total)
{
uint32_t toread = p->available();
if (toread > 0)
{
int read = p->read(buff + pnt, toread);
if (read > 0)
pnt += read;
}
}
p->close();
if (TJpgDec.drawJpg(x, y, buff, total, dither, invert) == 0)
ret = 1;
free(buff);
return ret;
}
bool Image::drawJpegFromWeb(const char *url, int x, int y, bool dither, bool invert)
{
bool ret = 0;
int32_t defaultLen = 800 * 600 * 4;
uint8_t *buff = downloadFile(url, &defaultLen);
ret = drawJpegFromBuffer(buff, x, y, defaultLen, dither, invert);
free(buff);
return ret;
}
bool Image::drawJpegFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither, bool invert)
{
bool ret = 0;
uint8_t *buff = downloadFile(s, len);
ret = drawJpegFromBuffer(buff, x, y, len, dither, invert);
free(buff);
return ret;
}
bool Image::drawJpegFromBuffer(uint8_t *buff, int32_t len, int x, int y, bool dither, bool invert)
{
bool ret = 0;
if (TJpgDec.drawJpg(x, y, buff, len, dither, invert) == 0)
ret = 1;
return ret;
};
bool Image::drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap, bool dither, bool invert)
{
if (!_imagePtrJpeg)
return 0;
@ -19,57 +93,15 @@ bool Image::drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t
for (int i = 0; i < w; ++i)
{
uint16_t rgb = bitmap[j * w + i];
if (_invert)
_imagePtrJpeg->drawPixel(i + x, j + y, 7 - RGB3BIT(RED(rgb), GREEN(rgb), BLUE(rgb)));
else
_imagePtrJpeg->drawPixel(i + x, j + y, RGB3BIT(RED(rgb), GREEN(rgb), BLUE(rgb)));
uint8_t val = RGB3BIT(RED(rgb), GREEN(rgb), BLUE(rgb));
if (invert)
val = 7 - val;
_imagePtrJpeg->writePixel(x + i, y + j, val);
}
}
_imagePtrJpeg->endWrite();
return 1;
}
bool Image::drawJpegFromSD(const char *fileName, int x, int y, bool dither, bool invert)
{
SdFile dat;
if (dat.open(fileName, O_RDONLY))
return drawJpegFromSD(&dat, x, y, dither, invert);
return 0;
}
bool Image::drawJpegFromSD(SdFile *p, int x, int y, bool dither, bool invert)
{
uint8_t ret = 0;
TJpgDec.setJpgScale(1);
TJpgDec.setCallback(drawJpegChunk);
uint32_t pnt = 0;
uint32_t total = p->fileSize();
uint8_t *buf = (uint8_t *)ps_malloc(total);
if (buf == NULL)
return 0;
while (pnt < total)
{
uint32_t toread = p->available();
if (toread > 0)
{
int read = p->read(buf + pnt, toread);
if (read > 0)
pnt += read;
}
}
p->close();
selectDisplayMode(INKPLATE_3BIT);
if (TJpgDec.drawJpg(x, y, buf, total, dither, invert) == 0)
ret = 1;
free(buf);
return ret;
}

View File

@ -28,7 +28,7 @@ bool Network::isConnected()
}
uint8_t *Network::downloadFile(const char *url, int32_t defaultLen)
uint8_t *Network::downloadFile(const char *url, int32_t *defaultLen)
{
if (!isConnected())
return NULL;
@ -45,7 +45,9 @@ uint8_t *Network::downloadFile(const char *url, int32_t defaultLen)
int32_t size = http.getSize();
if (size == -1)
size = defaultLen;
size = *defaultLen;
else
*defaultLen = size;
uint8_t *buffer = (uint8_t *)ps_malloc(size);
uint8_t *buffPtr = buffer;
@ -79,3 +81,36 @@ uint8_t *Network::downloadFile(const char *url, int32_t defaultLen)
return buffer;
}
uint8_t *Network::downloadFile(WiFiClient *s, int32_t len)
{
if (!isConnected())
return NULL;
bool sleep = WiFi.getSleep();
WiFi.setSleep(false);
uint8_t *buffer = (uint8_t *)ps_malloc(len);
uint8_t *buffPtr = buffer;
uint8_t buff[128] = {0};
while (len > 0)
{
size_t size = s->available();
if (size)
{
int c = s->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
memcpy(buffPtr, buff, c);
if (len > 0)
len -= c;
buffPtr += c;
}
yield();
}
WiFi.setSleep(sleep);
return buffer;
}

View File

@ -25,7 +25,8 @@ class Network
void disconnect();
bool isConnected();
uint8_t *downloadFile(const char *url, int32_t defaultLen);
uint8_t *downloadFile(const char *url, int32_t *defaultLen);
uint8_t *downloadFile(WiFiClient *url, int32_t len);
private:
};

View File

@ -14,11 +14,12 @@ void setup()
void loop()
{
int32_t t = millis();
display.drawBitmap(offSet, 0, (uint8_t *)bck_day, bck_day_w, bck_day_h, BLACK);
int32_t t = millis();
display.partialUpdate();
display.clearDisplay();
Serial.println(millis() - t);
display.clearDisplay();
offSet += 70;
offSet %= 300;
}

View File

@ -1,6 +1,6 @@
#include "Inkplate.h"
#include "SdFat.h"
Inkplate display(INKPLATE_3BIT);
Inkplate display(INKPLATE_1BIT);
void setup()
{
@ -30,9 +30,7 @@ void loop()
if (display.sdCardInit())
{
int16_t t = millis();
Serial.println(display.drawBitmapFromSd("Lenna.bmp", 0, 0, 1, 0));
Serial.println(millis() - t);
}
display.display();