commit
e3cf71ef4b
422
Inkplate.cpp
422
Inkplate.cpp
|
@ -134,6 +134,43 @@ void Inkplate::drawPixel(int16_t x0, int16_t y0, uint16_t color)
|
|||
}
|
||||
}
|
||||
|
||||
//Get pixel color function.
|
||||
uint16_t Inkplate::getPixel(int16_t x0, int16_t y0)
|
||||
{
|
||||
if (x0 > _width - 1 || y0 > _height - 1 || x0 < 0 || y0 < 0)
|
||||
return 0;
|
||||
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
_swap_int16_t(x0, y0);
|
||||
x0 = _height - x0 - 1;
|
||||
break;
|
||||
case 2:
|
||||
x0 = _width - x0 - 1;
|
||||
y0 = _height - y0 - 1;
|
||||
break;
|
||||
case 3:
|
||||
_swap_int16_t(x0, y0);
|
||||
y0 = _width - y0 - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_displayMode == 0)
|
||||
{
|
||||
int x = x0 / 8;
|
||||
int x_sub = x0 % 8;
|
||||
return *(_partial + 100 * y0 + x) & pixelMaskLUT[x_sub] * 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = x0 >> 1;
|
||||
int x_sub = x0 & 1;
|
||||
uint8_t temp;
|
||||
return (*(D_memory4Bit + 400 * y0 + x) & pixelMaskGLUT[x_sub]) >> (x_sub ? 4 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Inkplate::clearDisplay()
|
||||
{
|
||||
//Clear 1 bit per pixel display buffer
|
||||
|
@ -373,7 +410,7 @@ uint8_t Inkplate::getDisplayMode()
|
|||
return _displayMode;
|
||||
}
|
||||
|
||||
int Inkplate::drawBitmapFromSD(SdFile *p, int x, int y, bool invert)
|
||||
int Inkplate::drawBitmapFromSD(SdFile *p, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
if (sdCardOk == 0)
|
||||
return 0;
|
||||
|
@ -395,23 +432,23 @@ int Inkplate::drawBitmapFromSD(SdFile *p, int x, int y, bool invert)
|
|||
if (bmpHeader.color == 1)
|
||||
drawMonochromeBitmapSd(p, bmpHeader, x, y, invert);
|
||||
if (bmpHeader.color == 4)
|
||||
drawGrayscaleBitmap4Sd(p, bmpHeader, x, y, invert);
|
||||
drawGrayscaleBitmap4Sd(p, bmpHeader, x, y, dither, invert);
|
||||
if (bmpHeader.color == 8)
|
||||
drawGrayscaleBitmap8Sd(p, bmpHeader, x, y, invert);
|
||||
drawGrayscaleBitmap8Sd(p, bmpHeader, x, y, dither, invert);
|
||||
if (bmpHeader.color == 24)
|
||||
drawGrayscaleBitmap24Sd(p, bmpHeader, x, y, invert);
|
||||
drawGrayscaleBitmap24Sd(p, bmpHeader, x, y, dither, invert);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawBitmapFromSD(char *fileName, int x, int y, bool invert)
|
||||
int Inkplate::drawBitmapFromSD(char *fileName, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
if (sdCardOk == 0)
|
||||
return 0;
|
||||
SdFile dat;
|
||||
if (dat.open(fileName, O_RDONLY))
|
||||
{
|
||||
return drawBitmapFromSD(&dat, x, y, invert);
|
||||
return drawBitmapFromSD(&dat, x, y, dither, invert);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -419,7 +456,7 @@ int Inkplate::drawBitmapFromSD(char *fileName, int x, int y, bool invert)
|
|||
}
|
||||
}
|
||||
|
||||
int Inkplate::drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool invert)
|
||||
int Inkplate::drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool dither, bool invert)
|
||||
{
|
||||
struct bitmapHeader bmpHeader;
|
||||
readBmpHeaderWeb(s, &bmpHeader);
|
||||
|
@ -439,16 +476,16 @@ int Inkplate::drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool inver
|
|||
if (bmpHeader.color == 1)
|
||||
drawMonochromeBitmapWeb(s, bmpHeader, x, y, len, invert);
|
||||
if (bmpHeader.color == 4)
|
||||
drawGrayscaleBitmap4Web(s, bmpHeader, x, y, len, invert);
|
||||
drawGrayscaleBitmap4Web(s, bmpHeader, x, y, len, dither, invert);
|
||||
if (bmpHeader.color == 8)
|
||||
drawGrayscaleBitmap8Web(s, bmpHeader, x, y, len, invert);
|
||||
drawGrayscaleBitmap8Web(s, bmpHeader, x, y, len, dither, invert);
|
||||
if (bmpHeader.color == 24)
|
||||
drawGrayscaleBitmap24Web(s, bmpHeader, x, y, len, invert);
|
||||
drawGrayscaleBitmap24Web(s, bmpHeader, x, y, len, dither, invert);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawBitmapFromWeb(char *url, int x, int y, bool invert)
|
||||
int Inkplate::drawBitmapFromWeb(char *url, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
return 0;
|
||||
|
@ -469,7 +506,7 @@ int Inkplate::drawBitmapFromWeb(char *url, int x, int y, bool invert)
|
|||
if (len > 0)
|
||||
{
|
||||
WiFiClient *dat = http.getStreamPtr();
|
||||
ret = drawBitmapFromWeb(dat, x, y, len, invert);
|
||||
ret = drawBitmapFromWeb(dat, x, y, len, dither, invert);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1012,9 +1049,11 @@ int Inkplate::drawMonochromeBitmapSd(SdFile *f, struct bitmapHeader bmpHeader, i
|
|||
int i, j;
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
uint8_t *bufferPtr = pixelBuffer;
|
||||
f->read(pixelBuffer, w * 4);
|
||||
for (i = 0; i < w; i++)
|
||||
{
|
||||
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
|
||||
uint32_t pixelRow = *(bufferPtr++) << 24 | *(bufferPtr++) << 16 | *(bufferPtr++) << 8 | *(bufferPtr++);
|
||||
if (invert)
|
||||
pixelRow = ~pixelRow;
|
||||
for (int n = 0; n < 32; n++)
|
||||
|
@ -1037,7 +1076,7 @@ int Inkplate::drawMonochromeBitmapSd(SdFile *f, struct bitmapHeader bmpHeader, i
|
|||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert)
|
||||
int Inkplate::drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
int w = bmpHeader.width;
|
||||
int h = bmpHeader.height;
|
||||
|
@ -1046,11 +1085,36 @@ int Inkplate::drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, i
|
|||
|
||||
f->seekSet(bmpHeader.startRAW);
|
||||
int i, j;
|
||||
|
||||
uint8_t *bufferPtr;
|
||||
|
||||
if (dither) {
|
||||
bufferPtr = pixelBuffer;
|
||||
f->read(pixelBuffer, w * 4 + (paddingBits? 4 : 0));
|
||||
|
||||
ditherStart(pixelBuffer, bufferPtr, w * 8 + (paddingBits? 4 : 0), invert, 4);
|
||||
}
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
bufferPtr = pixelBuffer;
|
||||
f->read(pixelBuffer, w * 4 + (paddingBits? 4 : 0));
|
||||
|
||||
if (dither && j != h - 1) {
|
||||
ditherLoadNextLine(pixelBuffer, bufferPtr, w * 8 + (paddingBits? 4 : 0), invert, 4);
|
||||
}
|
||||
|
||||
for (i = 0; i < w; i++)
|
||||
{
|
||||
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
|
||||
if (dither) {
|
||||
|
||||
for (int n = 0; n < 8; n++)
|
||||
{
|
||||
drawPixel((i * 8) + n + x, h - 1 - j + y, ditherGetPixel((i * 8) + n, h - 1 - j, w * 8 + (paddingBits? 4 : 0), h) >> 5);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint32_t pixelRow = *(bufferPtr++) << 24 | *(bufferPtr++) << 16 | *(bufferPtr++) << 8 | *(bufferPtr++);
|
||||
if (invert)
|
||||
pixelRow = ~pixelRow;
|
||||
for (int n = 0; n < 8; n++)
|
||||
|
@ -1058,9 +1122,17 @@ int Inkplate::drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, i
|
|||
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 (dither) {
|
||||
for (int n = 0; n < paddingBits; n++)
|
||||
{
|
||||
drawPixel((i * 8) + n + x, h - 1 - j + y, ditherGetPixel((i * 8) + n, h - 1 - j, w * 8 + (paddingBits? 4 : 0), h) >> 5);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint32_t pixelRow = *(bufferPtr++) << 24 | *(bufferPtr++) << 16 | *(bufferPtr++) << 8 | *(bufferPtr++);
|
||||
if (invert)
|
||||
pixelRow = ~pixelRow;
|
||||
for (int n = 0; n < paddingBits; n++)
|
||||
|
@ -1069,28 +1141,57 @@ int Inkplate::drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, i
|
|||
}
|
||||
}
|
||||
}
|
||||
if (dither)
|
||||
ditherSwap(w * 8 + paddingBits);
|
||||
}
|
||||
f->close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawGrayscaleBitmap8Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert)
|
||||
int Inkplate::drawGrayscaleBitmap8Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
int w = bmpHeader.width;
|
||||
int h = bmpHeader.height;
|
||||
char padding = w % 4;
|
||||
char padding = w & 3;
|
||||
f->seekSet(bmpHeader.startRAW);
|
||||
int i, j;
|
||||
|
||||
uint8_t *bufferPtr;
|
||||
|
||||
if (dither) {
|
||||
bufferPtr = pixelBuffer;
|
||||
f->read(pixelBuffer, w);
|
||||
|
||||
ditherStart(pixelBuffer, bufferPtr, w, invert, 8);
|
||||
}
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
bufferPtr = pixelBuffer;
|
||||
f->read(pixelBuffer, w);
|
||||
|
||||
if (dither && j != h - 1) {
|
||||
ditherLoadNextLine(pixelBuffer, bufferPtr, w, invert, 8);
|
||||
}
|
||||
|
||||
for (i = 0; i < w; i++)
|
||||
{
|
||||
if (dither)
|
||||
drawPixel(i + x, h - 1 - j + y, ditherGetPixel(i, j, w, h) >> 5);
|
||||
else {
|
||||
uint8_t px = 0;
|
||||
if (invert)
|
||||
px = 255 - f->read();
|
||||
px = 255 - *(bufferPtr++);
|
||||
else
|
||||
px = f->read();
|
||||
px = *(bufferPtr++);
|
||||
drawPixel(i + x, h - 1 - j + y, px >> 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dither)
|
||||
ditherSwap(w);
|
||||
|
||||
if (padding)
|
||||
{
|
||||
for (int p = 0; p < 4 - padding; p++)
|
||||
|
@ -1098,20 +1199,36 @@ int Inkplate::drawGrayscaleBitmap8Sd(SdFile *f, struct bitmapHeader bmpHeader, i
|
|||
f->read();
|
||||
}
|
||||
}
|
||||
}
|
||||
f->close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert)
|
||||
int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
int w = bmpHeader.width;
|
||||
int h = bmpHeader.height;
|
||||
char padding = w % 4;
|
||||
char padding = w & 3;
|
||||
f->seekSet(bmpHeader.startRAW);
|
||||
int i, j;
|
||||
|
||||
uint8_t *bufferPtr;
|
||||
|
||||
if (dither) {
|
||||
bufferPtr = pixelBuffer;
|
||||
f->read(pixelBuffer, w * 3);
|
||||
|
||||
ditherStart(pixelBuffer, bufferPtr, w, invert, 24);
|
||||
}
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
bufferPtr = pixelBuffer;
|
||||
f->read(pixelBuffer, w * 3);
|
||||
|
||||
if (dither && j != h - 1) {
|
||||
ditherLoadNextLine(pixelBuffer, bufferPtr, w, invert, 24);
|
||||
}
|
||||
|
||||
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!)
|
||||
|
@ -1119,16 +1236,25 @@ int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader,
|
|||
//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.
|
||||
if (dither)
|
||||
drawPixel(i + x, h - 1 - j + y, ditherGetPixel(i, j, w, h) >> 5);
|
||||
else {
|
||||
uint8_t px = 0;
|
||||
//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.
|
||||
if (invert)
|
||||
px = ((255 - f->read()) * 2126 / 10000) + ((255 - f->read()) * 7152 / 10000) + ((255 - f->read()) * 722 / 10000);
|
||||
px = ((255 - *(bufferPtr++)) * 2126 / 10000) + ((255 - *(bufferPtr++)) * 7152 / 10000) + ((255 - *(bufferPtr++)) * 722 / 10000);
|
||||
else
|
||||
px = (f->read() * 2126 / 10000) + (f->read() * 7152 / 10000) + (f->read() * 722 / 10000);
|
||||
//drawPixel(i + x, h - j + y, gammaLUT[px]);
|
||||
px = (*(bufferPtr++) * 2126 / 10000) + (*(bufferPtr++) * 7152 / 10000) + (*(bufferPtr++) * 722 / 10000);
|
||||
drawPixel(i + x, h - 1 - j + y, px >> 5);
|
||||
}
|
||||
|
||||
//drawPixel(i + x, h - j + y, gammaLUT[px]);
|
||||
//drawPixel(i + x, h - j + y, px/32);
|
||||
}
|
||||
|
||||
if (dither)
|
||||
ditherSwap(w);
|
||||
|
||||
if (padding)
|
||||
{
|
||||
for (int p = 0; p < padding; p++)
|
||||
|
@ -1141,6 +1267,123 @@ int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader,
|
|||
return 1;
|
||||
}
|
||||
|
||||
//Loads first line in current dither buffer
|
||||
void Inkplate::ditherStart(uint8_t *pixelBuffer, uint8_t* bufferPtr, int w, bool invert, uint8_t bits) {
|
||||
for (int i = 0; i < w; ++i)
|
||||
if (bits == 24) {
|
||||
if (invert)
|
||||
ditherBuffer[0][i] = ((255 - *(bufferPtr++)) * 2126 / 10000) + ((255 - *(bufferPtr++)) * 7152 / 10000) + ((255 - *(bufferPtr++)) * 722 / 10000);
|
||||
else
|
||||
ditherBuffer[0][i] = (*(bufferPtr++) * 2126 / 10000) + (*(bufferPtr++) * 7152 / 10000) + (*(bufferPtr++) * 722 / 10000);
|
||||
}
|
||||
else if (bits == 8) {
|
||||
if (invert)
|
||||
ditherBuffer[0][i] = 255 - *(bufferPtr++);
|
||||
else
|
||||
ditherBuffer[0][i] = *(bufferPtr++);
|
||||
}
|
||||
if (bits == 4) {
|
||||
int _w = w / 8;
|
||||
int paddingBits = w % 8;
|
||||
|
||||
for (int i = 0; i < _w; ++i) {
|
||||
for (int n = 0; n < 4; n++) {
|
||||
uint8_t temp = *(bufferPtr++);
|
||||
ditherBuffer[0][i * 8 + n * 2] = temp & 0xF0;
|
||||
ditherBuffer[0][i * 8 + n * 2 + 1] = (temp & 0x0F) << 4;
|
||||
|
||||
if (invert) {
|
||||
ditherBuffer[0][i * 8 + n * 2] = ~ditherBuffer[0][i * 8 + n * 2];
|
||||
ditherBuffer[0][i * 8 + n * 2 + 1] = ~ditherBuffer[0][i * 8 + n * 2 + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (paddingBits)
|
||||
{
|
||||
uint32_t pixelRow = *(bufferPtr++) << 24 | *(bufferPtr++) << 16 | *(bufferPtr++) << 8 | *(bufferPtr++);
|
||||
if (invert)
|
||||
pixelRow = ~pixelRow;
|
||||
for (int n = 0; n < paddingBits; n++)
|
||||
{
|
||||
ditherBuffer[0][_w * 8 + n] = (pixelRow & (0xFULL << ((7 - n) * 4))) >> ((7 - n) * 4 - 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Loads next line, after this ditherGetPixel can be called and alters values in next line
|
||||
void Inkplate::ditherLoadNextLine(uint8_t *pixelBuffer, uint8_t* bufferPtr, int w, bool invert, uint8_t bits) {
|
||||
for (int i = 0; i < w; ++i)
|
||||
{
|
||||
if (bits == 24) {
|
||||
if (invert)
|
||||
ditherBuffer[1][i] = ((255 - *(bufferPtr++)) * 2126 / 10000) + ((255 - *(bufferPtr++)) * 7152 / 10000) + ((255 - *(bufferPtr++)) * 722 / 10000);
|
||||
else
|
||||
ditherBuffer[1][i] = (*(bufferPtr++) * 2126 / 10000) + (*(bufferPtr++) * 7152 / 10000) + (*(bufferPtr++) * 722 / 10000);
|
||||
}
|
||||
else if (bits == 8) {
|
||||
if (invert)
|
||||
ditherBuffer[1][i] = 255 - *(bufferPtr++);
|
||||
else
|
||||
ditherBuffer[1][i] = *(bufferPtr++);
|
||||
}
|
||||
}
|
||||
if (bits == 4) {
|
||||
int _w = w / 8;
|
||||
int paddingBits = w % 8;
|
||||
|
||||
for (int i = 0; i < _w; ++i) {
|
||||
for (int n = 0; n < 4; n++) {
|
||||
uint8_t temp = *(bufferPtr++);
|
||||
ditherBuffer[0][i * 8 + n * 2] = temp & 0xF0;
|
||||
ditherBuffer[0][i * 8 + n * 2 + 1] = (temp & 0x0F) << 4;
|
||||
|
||||
if (invert) {
|
||||
ditherBuffer[0][i * 8 + n * 2] = ~ditherBuffer[0][i * 8 + n * 2];
|
||||
ditherBuffer[0][i * 8 + n * 2 + 1] = ~ditherBuffer[0][i * 8 + n * 2 + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (paddingBits)
|
||||
{
|
||||
uint32_t pixelRow = *(bufferPtr++) << 24 | *(bufferPtr++) << 16 | *(bufferPtr++) << 8 | *(bufferPtr++);
|
||||
if (invert)
|
||||
pixelRow = ~pixelRow;
|
||||
for (int n = 0; n < paddingBits; n++)
|
||||
{
|
||||
ditherBuffer[1][_w * 8 + n] = (pixelRow & (0xFULL << (28 - n * 4))) >> (28 - n * 4 - 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Gets specific pixel, mainly at i, j is just used for bound checking when changing next line values
|
||||
uint8_t Inkplate::ditherGetPixel(int i, int j, int w, int h) {
|
||||
uint8_t oldpixel = ditherBuffer[0][i];
|
||||
uint8_t newpixel = (oldpixel & B11100000);
|
||||
|
||||
ditherBuffer[0][i] = newpixel;
|
||||
|
||||
uint8_t quant_error = oldpixel - newpixel;
|
||||
|
||||
if (i + 1 < w)
|
||||
ditherBuffer[0][i + 1] = min(255, (int)ditherBuffer[0][i + 1] + (((int)quant_error * 7) >> 4));
|
||||
if (j + 1 < h && 0 <= i - 1)
|
||||
ditherBuffer[1][i - 1] = min(255, (int)ditherBuffer[1][i - 1] + (((int)quant_error * 3) >> 4));
|
||||
if (j + 1 < h)
|
||||
ditherBuffer[1][i + 0] = min(255, (int)ditherBuffer[1][i + 0] + (((int)quant_error * 5) >> 4));
|
||||
if (j + 1 < h && i + 1 < w)
|
||||
ditherBuffer[1][i + 1] = min(255, (int)ditherBuffer[1][i + 1] + (((int)quant_error * 1) >> 4));
|
||||
|
||||
return newpixel;
|
||||
}
|
||||
|
||||
//Swaps current and next line, for next one to be overwritten
|
||||
uint8_t Inkplate::ditherSwap(int w) {
|
||||
for (int i = 0; i < w; ++i)
|
||||
ditherBuffer[0][i] = ditherBuffer[1][i];
|
||||
}
|
||||
|
||||
int Inkplate::drawMonochromeBitmapWeb(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert)
|
||||
{
|
||||
int w = bmpHeader.width;
|
||||
|
@ -1195,7 +1438,7 @@ int Inkplate::drawMonochromeBitmapWeb(WiFiClient *s, struct bitmapHeader bmpHead
|
|||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert)
|
||||
int Inkplate::drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool dither, bool invert)
|
||||
{
|
||||
int w = bmpHeader.width;
|
||||
int h = bmpHeader.height;
|
||||
|
@ -1219,12 +1462,40 @@ int Inkplate::drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHead
|
|||
}
|
||||
}
|
||||
|
||||
int i, j, k = bmpHeader.startRAW - 34;
|
||||
int i, j;
|
||||
|
||||
uint8_t *bufferPtr;
|
||||
uint8_t *f_pointer = buf + (bmpHeader.startRAW - 34);
|
||||
|
||||
if (dither) {
|
||||
bufferPtr = pixelBuffer;
|
||||
for (i = 0; i < w * 4 + (paddingBits? 1 : 0); i++)
|
||||
pixelBuffer[i] = *(f_pointer++);
|
||||
|
||||
ditherStart(pixelBuffer, bufferPtr, w, invert, 4);
|
||||
}
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
bufferPtr = pixelBuffer;
|
||||
for (i = 0; i < w * 4 + (paddingBits? 1 : 0); i++)
|
||||
pixelBuffer[i] = *(f_pointer++);
|
||||
|
||||
if (dither && j != h - 1) {
|
||||
ditherLoadNextLine(pixelBuffer, bufferPtr, w * 8 + (paddingBits? 4 : 0), invert, 4);
|
||||
}
|
||||
|
||||
for (i = 0; i < w; i++)
|
||||
{
|
||||
uint32_t pixelRow = buf[k++] << 24 | buf[k++] << 16 | buf[k++] << 8 | buf[k++];
|
||||
if (dither) {
|
||||
|
||||
for (int n = 0; n < 8; n++)
|
||||
{
|
||||
drawPixel((i * 8) + n + x, h - 1 - j + y, ditherGetPixel((i * 8) + n, h - 1 - j, w * 8 + (paddingBits? 4 : 0), h) >> 5);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint32_t pixelRow = *(bufferPtr++) << 24 | *(bufferPtr++) << 16 | *(bufferPtr++) << 8 | *(bufferPtr++);
|
||||
if (invert)
|
||||
pixelRow = ~pixelRow;
|
||||
for (int n = 0; n < 8; n++)
|
||||
|
@ -1232,9 +1503,17 @@ int Inkplate::drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHead
|
|||
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 (dither) {
|
||||
for (int n = 0; n < paddingBits; n++)
|
||||
{
|
||||
drawPixel((i * 8) + n + x, h - 1 - j + y, ditherGetPixel((i * 8) + n, h - 1 - j, w * 8 + (paddingBits? 4 : 0), h) >> 5);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint32_t pixelRow = *(bufferPtr++) << 24 | *(bufferPtr++) << 16 | *(bufferPtr++) << 8 | *(bufferPtr++);
|
||||
if (invert)
|
||||
pixelRow = ~pixelRow;
|
||||
for (int n = 0; n < paddingBits; n++)
|
||||
|
@ -1243,13 +1522,16 @@ int Inkplate::drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHead
|
|||
}
|
||||
}
|
||||
}
|
||||
if (dither)
|
||||
ditherSwap(w * 8 + paddingBits);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert)
|
||||
int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool dither, bool invert)
|
||||
{
|
||||
int w = bmpHeader.width;
|
||||
int h = bmpHeader.height;
|
||||
|
@ -1260,7 +1542,7 @@ int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHead
|
|||
if (buf == NULL)
|
||||
return 0;
|
||||
|
||||
int pnt = 0;
|
||||
uint32_t pnt = 0;
|
||||
while (pnt < total)
|
||||
{
|
||||
int toread = s->available();
|
||||
|
@ -1272,23 +1554,51 @@ int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHead
|
|||
}
|
||||
}
|
||||
|
||||
int i, j, k = bmpHeader.startRAW - 34;
|
||||
uint8_t *bufferPtr;
|
||||
uint8_t *f_pointer = buf + (bmpHeader.startRAW - 34);
|
||||
|
||||
int i, j;
|
||||
|
||||
if (dither) {
|
||||
bufferPtr = pixelBuffer;
|
||||
for (i = 0; i < w; i++)
|
||||
pixelBuffer[i] = *(f_pointer++);
|
||||
|
||||
ditherStart(buf, bufferPtr, w, invert, 8);
|
||||
}
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
bufferPtr = pixelBuffer;
|
||||
for (i = 0; i < w; i++)
|
||||
pixelBuffer[i] = *(f_pointer++);
|
||||
|
||||
if (dither && j != h - 1) {
|
||||
ditherLoadNextLine(buf, bufferPtr, w, invert, 8);
|
||||
}
|
||||
|
||||
for (i = 0; i < w; i++)
|
||||
{
|
||||
if (dither)
|
||||
drawPixel(i + x, h - 1 - j + y, ditherGetPixel(i, j, w, h) >> 5);
|
||||
else {
|
||||
uint8_t px = 0;
|
||||
if (invert)
|
||||
px = 255 - buf[k++];
|
||||
px = 255 - *(bufferPtr++);
|
||||
else
|
||||
px = buf[k++];
|
||||
px = *(bufferPtr++);
|
||||
drawPixel(i + x, h - 1 - j + y, px >> 5);
|
||||
}
|
||||
}
|
||||
|
||||
if (dither)
|
||||
ditherSwap(w);
|
||||
|
||||
if (padding)
|
||||
{
|
||||
for (int p = 0; p < 4 - padding; p++)
|
||||
{
|
||||
k++;
|
||||
++bufferPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1298,7 +1608,7 @@ int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHead
|
|||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert)
|
||||
int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool dither, bool invert)
|
||||
{
|
||||
int w = bmpHeader.width;
|
||||
int h = bmpHeader.height;
|
||||
|
@ -1321,9 +1631,29 @@ int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHea
|
|||
}
|
||||
}
|
||||
|
||||
int i, j, k = bmpHeader.startRAW - 34;
|
||||
uint8_t *bufferPtr;
|
||||
uint8_t *f_pointer = buf + (bmpHeader.startRAW - 34);
|
||||
|
||||
int i, j;
|
||||
|
||||
if (dither) {
|
||||
bufferPtr = pixelBuffer;
|
||||
for (i = 0; i < w * 3; i++)
|
||||
pixelBuffer[i] = *(f_pointer++);
|
||||
|
||||
ditherStart(buf, bufferPtr, w, invert, 24);
|
||||
}
|
||||
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
bufferPtr = pixelBuffer;
|
||||
for (i = 0; i < w * 3; i++)
|
||||
pixelBuffer[i] = *(f_pointer++);
|
||||
|
||||
if (dither && j != h - 1) {
|
||||
ditherLoadNextLine(buf, bufferPtr, w, invert, 24);
|
||||
}
|
||||
|
||||
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!)
|
||||
|
@ -1332,20 +1662,28 @@ int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHea
|
|||
//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.
|
||||
if (dither)
|
||||
drawPixel(i + x, h - 1 - j + y, ditherGetPixel(i, j, w, h) >> 5);
|
||||
else {
|
||||
uint8_t px = 0;
|
||||
if (invert)
|
||||
px = ((255 - buf[k++]) * 2126 / 10000) + ((255 - buf[k++]) * 7152 / 10000) + ((255 - buf[k++]) * 722 / 10000);
|
||||
px = ((255 - *(bufferPtr++)) * 2126 / 10000) + ((255 - *(bufferPtr++)) * 7152 / 10000) + ((255 - *(bufferPtr++)) * 722 / 10000);
|
||||
else
|
||||
px = (buf[k++] * 2126 / 10000) + (buf[k++] * 7152 / 10000) + (buf[k++] * 722 / 10000);
|
||||
px = (*(bufferPtr++) * 2126 / 10000) + (*(bufferPtr++) * 7152 / 10000) + (*(bufferPtr++) * 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 (dither)
|
||||
ditherSwap(w);
|
||||
|
||||
if (padding)
|
||||
{
|
||||
for (int p = 0; p < padding; p++)
|
||||
{
|
||||
k++;
|
||||
++bufferPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
27
Inkplate.h
27
Inkplate.h
|
@ -188,6 +188,7 @@ public:
|
|||
|
||||
Inkplate(uint8_t _mode);
|
||||
void begin(void);
|
||||
uint16_t getPixel(int16_t x0, int16_t y0);
|
||||
void drawPixel(int16_t x0, int16_t y0, uint16_t color);
|
||||
void clearDisplay();
|
||||
void display();
|
||||
|
@ -198,10 +199,10 @@ public:
|
|||
void einkOn(void);
|
||||
void selectDisplayMode(uint8_t _mode);
|
||||
uint8_t getDisplayMode();
|
||||
int drawBitmapFromSD(SdFile *p, int x, int y, bool invert = false);
|
||||
int drawBitmapFromSD(char *fileName, int x, int y, bool invert = false);
|
||||
int drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool invert = false);
|
||||
int drawBitmapFromWeb(char *url, int x, int y, bool invert = false);
|
||||
int drawBitmapFromSD(SdFile *p, int x, int y, bool dither = false, bool invert = false);
|
||||
int drawBitmapFromSD(char *fileName, int x, int y, bool dither = false, bool invert = false);
|
||||
int drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool dither = false, bool invert = false);
|
||||
int drawBitmapFromWeb(char *url, int x, int y, bool dither = false, bool invert = false);
|
||||
void drawThickLine(int x1, int y1, int x2, int y2, int color, float thickness);
|
||||
void drawGradientLine(int x1, int y1, int x2, int y2, int color1, int color2, float thickness = -1);
|
||||
int sdCardInit();
|
||||
|
@ -223,6 +224,8 @@ public:
|
|||
|
||||
private:
|
||||
uint8_t gammaLUT[256];
|
||||
uint8_t pixelBuffer[800 * 3 + 5];
|
||||
uint8_t ditherBuffer[800 * 3 + 5][2];
|
||||
int8_t _temperature;
|
||||
uint8_t _panelOn = 0;
|
||||
uint8_t _rotation = 0;
|
||||
|
@ -235,16 +238,20 @@ private:
|
|||
void display3b();
|
||||
uint32_t read32(uint8_t *c);
|
||||
uint16_t read16(uint8_t *c);
|
||||
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(int i, int j, int w, int h);
|
||||
uint8_t ditherSwap(int w);
|
||||
void readBmpHeaderSd(SdFile *_f, struct bitmapHeader *_h);
|
||||
void readBmpHeaderWeb(WiFiClient *_s, struct bitmapHeader *_h);
|
||||
int drawMonochromeBitmapSd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert);
|
||||
int drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert);
|
||||
int drawGrayscaleBitmap8Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert);
|
||||
int drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert);
|
||||
int drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool dither, bool invert);
|
||||
int drawGrayscaleBitmap8Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool dither, bool invert);
|
||||
int drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool dither, bool invert);
|
||||
int drawMonochromeBitmapWeb(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
||||
int drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
||||
int drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
||||
int drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
||||
int drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool dither, bool invert);
|
||||
int drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool dither, bool invert);
|
||||
int drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool dither, bool invert);
|
||||
void precalculateGamma(uint8_t *c, float gamma);
|
||||
};
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,26 @@
|
|||
.. Inkplate 6 documentation master file, created by
|
||||
sphinx-quickstart on Mon Aug 3 13:10:28 2020.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
*************
|
||||
.begin method
|
||||
*************
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
|
||||
*************
|
||||
What is this?
|
||||
*************
|
||||
|
||||
Used to intiate Inkplate
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
|
@ -10,6 +10,7 @@ Welcome to Inkplate 6's documentation!
|
|||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
begin
|
||||
|
||||
*************
|
||||
What is this?
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>.begin method — Inkplate 6 documentation</title>
|
||||
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
|
||||
<script src="_static/jquery.js"></script>
|
||||
<script src="_static/underscore.js"></script>
|
||||
<script src="_static/doctools.js"></script>
|
||||
<script src="_static/language_data.js"></script>
|
||||
<link rel="index" title="Index" href="genindex.html" />
|
||||
<link rel="search" title="Search" href="search.html" />
|
||||
<link rel="prev" title="Welcome to Inkplate 6’s documentation!" href="index.html" />
|
||||
|
||||
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="section" id="begin-method">
|
||||
<h1>.begin method<a class="headerlink" href="#begin-method" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="toctree-wrapper compound">
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="what-is-this">
|
||||
<h1>What is this?<a class="headerlink" href="#what-is-this" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Used to intiate Inkplate</p>
|
||||
<div class="section" id="indices-and-tables">
|
||||
<h2>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference internal" href="genindex.html"><span class="std std-ref">Index</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="py-modindex.html"><span class="std std-ref">Module Index</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="search.html"><span class="std std-ref">Search Page</span></a></p></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="index.html">Inkplate 6</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<p class="caption"><span class="caption-text">Contents:</span></p>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">.begin method</a><ul class="simple">
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="#what-is-this">What is this?</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#indices-and-tables">Indices and tables</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="index.html" title="previous chapter">Welcome to Inkplate 6’s documentation!</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©2020, e-radionica.com.
|
||||
|
||||
|
|
||||
Powered by <a href="http://sphinx-doc.org/">Sphinx 3.1.2</a>
|
||||
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
||||
|
||||
|
|
||||
<a href="_sources/begin.rst.txt"
|
||||
rel="nofollow">Page source</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -55,6 +55,11 @@
|
|||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<p class="caption"><span class="caption-text">Contents:</span></p>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="begin.html">.begin method</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="begin.html#what-is-this">What is this?</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<script src="_static/language_data.js"></script>
|
||||
<link rel="index" title="Index" href="genindex.html" />
|
||||
<link rel="search" title="Search" href="search.html" />
|
||||
<link rel="next" title=".begin method" href="begin.html" />
|
||||
|
||||
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||
|
||||
|
@ -34,6 +35,16 @@
|
|||
<div class="section" id="welcome-to-inkplate-6-s-documentation">
|
||||
<h1>Welcome to Inkplate 6’s documentation!<a class="headerlink" href="#welcome-to-inkplate-6-s-documentation" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="toctree-wrapper compound">
|
||||
<p class="caption"><span class="caption-text">Contents:</span></p>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="begin.html">.begin method</a><ul class="simple">
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="begin.html#what-is-this">What is this?</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="begin.html#indices-and-tables">Indices and tables</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="what-is-this">
|
||||
<h2>What is this?<a class="headerlink" href="#what-is-this" title="Permalink to this headline">¶</a></h2>
|
||||
|
@ -70,11 +81,17 @@
|
|||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<p class="caption"><span class="caption-text">Contents:</span></p>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="begin.html">.begin method</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="begin.html#what-is-this">What is this?</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="#">Documentation overview</a><ul>
|
||||
<li>Next: <a href="begin.html" title="next chapter">.begin method</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
Binary file not shown.
|
@ -74,6 +74,11 @@
|
|||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<p class="caption"><span class="caption-text">Contents:</span></p>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="begin.html">.begin method</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="begin.html#what-is-this">What is this?</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Search.setIndex({docnames:["index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":3,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":1,sphinx:56},filenames:["index.rst"],objects:{},objnames:{},objtypes:{},terms:{"function":0,For:0,aaaa:[],all:0,can:0,code:0,descript:0,exampl:0,file:0,find:0,first:0,header:0,here:0,includ:0,index:0,kako:[],librari:0,like:0,modul:0,need:0,our:0,ovo:[],page:0,print:[],radi:[],rang:[],search:0,test:[],top:0,work:0,you:0,your:0,znam:[]},titles:["Welcome to Inkplate 6\u2019s documentation!"],titleterms:{document:0,indic:0,inkplat:0,tabl:0,thi:0,welcom:0,what:0}})
|
||||
Search.setIndex({docnames:["begin","index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":3,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":1,sphinx:56},filenames:["begin.rst","index.rst"],objects:{},objnames:{},objtypes:{},terms:{"function":1,For:1,Used:0,aaaa:[],all:1,begin:1,can:1,code:1,content:1,descript:1,exampl:1,file:1,find:1,first:1,header:1,here:1,includ:1,index:[0,1],inkplat:0,intiat:0,kako:[],librari:1,like:1,method:1,modul:[0,1],need:1,our:1,ovo:[],page:[0,1],print:[],radi:[],rang:[],search:[0,1],test:[],top:1,work:1,you:1,your:1,znam:[]},titles:[".begin method","Welcome to Inkplate 6\u2019s documentation!"],titleterms:{begin:0,document:1,indic:[0,1],inkplat:1,method:0,tabl:[0,1],thi:[0,1],welcom:1,what:[0,1]}})
|
|
@ -0,0 +1,26 @@
|
|||
.. Inkplate 6 documentation master file, created by
|
||||
sphinx-quickstart on Mon Aug 3 13:10:28 2020.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
*************
|
||||
.begin method
|
||||
*************
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
|
||||
*************
|
||||
What is this?
|
||||
*************
|
||||
|
||||
Used to intiate Inkplate
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
|
@ -10,6 +10,7 @@ Welcome to Inkplate 6's documentation!
|
|||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
begin
|
||||
|
||||
*************
|
||||
What is this?
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#include "Inkplate.h"
|
||||
|
||||
void setup() {
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
|
@ -21,8 +21,8 @@
|
|||
#include "WiFi.h" //Include library for WiFi
|
||||
Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome)
|
||||
|
||||
const char* ssid = "YourWiFiSSID"; //Your WiFi SSID
|
||||
const char* password = "YourPass"; //Your WiFi password
|
||||
const char* ssid = ""; //Your WiFi SSID
|
||||
const char* password = ""; //Your WiFi password
|
||||
|
||||
void setup() {
|
||||
display.begin(); //Init Inkplate library (you should call this function ONLY ONCE)
|
||||
|
@ -45,11 +45,12 @@ void setup() {
|
|||
|
||||
//Draw the first image from web.
|
||||
//Monochromatic bitmap with 1 bit depth. Images like this load quickest.
|
||||
//NOTE: Both drawBitmapFromWeb methods allow for an optional fourth "invert" parameter. Setting this parameter to true
|
||||
//NOTE: Both drawBitmapFromWeb methods allow for an optional fifth "invert" parameter. Setting this parameter to true
|
||||
//will flip all colors on the image, making black white and white black. This may be necessary when exporting bitmaps from
|
||||
//certain softwares.
|
||||
//Forth parameter will dither the image.
|
||||
//Photo taken by: Roberto Fernandez
|
||||
if(!display.drawBitmapFromWeb("https://varipass.org/neowise_mono.bmp", 0, 0, true)) {
|
||||
if (!display.drawBitmapFromWeb("https://varipass.org/neowise_mono.bmp", 0, 0, false, true)) {
|
||||
//If is something failed (wrong filename or wrong bitmap format), write error message on the screen.
|
||||
//REMEMBER! You can only use Windows Bitmap file with color depth of 1, 4, 8 or 24 bits with no compression!
|
||||
display.println("Image open error");
|
||||
|
|
|
@ -27,6 +27,8 @@ Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and a
|
|||
SdFile file; //Create SdFile object used for accessing files on SD card
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
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
|
||||
|
@ -40,14 +42,16 @@ void setup() {
|
|||
//NOTE: Both drawBitmapFromSD methods allow for an optional fourth "invert" parameter. Setting this parameter to true
|
||||
//will flip all colors on the image, making black white and white black. This may be necessary when exporting bitmaps from
|
||||
//certain softwares.
|
||||
if(!display.drawBitmapFromSD("image1.bmp", 0, 0)) {
|
||||
if (!display.drawBitmapFromSD("image1.bmp", 0, 0, 1)) {
|
||||
//If is something failed (wrong filename or wrong bitmap format), write error message on the screen.
|
||||
//REMEMBER! You can only use Windows Bitmap file with color depth of 1, 4, 8 or 24 bits with no compression!
|
||||
//You can turn of dithering for somewhat faster image load by changing the last 1 to 0, or removing the 1 argument 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();
|
||||
|
|
|
@ -57,6 +57,13 @@ Network network;
|
|||
// Contants used for drawing icons
|
||||
char abbrs[32][16] ={ "sn", "sl", "h", "t", "hr", "lr", "s", "hc", "lc", "c" };
|
||||
const uint8_t *logos[16] ={ icon_sn, icon_sl, icon_h, icon_t, icon_hr, icon_lr, icon_s, icon_hc, icon_lc, icon_c };
|
||||
const uint8_t *s_logos[16] ={ icon_s_sn, icon_s_sl, icon_s_h, icon_s_t, icon_s_hr, icon_s_lr, icon_s_s, icon_s_hc, icon_s_lc, icon_s_c };
|
||||
|
||||
|
||||
char abbr1[16];
|
||||
char abbr2[16];
|
||||
char abbr3[16];
|
||||
char abbr4[16];
|
||||
|
||||
// Variables for storing temperature
|
||||
char temps[8][4] ={
|
||||
|
@ -138,7 +145,7 @@ void loop()
|
|||
// Get all relevant data, see Network.cpp for info
|
||||
network.getTime(currentTime);
|
||||
network.getDays(days[0], days[1], days[2], days[3]);
|
||||
network.getData(city, temps[0], temps[1], temps[2], temps[3], currentTemp, currentWind, currentTime, currentWeather, currentWeatherAbbr);
|
||||
network.getData(city, temps[0], temps[1], temps[2], temps[3], currentTemp, currentWind, currentTime, currentWeather, currentWeatherAbbr, abbr1, abbr2, abbr3, abbr4);
|
||||
|
||||
// Draw data, see functions below for info
|
||||
drawWeather();
|
||||
|
@ -153,6 +160,8 @@ void loop()
|
|||
else
|
||||
display.partialUpdate();
|
||||
|
||||
|
||||
|
||||
// Go to sleep before checking again
|
||||
esp_sleep_enable_timer_wakeup(1000L * DELAY_MS);
|
||||
(void)esp_light_sleep_start();
|
||||
|
@ -220,16 +229,16 @@ void drawTemps()
|
|||
display.setTextSize(1);
|
||||
display.setTextColor(WHITE, BLACK);
|
||||
|
||||
display.setCursor(1 * rectSpacing + 0 * rectWidth + textMargin, 300 + textMargin + 70);
|
||||
display.setCursor(1 * rectSpacing + 0 * rectWidth + textMargin, 300 + textMargin + 40);
|
||||
display.println(days[0]);
|
||||
|
||||
display.setCursor(2 * rectSpacing + 1 * rectWidth + textMargin, 300 + textMargin + 70);
|
||||
display.setCursor(2 * rectSpacing + 1 * rectWidth + textMargin, 300 + textMargin + 40);
|
||||
display.println(days[1]);
|
||||
|
||||
display.setCursor(3 * rectSpacing + 2 * rectWidth + textMargin, 300 + textMargin + 70);
|
||||
display.setCursor(3 * rectSpacing + 2 * rectWidth + textMargin, 300 + textMargin + 40);
|
||||
display.println(days[2]);
|
||||
|
||||
display.setCursor(4 * rectSpacing + 3 * rectWidth + textMargin, 300 + textMargin + 70);
|
||||
display.setCursor(4 * rectSpacing + 3 * rectWidth + textMargin, 300 + textMargin + 40);
|
||||
display.println(days[3]);
|
||||
|
||||
//Drawing temperature values into black rectangles
|
||||
|
@ -237,21 +246,49 @@ void drawTemps()
|
|||
display.setTextSize(1);
|
||||
display.setTextColor(WHITE, BLACK);
|
||||
|
||||
display.setCursor(1 * rectSpacing + 0 * rectWidth + textMargin, 300 + textMargin + 160);
|
||||
display.setCursor(1 * rectSpacing + 0 * rectWidth + textMargin, 300 + textMargin + 120);
|
||||
display.print(temps[0]);
|
||||
display.println(F("C"));
|
||||
|
||||
display.setCursor(2 * rectSpacing + 1 * rectWidth + textMargin, 300 + textMargin + 160);
|
||||
display.setCursor(2 * rectSpacing + 1 * rectWidth + textMargin, 300 + textMargin + 120);
|
||||
display.print(temps[1]);
|
||||
display.println(F("C"));
|
||||
|
||||
display.setCursor(3 * rectSpacing + 2 * rectWidth + textMargin, 300 + textMargin + 160);
|
||||
display.setCursor(3 * rectSpacing + 2 * rectWidth + textMargin, 300 + textMargin + 120);
|
||||
display.print(temps[2]);
|
||||
display.println(F("C"));
|
||||
|
||||
display.setCursor(4 * rectSpacing + 3 * rectWidth + textMargin, 300 + textMargin + 160);
|
||||
display.setCursor(4 * rectSpacing + 3 * rectWidth + textMargin, 300 + textMargin + 120);
|
||||
display.print(temps[3]);
|
||||
display.println(F("C"));
|
||||
|
||||
for (int i = 0; i < 18; ++i)
|
||||
{
|
||||
//If found draw specified icon
|
||||
if (strcmp(abbr1, abbrs[i]) == 0)
|
||||
display.drawBitmap(1 * rectSpacing + 0 * rectWidth + textMargin, 300 + textMargin + 150, s_logos[i], 48, 48, WHITE, BLACK);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 18; ++i)
|
||||
{
|
||||
//If found draw specified icon
|
||||
if (strcmp(abbr2, abbrs[i]) == 0)
|
||||
display.drawBitmap(2 * rectSpacing + 1 * rectWidth + textMargin, 300 + textMargin + 150, s_logos[i], 48, 48, WHITE, BLACK);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 18; ++i)
|
||||
{
|
||||
//If found draw specified icon
|
||||
if (strcmp(abbr3, abbrs[i]) == 0)
|
||||
display.drawBitmap(3 * rectSpacing + 2 * rectWidth + textMargin, 300 + textMargin + 150, s_logos[i], 48, 48, WHITE, BLACK);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 18; ++i)
|
||||
{
|
||||
//If found draw specified icon
|
||||
if (strcmp(abbr4, abbrs[i]) == 0)
|
||||
display.drawBitmap(4 * rectSpacing + 3 * rectWidth + textMargin, 300 + textMargin + 150, s_logos[i], 48, 48, WHITE, BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
// Current weather drawing function
|
|
@ -3,15 +3,10 @@
|
|||
#include "Network.h"
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <WiFiMulti.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
// WiFiMulti object declaration
|
||||
WiFiMulti WiFiMulti;
|
||||
|
||||
// Static Json from ArduinoJson library
|
||||
StaticJsonDocument<6000> doc;
|
||||
|
||||
|
@ -30,25 +25,27 @@ void Network::begin(char *city)
|
|||
{
|
||||
// Initiating wifi, like in BasicHttpClient example
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFiMulti.addAP(ssid, pass);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
Serial.print(F("Waiting for WiFi to connect..."));
|
||||
while ((WiFiMulti.run() != WL_CONNECTED))
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
WiFi.reconnect();
|
||||
|
||||
delay(5000);
|
||||
|
||||
Serial.println(F("Waiting for WiFi to reconnect..."));
|
||||
while ((WiFi.status() != WL_CONNECTED))
|
||||
{
|
||||
// Printing a dot to Serial monitor every second while waiting to connect
|
||||
// Prints a dot every second that wifi isn't connected
|
||||
Serial.print(F("."));
|
||||
delay(1000);
|
||||
}
|
||||
Serial.println(F(" connected"));
|
||||
}
|
||||
|
||||
// Find internet time
|
||||
setTime();
|
||||
|
||||
// Search for given cities woeid
|
||||
findCity(city);
|
||||
|
||||
// reduce power by making WiFi module sleep
|
||||
WiFi.setSleep(1);
|
||||
}
|
||||
|
||||
// Gets time from ntp server
|
||||
|
@ -87,11 +84,22 @@ void formatWind(char *str, float wind)
|
|||
dtostrf(wind, 2, 0, str);
|
||||
}
|
||||
|
||||
void Network::getData(char *city, char *temp1, char *temp2, char *temp3, char *temp4, char *currentTemp, char *currentWind, char *currentTime, char *currentWeather, char *currentWeatherAbbr)
|
||||
void Network::getData(char *city, char *temp1, char *temp2, char *temp3, char *temp4, char *currentTemp, char *currentWind, char *currentTime, char *currentWeather, char *currentWeatherAbbr, char* abbr1, char* abbr2, char* abbr3, char* abbr4)
|
||||
{
|
||||
// Return if wifi isn't connected
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
return;
|
||||
// Reconnect if wifi isn't connected
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
WiFi.reconnect();
|
||||
|
||||
delay(5000);
|
||||
|
||||
Serial.println(F("Waiting for WiFi to reconnect..."));
|
||||
while ((WiFi.status() != WL_CONNECTED))
|
||||
{
|
||||
// Prints a dot every second that wifi isn't connected
|
||||
Serial.print(F("."));
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Wake up if sleeping and save inital state
|
||||
bool sleep = WiFi.getSleep();
|
||||
|
@ -138,6 +146,11 @@ void Network::getData(char *city, char *temp1, char *temp2, char *temp3, char *t
|
|||
strcpy(currentWeather, doc["consolidated_weather"][0]["weather_state_name"].as<char *>());
|
||||
strcpy(currentWeatherAbbr, doc["consolidated_weather"][0]["weather_state_abbr"].as<char *>());
|
||||
|
||||
strcpy(abbr1, doc["consolidated_weather"][0]["weather_state_abbr"].as<char *>());
|
||||
strcpy(abbr2, doc["consolidated_weather"][1]["weather_state_abbr"].as<char *>());
|
||||
strcpy(abbr3, doc["consolidated_weather"][2]["weather_state_abbr"].as<char *>());
|
||||
strcpy(abbr4, doc["consolidated_weather"][3]["weather_state_abbr"].as<char *>());
|
||||
|
||||
formatTemp(temp1, doc["consolidated_weather"][0][F("the_temp")].as<float>());
|
||||
formatTemp(temp2, doc["consolidated_weather"][1][F("the_temp")].as<float>());
|
||||
formatTemp(temp3, doc["consolidated_weather"][2][F("the_temp")].as<float>());
|
||||
|
@ -201,9 +214,20 @@ void Network::getDays(char *day, char *day1, char *day2, char *day3)
|
|||
|
||||
void Network::findCity(char *city)
|
||||
{
|
||||
// If not connected to wifi, return
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
return;
|
||||
// If not connected to wifi reconnect wifi
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
WiFi.reconnect();
|
||||
|
||||
delay(5000);
|
||||
|
||||
Serial.println(F("Waiting for WiFi to reconnect..."));
|
||||
while ((WiFi.status() != WL_CONNECTED))
|
||||
{
|
||||
// Prints a dot every second that wifi isn't connected
|
||||
Serial.print(F("."));
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Wake wifi module and save initial state
|
||||
bool sleep = WiFi.getSleep();
|
|
@ -24,7 +24,7 @@ public:
|
|||
// Functions we can access in main file
|
||||
void begin(char *city);
|
||||
void getTime(char *timeStr);
|
||||
void getData(char *city, char *temp1, char *temp2, char *temp3, char *temp4, char *currentTemp, char *currentWind, char *currentTime, char *currentWeather, char *currentWeatherAbbr);
|
||||
void getData(char *city, char *temp1, char *temp2, char *temp3, char *temp4, char *currentTemp, char *currentWind, char *currentTime, char *currentWeather, char *currentWeatherAbbr, char* abbr1, char* abbr2, char* abbr3, char* abbr4);
|
||||
void getDays(char *day, char *day1, char *day2, char *day3);
|
||||
|
||||
// Used to store loaction woeid (world id), set in findCity()
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -15,16 +15,16 @@ if not os.path.isdir("./binary_icons"):
|
|||
|
||||
for file in os.listdir("./icons"):
|
||||
im = Image.open("./icons/" + file)
|
||||
im = im.resize((152, 152))
|
||||
im = im.resize((48, 48))
|
||||
alp = im.split()[-1]
|
||||
s = [0 for x in range(152 * 152)]
|
||||
for y in range(152):
|
||||
for x in range(152):
|
||||
s = [0 for x in range(48 * 48)]
|
||||
for y in range(48):
|
||||
for x in range(48):
|
||||
# print(im.getpixel((x, y)))
|
||||
if alp.getpixel((x, y)) > 128:
|
||||
s[(x + 152 * y) // 8] |= 1 << (7 - (x + 152 * y) % 8)
|
||||
s[(x + 48 * y) // 8] |= 1 << (7 - (x + 48 * y) % 8)
|
||||
|
||||
with open("./binary_icons/icon_" + file[:-4] + ".h", "w") as f:
|
||||
print("const uint8_t icon_" + file[:-4] + "[] PROGMEM = {", file=f)
|
||||
with open("./binary_icons/icon_s_" + file[:-4] + ".h", "w") as f:
|
||||
print("const uint8_t icon_s_" + file[:-4] + "[] PROGMEM = {", file=f)
|
||||
print(",".join(list(map(hex, s))), file=f)
|
||||
print("};", file=f)
|
|
@ -12,4 +12,15 @@
|
|||
#include "binary_icons/icon_sn.h"
|
||||
#include "binary_icons/icon_t.h"
|
||||
|
||||
#include "binary_icons/icon_s_c.h"
|
||||
#include "binary_icons/icon_s_h.h"
|
||||
#include "binary_icons/icon_s_hc.h"
|
||||
#include "binary_icons/icon_s_hr.h"
|
||||
#include "binary_icons/icon_s_lc.h"
|
||||
#include "binary_icons/icon_s_lr.h"
|
||||
#include "binary_icons/icon_s_s.h"
|
||||
#include "binary_icons/icon_s_sl.h"
|
||||
#include "binary_icons/icon_s_sn.h"
|
||||
#include "binary_icons/icon_s_t.h"
|
||||
|
||||
#endif
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue