Update Inkplate.cpp
This commit is contained in:
parent
5e961c5d0c
commit
8d19ff62ce
380
Inkplate.cpp
380
Inkplate.cpp
|
@ -1,8 +1,9 @@
|
||||||
#include "Inkplate.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "Adafruit_GFX.h"
|
#include "Adafruit_GFX.h"
|
||||||
|
#include "WiFi.h"
|
||||||
|
#include "HTTPClient.h"
|
||||||
|
#include "Inkplate.h"
|
||||||
Adafruit_MCP23017 mcp;
|
Adafruit_MCP23017 mcp;
|
||||||
SPIClass spi2(HSPI);
|
SPIClass spi2(HSPI);
|
||||||
SdFat sd(&spi2);
|
SdFat sd(&spi2);
|
||||||
|
@ -87,12 +88,12 @@ void Inkplate::begin(void) {
|
||||||
|
|
||||||
//Draw function, used by Adafruit GFX.
|
//Draw function, used by Adafruit GFX.
|
||||||
void Inkplate::drawPixel(int16_t x0, int16_t y0, uint16_t color) {
|
void Inkplate::drawPixel(int16_t x0, int16_t y0, uint16_t color) {
|
||||||
if (x0 > _width - 1 || y0 > _height - 1 || x0 < 0 || y0 < 0) return;
|
if (x0 > 799 || y0 > 599 || x0 < 0 || y0 < 0) return;
|
||||||
|
|
||||||
switch (_rotation) {
|
switch (_rotation) {
|
||||||
case 1:
|
case 1:
|
||||||
_swap_int16_t(x0, y0);
|
_swap_int16_t(x0, y0);
|
||||||
x0 = _height - x0 - 1;
|
x0 = _width - x0 - 1;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
x0 = _width - x0 - 1;
|
x0 = _width - x0 - 1;
|
||||||
|
@ -237,7 +238,7 @@ void Inkplate::drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char* _p, i
|
||||||
|
|
||||||
void Inkplate::setRotation(uint8_t r) {
|
void Inkplate::setRotation(uint8_t r) {
|
||||||
_rotation = r % 4;
|
_rotation = r % 4;
|
||||||
switch (_rotation) {
|
switch (rotation) {
|
||||||
case 0:
|
case 0:
|
||||||
_width = E_INK_WIDTH;
|
_width = E_INK_WIDTH;
|
||||||
_height = E_INK_HEIGHT;
|
_height = E_INK_HEIGHT;
|
||||||
|
@ -329,13 +330,13 @@ uint8_t Inkplate::getDisplayMode() {
|
||||||
return _displayMode;
|
return _displayMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inkplate::drawBitmapFromSD(SdFile* p, int x, int y) {
|
int Inkplate::drawBitmapFromSD(SdFile* p, int x, int y, bool invert) {
|
||||||
if(sdCardOk == 0) return 0;
|
if(sdCardOk == 0) return 0;
|
||||||
struct bitmapHeader bmpHeader;
|
struct bitmapHeader bmpHeader;
|
||||||
readBmpHeader(p, &bmpHeader);
|
readBmpHeaderSd(p, &bmpHeader);
|
||||||
if (bmpHeader.signature != 0x4D42 || bmpHeader.compression != 0 || !(bmpHeader.color == 1 || bmpHeader.color == 24)) return 0;
|
if (bmpHeader.signature != 0x4D42 || bmpHeader.compression != 0 || !(bmpHeader.color == 1 || bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 24)) return 0;
|
||||||
|
|
||||||
if ((bmpHeader.color == 24 || bmpHeader.color == 32) && getDisplayMode() != INKPLATE_3BIT) {
|
if ((bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 24 || bmpHeader.color == 32) && getDisplayMode() != INKPLATE_3BIT) {
|
||||||
selectDisplayMode(INKPLATE_3BIT);
|
selectDisplayMode(INKPLATE_3BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,68 +344,71 @@ int Inkplate::drawBitmapFromSD(SdFile* p, int x, int y) {
|
||||||
selectDisplayMode(INKPLATE_1BIT);
|
selectDisplayMode(INKPLATE_1BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bmpHeader.color == 1) drawMonochromeBitmap(p, bmpHeader, x, y);
|
if (bmpHeader.color == 1) drawMonochromeBitmapSd(p, bmpHeader, x, y, invert);
|
||||||
if (bmpHeader.color == 24) drawGrayscaleBitmap24(p, bmpHeader, x, y);
|
if (bmpHeader.color == 4) drawGrayscaleBitmap4Sd(p, bmpHeader, x, y, invert);
|
||||||
|
if (bmpHeader.color == 8) drawGrayscaleBitmap8Sd(p, bmpHeader, x, y, invert);
|
||||||
|
if (bmpHeader.color == 24) drawGrayscaleBitmap24Sd(p, bmpHeader, x, y, invert);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inkplate::drawBitmapFromSD(char* fileName, int x, int y) {
|
int Inkplate::drawBitmapFromSD(char* fileName, int x, int y, bool invert) {
|
||||||
if(sdCardOk == 0) return 0;
|
if(sdCardOk == 0) return 0;
|
||||||
SdFile dat;
|
SdFile dat;
|
||||||
if (dat.open(fileName, O_RDONLY)) {
|
if (dat.open(fileName, O_RDONLY)) {
|
||||||
return drawBitmapFromSD(&dat, x, y);
|
return drawBitmapFromSD(&dat, x, y, invert);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inkplate::drawThickLine(int x1, int y1, int x2, int y2, int color, float thickness)
|
int Inkplate::drawBitmapFromWeb(WiFiClient* s, int x, int y, int len, bool invert) {
|
||||||
{
|
struct bitmapHeader bmpHeader;
|
||||||
float deg = atan2f((float)(y2 - y1), (float)(x2 - x1));
|
readBmpHeaderWeb(s, &bmpHeader);
|
||||||
|
if (bmpHeader.signature != 0x4D42 || bmpHeader.compression != 0 || !(bmpHeader.color == 1 || bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 24)) return 0;
|
||||||
|
|
||||||
float l1 = tan(deg);
|
if ((bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 24 || bmpHeader.color == 32) && getDisplayMode() != INKPLATE_3BIT) {
|
||||||
float k1 = (float)y1 - l1 * (float)x1;
|
selectDisplayMode(INKPLATE_3BIT);
|
||||||
|
}
|
||||||
|
|
||||||
float degShift = (l1 < 0 ? M_PI_2 : -M_PI_2);
|
if (bmpHeader.color == 1 && getDisplayMode() != INKPLATE_1BIT) {
|
||||||
|
selectDisplayMode(INKPLATE_1BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bmpHeader.color == 1) drawMonochromeBitmapWeb(s, bmpHeader, x, y, len, invert);
|
||||||
|
if (bmpHeader.color == 4) drawGrayscaleBitmap4Web(s, bmpHeader, x, y, len, invert);
|
||||||
|
if (bmpHeader.color == 8) drawGrayscaleBitmap8Web(s, bmpHeader, x, y, len, invert);
|
||||||
|
if (bmpHeader.color == 24) drawGrayscaleBitmap24Web(s, bmpHeader, x, y, len, invert);
|
||||||
|
|
||||||
int x3 = (int)round((float)x1 + thickness / 2.0 * cos(deg + degShift));
|
return 1;
|
||||||
int y3 = (int)round((float)y1 + thickness / 2.0 * sin(deg + degShift));
|
|
||||||
|
|
||||||
int x4 = (int)round((float)x2 + thickness / 2.0 * cos(deg + degShift));
|
|
||||||
int y4 = (int)round((float)y2 + thickness / 2.0 * sin(deg + degShift));
|
|
||||||
|
|
||||||
x1 = (int)round((float)x1 + thickness / 2.0 * cos(deg - degShift));
|
|
||||||
y1 = (int)round((float)y1 + thickness / 2.0 * sin(deg - degShift));
|
|
||||||
|
|
||||||
x2 = (int)round((float)x2 + thickness / 2.0 * cos(deg - degShift));
|
|
||||||
y2 = (int)round((float)y2 + thickness / 2.0 * sin(deg - degShift));
|
|
||||||
|
|
||||||
fillTriangle(x1, y1, x2, y2, x3, y3, color);
|
|
||||||
fillTriangle(x2, y2, x4, y4, x3, y3, color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inkplate::drawGradientLine(int x1, int y1, int x2, int y2, int color1, int color2, float thickness) {
|
int Inkplate::drawBitmapFromWeb(char* url, int x, int y, bool invert) {
|
||||||
int n = color2 - color1;
|
if (WiFi.status() != WL_CONNECTED) return 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
float px = (float)(x2 - x1) / (float)n;
|
bool sleep = WiFi.getSleep();
|
||||||
float py = (float)(y2 - y1) / (float)n;
|
WiFi.setSleep(false);
|
||||||
|
|
||||||
for (int i = 0; i < n; ++i)
|
HTTPClient http;
|
||||||
{
|
http.getStream().setNoDelay(true);
|
||||||
if (abs(thickness + 1) < 0.1)
|
http.getStream().setTimeout(1);
|
||||||
drawLine((int)((float)x1 + (float)i * px), (int)((float)y1 + (float)i * py),
|
http.begin(url);
|
||||||
(int)((float)x1 + (float)(i + 1) * px), (int)((float)y1 + (float)(i + 1) * py),
|
|
||||||
color1 + i);
|
int httpCode = http.GET();
|
||||||
else
|
if (httpCode == 200) {
|
||||||
drawThickLine((int)((float)x1 + (float)i * px), (int)((float)y1 + (float)i * py),
|
int32_t len = http.getSize();
|
||||||
(int)((float)x1 + (float)(i + 1) * px), (int)((float)y1 + (float)(i + 1) * py),
|
if (len > 0) {
|
||||||
color1 + i,
|
WiFiClient * dat = http.getStreamPtr();
|
||||||
thickness);
|
ret = drawBitmapFromWeb(dat, x, y, len, invert);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
http.end();
|
||||||
|
WiFi.setSleep(sleep);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Inkplate::sdCardInit() {
|
int Inkplate::sdCardInit() {
|
||||||
spi2.begin(14, 12, 13, 15);
|
spi2.begin(14, 12, 13, 15);
|
||||||
sdCardOk = sd.begin(15, SD_SCK_MHZ(25));
|
sdCardOk = sd.begin(15, SD_SCK_MHZ(25));
|
||||||
|
@ -815,7 +819,7 @@ uint16_t Inkplate::read16(uint8_t* c) {
|
||||||
return (*(c) | (*(c + 1) << 8));
|
return (*(c) | (*(c + 1) << 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inkplate::readBmpHeader(SdFile *_f, struct bitmapHeader *_h) {
|
void Inkplate::readBmpHeaderSd(SdFile *_f, struct bitmapHeader *_h) {
|
||||||
uint8_t header[100];
|
uint8_t header[100];
|
||||||
_f->rewind();
|
_f->rewind();
|
||||||
_f->read(header, 100);
|
_f->read(header, 100);
|
||||||
|
@ -830,7 +834,21 @@ void Inkplate::readBmpHeader(SdFile *_f, struct bitmapHeader *_h) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inkplate::drawMonochromeBitmap(SdFile *f, struct bitmapHeader bmpHeader, int x, int y) {
|
void Inkplate::readBmpHeaderWeb(WiFiClient *_s, struct bitmapHeader *_h) {
|
||||||
|
uint8_t header[34];
|
||||||
|
_s->read(header, 34);
|
||||||
|
_h->signature = read16(header + 0);
|
||||||
|
_h->fileSize = read32(header + 2);
|
||||||
|
_h->startRAW = read32(header + 10);
|
||||||
|
_h->dibHeaderSize = read32(header + 14);
|
||||||
|
_h->width = read32(header + 18);
|
||||||
|
_h->height = read32(header + 22);
|
||||||
|
_h->color = read16(header + 28);
|
||||||
|
_h->compression = read32(header + 30);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Inkplate::drawMonochromeBitmapSd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert) {
|
||||||
int w = bmpHeader.width;
|
int w = bmpHeader.width;
|
||||||
int h = bmpHeader.height;
|
int h = bmpHeader.height;
|
||||||
uint8_t paddingBits = w % 32;
|
uint8_t paddingBits = w % 32;
|
||||||
|
@ -841,14 +859,18 @@ int Inkplate::drawMonochromeBitmap(SdFile *f, struct bitmapHeader bmpHeader, int
|
||||||
for (j = 0; j < h; j++) {
|
for (j = 0; j < h; j++) {
|
||||||
for (i = 0; i < w; i++) {
|
for (i = 0; i < w; i++) {
|
||||||
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
|
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
|
||||||
|
if (invert)
|
||||||
|
pixelRow = ~pixelRow;
|
||||||
for (int n = 0; n < 32; n++) {
|
for (int n = 0; n < 32; n++) {
|
||||||
drawPixel((i * 32) + n + x, h - j + y, !(pixelRow & (1ULL << (31 - n))));
|
drawPixel((i * 32) + n + x, h - 1 - j + y, !(pixelRow & (1ULL << (31 - n))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (paddingBits) {
|
if (paddingBits) {
|
||||||
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
|
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
|
||||||
|
if (invert)
|
||||||
|
pixelRow = ~pixelRow;
|
||||||
for (int n = 0; n < paddingBits; n++) {
|
for (int n = 0; n < paddingBits; n++) {
|
||||||
drawPixel((i * 32) + n + x, h - j + y, !(pixelRow & (1ULL << (31 - n))));
|
drawPixel((i * 32) + n + x, h - 1 - j + y, !(pixelRow & (1ULL << (31 - n))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -856,7 +878,62 @@ int Inkplate::drawMonochromeBitmap(SdFile *f, struct bitmapHeader bmpHeader, int
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inkplate::drawGrayscaleBitmap24(SdFile *f, struct bitmapHeader bmpHeader, int x, int y) {
|
int Inkplate::drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert) {
|
||||||
|
int w = bmpHeader.width;
|
||||||
|
int h = bmpHeader.height;
|
||||||
|
uint8_t paddingBits = w % 8;
|
||||||
|
w /= 8;
|
||||||
|
|
||||||
|
f->seekSet(bmpHeader.startRAW);
|
||||||
|
int i, j;
|
||||||
|
for (j = 0; j < h; j++) {
|
||||||
|
for (i = 0; i < w; i++) {
|
||||||
|
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
|
||||||
|
if (invert)
|
||||||
|
pixelRow = ~pixelRow;
|
||||||
|
for (int n = 0; n < 8; n++) {
|
||||||
|
drawPixel((i * 8) + n + x, h - 1 - j + y, (pixelRow & (0xFULL << (28 - n*4))) >> (28 - n*4 + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (paddingBits) {
|
||||||
|
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
|
||||||
|
if (invert)
|
||||||
|
pixelRow = ~pixelRow;
|
||||||
|
for (int n = 0; n < paddingBits; n++) {
|
||||||
|
drawPixel((i * 8) + n + x, h - 1 - j + y, ((pixelRow & (0xFULL << (28 - n*4)))) >> (28 - n*4 + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f->close();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Inkplate::drawGrayscaleBitmap8Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert) {
|
||||||
|
int w = bmpHeader.width;
|
||||||
|
int h = bmpHeader.height;
|
||||||
|
char padding = w % 4;
|
||||||
|
f->seekSet(bmpHeader.startRAW);
|
||||||
|
int i, j;
|
||||||
|
for (j = 0; j < h; j++) {
|
||||||
|
for (i = 0; i < w; i++) {
|
||||||
|
uint8_t px = 0;
|
||||||
|
if (invert)
|
||||||
|
px = 255-f->read();
|
||||||
|
else
|
||||||
|
px = f->read();
|
||||||
|
drawPixel(i + x, h - 1 - j + y, px>>5);
|
||||||
|
}
|
||||||
|
if (padding) {
|
||||||
|
for (int p = 0; p < 4-padding; p++) {
|
||||||
|
f->read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f->close();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert) {
|
||||||
int w = bmpHeader.width;
|
int w = bmpHeader.width;
|
||||||
int h = bmpHeader.height;
|
int h = bmpHeader.height;
|
||||||
char padding = w % 4;
|
char padding = w % 4;
|
||||||
|
@ -870,10 +947,14 @@ int Inkplate::drawGrayscaleBitmap24(SdFile *f, struct bitmapHeader bmpHeader, in
|
||||||
//display.drawPixel(i + x, h - j + y, (uint8_t)(px*7));
|
//display.drawPixel(i + x, h - j + y, (uint8_t)(px*7));
|
||||||
|
|
||||||
//So then, we are convertng it to grayscale using good old average and gamma correction (from LUT). With this metod, it is still slow (full size image takes 4 seconds), but much beter than prev mentioned method.
|
//So then, we are convertng it to grayscale using good old average and gamma correction (from LUT). With this metod, it is still slow (full size image takes 4 seconds), but much beter than prev mentioned method.
|
||||||
uint8_t px = (f->read() * 2126 / 10000) + (f->read() * 7152 / 10000) + (f->read() * 722 / 10000);
|
uint8_t px = 0;
|
||||||
|
if (invert)
|
||||||
|
px = ((255-f->read()) * 2126 / 10000) + ((255-f->read()) * 7152 / 10000) + ((255-f->read()) * 722 / 10000);
|
||||||
|
else
|
||||||
|
px = (f->read() * 2126 / 10000) + (f->read() * 7152 / 10000) + (f->read() * 722 / 10000);
|
||||||
//drawPixel(i + x, h - j + y, gammaLUT[px]);
|
//drawPixel(i + x, h - j + y, gammaLUT[px]);
|
||||||
drawPixel(i + x, h - j + y, px>>5);
|
drawPixel(i + x, h - 1 - j + y, px>>5);
|
||||||
//drawPixel(i + x, h - j + y, px/32);
|
//drawPixel(i + x, h - j + y, px/32);
|
||||||
}
|
}
|
||||||
if (padding) {
|
if (padding) {
|
||||||
for (int p = 0; p < padding; p++) {
|
for (int p = 0; p < padding; p++) {
|
||||||
|
@ -885,9 +966,192 @@ int Inkplate::drawGrayscaleBitmap24(SdFile *f, struct bitmapHeader bmpHeader, in
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Inkplate::drawMonochromeBitmapWeb(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert) {
|
||||||
|
int w = bmpHeader.width;
|
||||||
|
int h = bmpHeader.height;
|
||||||
|
uint8_t paddingBits = w % 32;
|
||||||
|
int total = len - 34;
|
||||||
|
w /= 32;
|
||||||
|
|
||||||
|
uint8_t* buf = (uint8_t*) ps_malloc(total);
|
||||||
|
if (buf == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int pnt = 0;
|
||||||
|
while (pnt < total) {
|
||||||
|
int toread = s->available();
|
||||||
|
if (toread > 0) {
|
||||||
|
int read = s->read(buf+pnt, toread);
|
||||||
|
if (read > 0)
|
||||||
|
pnt += read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i, j, k = bmpHeader.startRAW - 34;
|
||||||
|
for (j = 0; j < h; j++) {
|
||||||
|
for (i = 0; i < w; i++) {
|
||||||
|
uint32_t pixelRow = buf[k++] << 24 | buf[k++] << 16 | buf[k++] << 8 | buf[k++];
|
||||||
|
if (invert)
|
||||||
|
pixelRow = ~pixelRow;
|
||||||
|
for (int n = 0; n < 32; n++) {
|
||||||
|
drawPixel((i * 32) + n + x, h - 1 - j + y, !(pixelRow & (1ULL << (31 - n))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (paddingBits) {
|
||||||
|
uint32_t pixelRow = buf[k++] << 24 | buf[k++] << 16 | buf[k++] << 8 | buf[k++];
|
||||||
|
if (invert)
|
||||||
|
pixelRow = ~pixelRow;
|
||||||
|
for (int n = 0; n < paddingBits; n++) {
|
||||||
|
drawPixel((i * 32) + n + x, h - 1 - j + y, !(pixelRow & (1ULL << (31 - n))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Inkplate::drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert) {
|
||||||
|
int w = bmpHeader.width;
|
||||||
|
int h = bmpHeader.height;
|
||||||
|
char paddingBits = w % 8;
|
||||||
|
int total = len - 34;
|
||||||
|
w /= 8;
|
||||||
|
|
||||||
|
uint8_t* buf = (uint8_t*) ps_malloc(total);
|
||||||
|
if (buf == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int pnt = 0;
|
||||||
|
while (pnt < total) {
|
||||||
|
int toread = s->available();
|
||||||
|
if (toread > 0) {
|
||||||
|
int read = s->read(buf+pnt, toread);
|
||||||
|
if (read > 0)
|
||||||
|
pnt += read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i, j, k = bmpHeader.startRAW - 34;
|
||||||
|
for (j = 0; j < h; j++) {
|
||||||
|
for (i = 0; i < w; i++) {
|
||||||
|
uint32_t pixelRow = buf[k++] << 24 | buf[k++] << 16 | buf[k++] << 8 | buf[k++];
|
||||||
|
if (invert)
|
||||||
|
pixelRow = ~pixelRow;
|
||||||
|
for (int n = 0; n < 8; n++) {
|
||||||
|
drawPixel((i * 8) + n + x, h - 1 - j + y, (pixelRow & (0xFULL << (28 - n*4))) >> (28 - n*4 + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (paddingBits) {
|
||||||
|
uint32_t pixelRow = buf[k++] << 24 | buf[k++] << 16 | buf[k++] << 8 | buf[k++];
|
||||||
|
if (invert)
|
||||||
|
pixelRow = ~pixelRow;
|
||||||
|
for (int n = 0; n < paddingBits; n++) {
|
||||||
|
drawPixel((i * 8) + n + x, h - 1 - j + y, ((pixelRow & (0xFULL << (28 - n*4)))) >> (28 - n*4 + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert) {
|
||||||
|
int w = bmpHeader.width;
|
||||||
|
int h = bmpHeader.height;
|
||||||
|
char padding = w % 4;
|
||||||
|
int total = len - 34;
|
||||||
|
|
||||||
|
uint8_t* buf = (uint8_t*) ps_malloc(total);
|
||||||
|
if (buf == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int pnt = 0;
|
||||||
|
while (pnt < total) {
|
||||||
|
int toread = s->available();
|
||||||
|
if (toread > 0) {
|
||||||
|
int read = s->read(buf+pnt, toread);
|
||||||
|
if (read > 0)
|
||||||
|
pnt += read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i, j, k = bmpHeader.startRAW - 34;
|
||||||
|
for (j = 0; j < h; j++) {
|
||||||
|
for (i = 0; i < w; i++) {
|
||||||
|
uint8_t px = 0;
|
||||||
|
if (invert)
|
||||||
|
px = 255-buf[k++];
|
||||||
|
else
|
||||||
|
px = buf[k++];
|
||||||
|
drawPixel(i + x, h - 1 - j + y, px>>5);
|
||||||
|
}
|
||||||
|
if (padding) {
|
||||||
|
for (int p = 0; p < 4-padding; p++) {
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert) {
|
||||||
|
int w = bmpHeader.width;
|
||||||
|
int h = bmpHeader.height;
|
||||||
|
char padding = w % 4;
|
||||||
|
int total = len - 34;
|
||||||
|
|
||||||
|
uint8_t* buf = (uint8_t*) ps_malloc(total);
|
||||||
|
if (buf == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int pnt = 0;
|
||||||
|
while (pnt < total) {
|
||||||
|
int toread = s->available();
|
||||||
|
if (toread > 0) {
|
||||||
|
int read = s->read(buf+pnt, toread);
|
||||||
|
if (read > 0)
|
||||||
|
pnt += read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int i, j, k = bmpHeader.startRAW - 34;
|
||||||
|
for (j = 0; j < h; j++) {
|
||||||
|
for (i = 0; i < w; i++) {
|
||||||
|
//This is the proper way of converting True Color (24 Bit RGB) bitmap file into grayscale, but it takes waaay too much time (full size picture takes about 17s to decode!)
|
||||||
|
//float px = (0.2126 * (readByteFromSD(&file) / 255.0)) + (0.7152 * (readByteFromSD(&file) / 255.0)) + (0.0722 * (readByteFromSD(&file) / 255.0));
|
||||||
|
//px = pow(px, 1.5);
|
||||||
|
//display.drawPixel(i + x, h - j + y, (uint8_t)(px*7));
|
||||||
|
|
||||||
|
//So then, we are convertng it to grayscale using good old average and gamma correction (from LUT). With this metod, it is still slow (full size image takes 4 seconds), but much beter than prev mentioned method.
|
||||||
|
uint8_t px = 0;
|
||||||
|
if (invert)
|
||||||
|
px = ((255-buf[k++]) * 2126 / 10000) + ((255-buf[k++]) * 7152 / 10000) + ((255-buf[k++]) * 722 / 10000);
|
||||||
|
else
|
||||||
|
px = (buf[k++] * 2126 / 10000) + (buf[k++] * 7152 / 10000) + (buf[k++] * 722 / 10000);
|
||||||
|
//drawPixel(i + x, h - j + y, gammaLUT[px]);
|
||||||
|
drawPixel(i + x, h - 1 - j + y, px>>5);
|
||||||
|
//drawPixel(i + x, h - j + y, px/32);
|
||||||
|
}
|
||||||
|
if (padding) {
|
||||||
|
for (int p = 0; p < padding; p++) {
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void Inkplate::precalculateGamma(uint8_t* c, float gamma) {
|
void Inkplate::precalculateGamma(uint8_t* c, float gamma) {
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
c[i] = int(round((pow(i / 255.0, gamma)) * 15));
|
c[i] = int(round((pow(i / 255.0, gamma)) * 15));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue