Few new fixes.
This commit is contained in:
parent
5d94d15672
commit
6fd572b52f
|
@ -12,9 +12,6 @@
|
|||
|
||||
#include "include/defines.h"
|
||||
|
||||
static void ckvClock();
|
||||
static void usleep1();
|
||||
|
||||
class Inkplate : public System, public GFX
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#define GREEN(a) ((((a)&0x07e0) >> 5) << 2)
|
||||
#define BLUE(a) (((a)&0x001f) << 3)
|
||||
|
||||
static Image *_imagePtrJpeg = nullptr;
|
||||
Image *_imagePtrJpeg = nullptr;
|
||||
|
||||
Image::Image()
|
||||
{
|
||||
|
@ -193,147 +193,7 @@ uint8_t Image::ditherSwap(int w)
|
|||
ditherBuffer[0][i] = ditherBuffer[1][i];
|
||||
}
|
||||
|
||||
bool Image::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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
int i, j;
|
||||
for (j = 0; j < h; ++j)
|
||||
{
|
||||
for (i = 0; i < w; ++i)
|
||||
{
|
||||
uint16_t rgb = bitmap[j * w + i];
|
||||
if (_invert)
|
||||
rgb = ~rgb;
|
||||
uint8_t px = (RED(rgb) * 2126 / 10000) + (GREEN(rgb) * 7152 / 10000) + (BLUE(rgb) * 722 / 10000);
|
||||
_imagePtrJpeg->drawPixel(i + x, j + y, px >> 5);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void Image::drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char *_p, int16_t _w, int16_t _h)
|
||||
{
|
||||
if (getDisplayMode() != INKPLATE_3BIT)
|
||||
return;
|
||||
uint8_t _rem = _w % 2;
|
||||
int i, j;
|
||||
int xSize = _w / 2 + _rem;
|
||||
|
||||
for (i = 0; i < _h; i++)
|
||||
{
|
||||
for (j = 0; j < xSize - 1; j++)
|
||||
{
|
||||
drawPixel((j * 2) + _x, i + _y, (*(_p + xSize * (i) + j) >> 4) >> 1);
|
||||
drawPixel((j * 2) + 1 + _x, i + _y, (*(_p + xSize * (i) + j) & 0xff) >> 1);
|
||||
}
|
||||
drawPixel((j * 2) + _x, i + _y, (*(_p + xSize * (i) + j) >> 4) >> 1);
|
||||
if (_rem == 0)
|
||||
drawPixel((j * 2) + 1 + _x, i + _y, (*(_p + xSize * (i) + j) & 0xff) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
// FUTURE COMPATIBILITY FUNCTIONS; DO NOT USE!
|
||||
void Image::drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg)
|
||||
void Image::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg)
|
||||
{
|
||||
int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
|
||||
uint8_t byte = 0;
|
||||
|
@ -357,6 +217,30 @@ void Image::drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t
|
|||
endWrite();
|
||||
}
|
||||
|
||||
void Image::drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char *_p, int16_t _w, int16_t _h)
|
||||
{
|
||||
if (getDisplayMode() != INKPLATE_3BIT)
|
||||
return;
|
||||
uint8_t _rem = _w & 1;
|
||||
int i, j;
|
||||
int xSize = (_w >> 1) + _rem;
|
||||
|
||||
startWrite();
|
||||
for (i = 0; i < _h; i++)
|
||||
{
|
||||
for (j = 0; j < xSize - 1; j++)
|
||||
{
|
||||
writePixel((j * 2) + _x, i + _y, (*(_p + xSize * (i) + j) >> 4) >> 1);
|
||||
writePixel((j * 2) + 1 + _x, i + _y, (*(_p + xSize * (i) + j) & 0xff) >> 1);
|
||||
}
|
||||
writePixel((j * 2) + _x, i + _y, (*(_p + xSize * (i) + j) >> 4) >> 1);
|
||||
if (_rem == 0)
|
||||
writePixel((j * 2) + 1 + _x, i + _y, (*(_p + xSize * (i) + j) & 0xff) >> 1);
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
// FUTURE COMPATIBILITY FUNCTIONS; DO NOT USE!
|
||||
void Image::drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
startWrite();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "../libs/SdFat/SdFat.h"
|
||||
#include "Arduino.h"
|
||||
#include "Network.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "defines.h"
|
||||
|
||||
|
@ -18,7 +19,7 @@ struct bitmapHeader
|
|||
uint32_t compression;
|
||||
};
|
||||
|
||||
class Image
|
||||
class Image : Network
|
||||
{
|
||||
public:
|
||||
Image();
|
||||
|
@ -35,7 +36,8 @@ class Image
|
|||
bool drawImage(const SdFile *path, int x, int y, bool dither = 1, bool invert = 0);
|
||||
bool drawImage(const WiFiClient *s, int x, int y, int len = -1, bool dither = 1, bool invert = 0);
|
||||
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg = 0xFFFF);
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color,
|
||||
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);
|
||||
|
@ -75,8 +77,10 @@ class Image
|
|||
uint32_t read32(uint8_t *c);
|
||||
uint16_t read16(uint8_t *c);
|
||||
|
||||
void readBmpHeader(uint8_t *buf, bitmapHeader *_h);
|
||||
void readBmpHeaderSd(SdFile *_f, bitmapHeader *_h);
|
||||
inline void displayBmpLine(int16_t x, int16_t y, SdFile *f, bitmapHeader *bmpHeader, bool dither, bool invert);
|
||||
|
||||
inline void displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool dither, bool invert);
|
||||
|
||||
bool drawMonochromeBitmapWeb(WiFiClient *s, bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
||||
bool drawGrayscaleBitmap4Web(WiFiClient *s, bitmapHeader bmpHeader, int x, int y, int len, bool dither,
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#include "Image.h"
|
||||
|
||||
#define RGB3BIT(r, g, b) ((54UL * (r) + 183UL * (g) + 19UL * (b)) >> 13)
|
||||
|
||||
void Image::readBmpHeaderSd(SdFile *_f, bitmapHeader *_h)
|
||||
{
|
||||
uint8_t header[100];
|
||||
|
||||
_f->rewind();
|
||||
_f->read(header, 100);
|
||||
_h->signature = read16(header + 0);
|
||||
|
@ -32,32 +35,50 @@ void Image::readBmpHeaderSd(SdFile *_f, bitmapHeader *_h)
|
|||
{
|
||||
uint32_t c = read32(paletteRGB + (i << 2));
|
||||
|
||||
Serial.println(c, 2);
|
||||
uint8_t r = (c & 0xFF000000) >> 24;
|
||||
uint8_t g = (c & 0x00FF0000) >> 16;
|
||||
uint8_t b = (c & 0x0000FF00) >> 8;
|
||||
|
||||
pallete[i >> 1] |= RGB3BIT(r, g, b) << (i & 1 ? 0 : 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Image::readBmpHeader(uint8_t *buf, bitmapHeader *_h)
|
||||
{
|
||||
_h->signature = read16(buf + 0);
|
||||
_h->fileSize = read32(buf + 2);
|
||||
_h->startRAW = read32(buf + 10);
|
||||
_h->dibHeaderSize = read32(buf + 14);
|
||||
_h->width = read32(buf + 18);
|
||||
_h->height = read32(buf + 22);
|
||||
_h->color = read16(buf + 28);
|
||||
_h->compression = read32(buf + 30);
|
||||
|
||||
uint32_t totalColors = read32(buf + 46);
|
||||
|
||||
uint8_t paletteRGB[1024];
|
||||
|
||||
if (_h->color <= 8)
|
||||
{
|
||||
if (!totalColors)
|
||||
totalColors = (1ULL << _h->color);
|
||||
|
||||
memcpy(paletteRGB, buf + 53, totalColors * 4);
|
||||
memset(pallete, 0, sizeof pallete);
|
||||
|
||||
for (int i = 0; i < totalColors; ++i)
|
||||
{
|
||||
uint32_t c = read32(paletteRGB + (i << 2));
|
||||
|
||||
uint8_t r = (c & 0xFF000000) >> 24;
|
||||
uint8_t g = (c & 0x00FF0000) >> 16;
|
||||
uint8_t b = (c & 0x0000FF00) >> 8;
|
||||
uint8_t a = (c & 0x000000FF);
|
||||
|
||||
Serial.println(b, 2);
|
||||
Serial.println(g, 2);
|
||||
Serial.println(r, 2);
|
||||
Serial.println(a, 2);
|
||||
|
||||
pallete[i >> 1] |= ((54UL * r + 183UL * g + 19UL * b) >> 13) << (i & 1 ? 0 : 4);
|
||||
pallete[i >> 1] |= RGB3BIT(r, g, b) << (i & 1 ? 0 : 4);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < totalColors / 2; ++i)
|
||||
{
|
||||
Serial.println(pallete[i] >> 8);
|
||||
Serial.println(pallete[i] & 0xF);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
bool Image::drawBitmapFromSD(const char *fileName, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
|
@ -87,28 +108,27 @@ bool Image::drawBitmapFromSD(SdFile *p, int x, int y, bool dither, bool invert)
|
|||
selectDisplayMode(INKPLATE_3BIT);
|
||||
|
||||
int16_t w = bmpHeader.width, h = bmpHeader.height;
|
||||
int8_t c = bmpHeader.color;
|
||||
|
||||
p->seekSet(bmpHeader.startRAW);
|
||||
|
||||
if (bmpHeader.color == 1)
|
||||
Serial.println("nice");
|
||||
|
||||
for (int i = 0; i < h; ++i)
|
||||
displayBmpLine(x, y + i, p, &bmpHeader, dither, invert);
|
||||
{
|
||||
int16_t rowSize = (((int16_t)c * w + 31) >> 5) << 2;
|
||||
|
||||
p->read(pixelBuffer, rowSize);
|
||||
displayBmpLine(x, y + i, &bmpHeader, dither, invert);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Image::displayBmpLine(int16_t x, int16_t y, SdFile *f, bitmapHeader *bmpHeader, bool dither, bool invert)
|
||||
void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool dither, bool invert)
|
||||
{
|
||||
int16_t w = bmpHeader->width, h = bmpHeader->height;
|
||||
int8_t c = bmpHeader->color;
|
||||
|
||||
int16_t rowSize = (((int16_t)c * w + 31) >> 5) << 2;
|
||||
|
||||
startWrite();
|
||||
|
||||
f->read(pixelBuffer, rowSize);
|
||||
for (int j = 0; j < w; ++j)
|
||||
{
|
||||
switch (c)
|
||||
|
@ -142,9 +162,9 @@ void Image::displayBmpLine(int16_t x, int16_t y, SdFile *f, bitmapHeader *bmpHea
|
|||
uint8_t b = (px & 0x1F) << 3;
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - ((54UL * r + 183UL * g + 19UL * b) >> 13));
|
||||
writePixel(x + j, y, 7 - RGB3BIT(r, g, b));
|
||||
else
|
||||
writePixel(x + j, y, (54UL * r + 183UL * b + 19UL * g) >> 13);
|
||||
writePixel(x + j, y, RGB3BIT(r, g, b));
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
|
@ -153,9 +173,9 @@ void Image::displayBmpLine(int16_t x, int16_t y, SdFile *f, bitmapHeader *bmpHea
|
|||
uint8_t b = pixelBuffer[j * 3 + 2];
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - ((54UL * r + 183UL * g + 19UL * b) >> 13));
|
||||
writePixel(x + j, y, 7 - RGB3BIT(r, g, b));
|
||||
else
|
||||
writePixel(x + j, y, (54UL * r + 183UL * b + 19UL * g) >> 13);
|
||||
writePixel(x + j, y, RGB3BIT(r, g, b));
|
||||
break;
|
||||
}
|
||||
case 32:
|
||||
|
@ -164,9 +184,9 @@ void Image::displayBmpLine(int16_t x, int16_t y, SdFile *f, bitmapHeader *bmpHea
|
|||
uint8_t b = pixelBuffer[j * 4 + 2];
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - ((54UL * r + 183UL * g + 19UL * b) >> 13));
|
||||
writePixel(x + j, y, 7 - RGB3BIT(r, g, b));
|
||||
else
|
||||
writePixel(x + j, y, (54UL * r + 183UL * b + 19UL * g) >> 13);
|
||||
writePixel(x + j, y, RGB3BIT(r, g, b));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -174,240 +194,110 @@ void Image::displayBmpLine(int16_t x, int16_t y, SdFile *f, bitmapHeader *bmpHea
|
|||
endWrite();
|
||||
}
|
||||
|
||||
// bool Image::drawMonochromeBitmapSd(SdFile *f, bitmapHeader bmpHeader, int x, int y, bool invert)
|
||||
// {
|
||||
// int w = bmpHeader.width;
|
||||
// int h = bmpHeader.height;
|
||||
// uint8_t paddingBits = w % 32;
|
||||
// w /= 32;
|
||||
bool Image::drawBitmapFromWeb(const char *url, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
uint8_t *buf = (uint8_t *)ps_malloc(800 * 600 * 4 + 100); // TODO: allocate as mush as used
|
||||
downloadFile(buf, url);
|
||||
|
||||
struct bitmapHeader bmpHeader;
|
||||
|
||||
// int i, j;
|
||||
// for (j = 0; j < h; j++)
|
||||
// {
|
||||
// uint8_t *bufferPtr = pixelBuffer;
|
||||
readBmpHeader(buf, &bmpHeader);
|
||||
|
||||
// for (i = 0; i < w; i++)
|
||||
// {
|
||||
// uint32_t pixelRow = *(bufferPtr++) << 24 | *(bufferPtr++) << 16 | *(bufferPtr++) << 8 | *(bufferPtr++);
|
||||
// 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 = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
|
||||
// if (invert)
|
||||
// pixelRow = ~pixelRow;
|
||||
// for (int n = 0; n < paddingBits; n++)
|
||||
// {
|
||||
// drawPixel((i * 32) + n + x, h - 1 - j + y, !(pixelRow & (1ULL << (31 - n))));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// f->close();
|
||||
// return 1;
|
||||
// }
|
||||
uint8_t *bufferPtr = buf + bmpHeader.startRAW;
|
||||
for (int i = 0; i < bmpHeader.height; ++i)
|
||||
{
|
||||
memcpy(pixelBuffer, bufferPtr, bmpHeader.width);
|
||||
displayBmpLine(x, y + i, &bmpHeader, dither, invert);
|
||||
bufferPtr += bmpHeader.width;
|
||||
}
|
||||
|
||||
// bool Image::drawGrayscaleBitmap4Sd(SdFile *f, bitmapHeader bmpHeader, int x, int y, bool dither, bool invert)
|
||||
// {
|
||||
// int w = bmpHeader.width;
|
||||
// int h = bmpHeader.height;
|
||||
// uint8_t paddingBits = w % 8;
|
||||
// w /= 8;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// f->seekSet(bmpHeader.startRAW);
|
||||
// int i, j;
|
||||
bool Image::drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool dither, bool invert)
|
||||
{
|
||||
struct bitmapHeader bmpHeader;
|
||||
// readBmpHeaderWeb(s, &bmpHeader);
|
||||
|
||||
// uint8_t *bufferPtr;
|
||||
if (bmpHeader.signature != 0x4D42 || bmpHeader.compression != 0 ||
|
||||
!(bmpHeader.color == 1 || bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 16 ||
|
||||
bmpHeader.color == 24))
|
||||
return 0;
|
||||
|
||||
// if (dither)
|
||||
// {
|
||||
// bufferPtr = pixelBuffer;
|
||||
// f->read(pixelBuffer, w * 4 + (paddingBits ? 4 : 0));
|
||||
if ((bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 16 || bmpHeader.color == 24 ||
|
||||
bmpHeader.color == 32) &&
|
||||
getDisplayMode() != INKPLATE_3BIT)
|
||||
{
|
||||
selectDisplayMode(INKPLATE_3BIT);
|
||||
}
|
||||
|
||||
// ditherStart(pixelBuffer, bufferPtr, w * 8 + (paddingBits ? 4 : 0), invert, 4);
|
||||
// }
|
||||
if (bmpHeader.color == 1 && getDisplayMode() != INKPLATE_1BIT)
|
||||
{
|
||||
selectDisplayMode(INKPLATE_1BIT);
|
||||
}
|
||||
|
||||
// for (j = 0; j < h; j++)
|
||||
// {
|
||||
// bufferPtr = pixelBuffer;
|
||||
// f->read(pixelBuffer, w * 4 + (paddingBits ? 4 : 0));
|
||||
if (bmpHeader.color == 1)
|
||||
drawMonochromeBitmapWeb(s, bmpHeader, x, y, len, invert);
|
||||
if (bmpHeader.color == 4)
|
||||
drawGrayscaleBitmap4Web(s, bmpHeader, x, y, len, dither, invert);
|
||||
if (bmpHeader.color == 8)
|
||||
drawGrayscaleBitmap8Web(s, bmpHeader, x, y, len, dither, invert);
|
||||
if (bmpHeader.color == 24)
|
||||
drawGrayscaleBitmap24Web(s, bmpHeader, x, y, len, dither, invert);
|
||||
|
||||
// if (dither && j != h - 1)
|
||||
// {
|
||||
// ditherLoadNextLine(pixelBuffer, bufferPtr, w * 8 + (paddingBits ? 4 : 0), invert, 4);
|
||||
// }
|
||||
return 1;
|
||||
}
|
||||
|
||||
// for (i = 0; i < w; i++)
|
||||
// {
|
||||
// if (dither)
|
||||
// {
|
||||
bool Image::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;
|
||||
|
||||
// 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++)
|
||||
// {
|
||||
// drawPixel((i * 8) + n + x, h - 1 - j + y,
|
||||
// (pixelRow & (0xFULL << (28 - n * 4))) >> (28 - n * 4 + 1));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (paddingBits)
|
||||
// {
|
||||
// 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++)
|
||||
// {
|
||||
// drawPixel((i * 8) + n + x, h - 1 - j + y,
|
||||
// ((pixelRow & (0xFULL << (28 - n * 4)))) >> (28 - n * 4 + 1));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (dither)
|
||||
// ditherSwap(w * 8 + paddingBits);
|
||||
// }
|
||||
// f->close();
|
||||
// return 1;
|
||||
// }
|
||||
uint8_t *buf = (uint8_t *)ps_malloc(total);
|
||||
if (buf == NULL)
|
||||
return 0;
|
||||
|
||||
// bool Image::drawGrayscaleBitmap8Sd(SdFile *f, bitmapHeader bmpHeader, int x, int y, bool dither, bool invert)
|
||||
// {
|
||||
// int w = bmpHeader.width;
|
||||
// int h = bmpHeader.height;
|
||||
// char padding = w & 3;
|
||||
// f->seekSet(bmpHeader.startRAW);
|
||||
// int i, j;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// uint8_t *bufferPtr;
|
||||
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))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (dither)
|
||||
// {
|
||||
// bufferPtr = pixelBuffer;
|
||||
// f->read(pixelBuffer, w);
|
||||
free(buf);
|
||||
|
||||
// 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 - *(bufferPtr++);
|
||||
// else
|
||||
// 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++)
|
||||
// {
|
||||
// f->read();
|
||||
// }
|
||||
// }
|
||||
// f->close();
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
// bool Image::drawGrayscaleBitmap24Sd(SdFile *f, bitmapHeader bmpHeader, int x, int y, bool dither, bool invert)
|
||||
// {
|
||||
// int w = bmpHeader.width;
|
||||
// int h = bmpHeader.height;
|
||||
// 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++)
|
||||
// {
|
||||
// if (dither)
|
||||
// drawPixel(i + x, h - 1 - j + y, ditherGetPixel(i, j, w, h) >> 5);
|
||||
// else
|
||||
// {
|
||||
// uint8_t px = 0;
|
||||
// if (invert)
|
||||
// px = ((255 - *(bufferPtr++)) * 2126 / 10000) + ((255 - *(bufferPtr++)) * 7152 / 10000) +
|
||||
// ((255 - *(bufferPtr++)) * 722 / 10000);
|
||||
// else
|
||||
// px = (*(bufferPtr++) * 2126 / 10000) + (*(bufferPtr++) * 7152 / 10000) +
|
||||
// (*(bufferPtr++) * 722 / 10000);
|
||||
// drawPixel(i + x, h - 1 - j + y, px >> 5);
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (dither)
|
||||
// ditherSwap(w);
|
||||
|
||||
// if (padding)
|
||||
// {
|
||||
// for (int p = 0; p < padding; p++)
|
||||
// {
|
||||
// f->read();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// f->close();
|
||||
// return 1;
|
||||
// }
|
||||
return 1;
|
||||
}
|
|
@ -1,5 +1,77 @@
|
|||
#include "Image.h"
|
||||
|
||||
#include "../libs/TJpeg/TJpg_Decoder.h"
|
||||
|
||||
#define RED(a) ((((a)&0xf800) >> 11) << 3)
|
||||
#define GREEN(a) ((((a)&0x07e0) >> 5) << 2)
|
||||
#define BLUE(a) (((a)&0x001f) << 3)
|
||||
|
||||
#define RGB3BIT(r, g, b) ((54UL * (r) + 183UL * (g) + 19UL * (b)) >> 13)
|
||||
|
||||
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)
|
||||
{
|
||||
if (!_imagePtrJpeg)
|
||||
return 0;
|
||||
|
||||
_imagePtrJpeg->startWrite();
|
||||
for (int j = 0; j < h; ++j)
|
||||
{
|
||||
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)));
|
||||
}
|
||||
}
|
||||
_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;
|
||||
}
|
|
@ -1 +1,76 @@
|
|||
#include "Network.h"
|
||||
|
||||
bool Network::joinAP(char *ssid, char *pass)
|
||||
{
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
int cnt = 0;
|
||||
while (!isConnected())
|
||||
{
|
||||
if (cnt > 15)
|
||||
return 0;
|
||||
delay(1000);
|
||||
++cnt;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Network::disconnect()
|
||||
{
|
||||
WiFi.mode(WIFI_OFF);
|
||||
}
|
||||
|
||||
bool Network::isConnected()
|
||||
{
|
||||
return WiFi.status() == WL_CONNECTED;
|
||||
}
|
||||
|
||||
bool Network::downloadFile(uint8_t *buffer, const char *url)
|
||||
{
|
||||
if (!isConnected())
|
||||
return 0;
|
||||
|
||||
int ret = 0;
|
||||
uint8_t *bufferPtr = buffer;
|
||||
|
||||
bool sleep = WiFi.getSleep();
|
||||
WiFi.setSleep(false);
|
||||
|
||||
HTTPClient http;
|
||||
http.getStream().setNoDelay(true);
|
||||
http.getStream().setTimeout(1);
|
||||
http.begin(url);
|
||||
|
||||
int httpCode = http.GET();
|
||||
if (httpCode == 200)
|
||||
{
|
||||
int total = http.getSize();
|
||||
int len = total;
|
||||
|
||||
uint8_t buff[128] = {0};
|
||||
|
||||
WiFiClient *stream = http.getStreamPtr();
|
||||
|
||||
while (http.connected() && (len > 0 || len == -1))
|
||||
{
|
||||
size_t size = stream->available();
|
||||
if (size)
|
||||
{
|
||||
int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
|
||||
|
||||
memcpy(bufferPtr, buff, c);
|
||||
bufferPtr += c;
|
||||
|
||||
if (len > 0)
|
||||
len -= c;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
http.end();
|
||||
WiFi.setSleep(sleep);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,13 @@
|
|||
class Network
|
||||
{
|
||||
public:
|
||||
private:
|
||||
bool joinAP(char *ssid, char *pass);
|
||||
void disconnect();
|
||||
bool isConnected();
|
||||
|
||||
bool downloadFile(uint8_t *buffer, const char *url);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
|
@ -16,14 +16,14 @@
|
|||
void Shapes::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
|
||||
{
|
||||
startWrite();
|
||||
writeFastHLine(x, y, h, color);
|
||||
writeFastVLine(x, y, h, color);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Shapes::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
|
||||
{
|
||||
startWrite();
|
||||
writeLine(x, y, x + w - 1, y, color);
|
||||
writeFastHLine(x, y, w, color);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
|
@ -327,3 +327,151 @@ void Shapes::fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_
|
|||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
|
||||
void Shapes::drawElipse(int rx, int ry, int xc, int yc, int c)
|
||||
{
|
||||
float dx, dy, d1, d2, x, y;
|
||||
x = 0;
|
||||
y = ry;
|
||||
|
||||
d1 = (ry * ry) - (rx * rx * ry) + (0.25 * rx * rx);
|
||||
dx = 2 * ry * ry * x;
|
||||
dy = 2 * rx * rx * y;
|
||||
|
||||
while (dx < dy)
|
||||
{
|
||||
drawPixel(x + xc, y + yc, c);
|
||||
drawPixel(-x + xc, y + yc, c);
|
||||
drawPixel(x + xc, -y + yc, c);
|
||||
drawPixel(-x + xc, -y + yc, c);
|
||||
|
||||
if (d1 < 0)
|
||||
{
|
||||
x++;
|
||||
dx = dx + (2 * ry * ry);
|
||||
d1 = d1 + dx + (ry * ry);
|
||||
}
|
||||
else
|
||||
{
|
||||
x++;
|
||||
y--;
|
||||
dx = dx + (2 * ry * ry);
|
||||
dy = dy - (2 * rx * rx);
|
||||
d1 = d1 + dx - dy + (ry * ry);
|
||||
}
|
||||
}
|
||||
|
||||
d2 = ((ry * ry) * ((x + 0.5) * (x + 0.5))) + ((rx * rx) * ((y - 1) * (y - 1))) - (rx * rx * ry * ry);
|
||||
while (y >= 0)
|
||||
{
|
||||
drawPixel(x + xc, y + yc, c);
|
||||
drawPixel(-x + xc, y + yc, c);
|
||||
drawPixel(x + xc, -y + yc, c);
|
||||
drawPixel(-x + xc, -y + yc, c);
|
||||
|
||||
if (d2 > 0)
|
||||
{
|
||||
y--;
|
||||
dy = dy - (2 * rx * rx);
|
||||
d2 = d2 + (rx * rx) - dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
y--;
|
||||
x++;
|
||||
dx = dx + (2 * ry * ry);
|
||||
dy = dy - (2 * rx * rx);
|
||||
d2 = d2 + dx - dy + (rx * rx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Shapes::fillElipse(int rx, int ry, int xc, int yc, int c)
|
||||
{
|
||||
int hh = ry * ry;
|
||||
int ww = rx * rx;
|
||||
int hhww = hh * ww;
|
||||
int x0 = rx;
|
||||
int dx = 0;
|
||||
|
||||
for (int x = -rx; x <= rx; x++)
|
||||
drawPixel(xc + x, yc, c);
|
||||
|
||||
for (int y = 1; y <= ry; y++)
|
||||
{
|
||||
int x1 = x0 - (dx - 1);
|
||||
for (; x1 > 0; x1--)
|
||||
if (x1 * x1 * hh + y * y * ww <= hhww)
|
||||
break;
|
||||
dx = x0 - x1;
|
||||
x0 = x1;
|
||||
|
||||
for (int x = -x0; x <= x0; x++)
|
||||
{
|
||||
drawPixel(xc + x, yc - y, c);
|
||||
drawPixel(xc + x, yc + y, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Shapes::fillPolygon(int *x, int *y, int n, int color)
|
||||
{
|
||||
int tx[100], ty[100];
|
||||
triangulate.triangulate(x, y, n, tx, ty);
|
||||
|
||||
for (int i = 0; i < n - 2; ++i)
|
||||
{
|
||||
fillTriangle(tx[i * 3 + 0], ty[i * 3 + 0], tx[i * 3 + 1], ty[i * 3 + 1], tx[i * 3 + 2], ty[i * 3 + 2], color);
|
||||
}
|
||||
}
|
||||
|
||||
void Shapes::drawPolygon(int *x, int *y, int n, int color)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
drawLine(x[i], y[i], x[(i + 1) % n], y[(i + 1) % n], color);
|
||||
}
|
||||
|
||||
void Shapes::drawThickLine(int x1, int y1, int x2, int y2, int color, float thickness)
|
||||
{
|
||||
float deg = atan2f((float)(y2 - y1), (float)(x2 - x1));
|
||||
|
||||
float l1 = tan(deg);
|
||||
float k1 = (float)y1 - l1 * (float)x1;
|
||||
|
||||
float degShift = (l1 < 0 ? M_PI_2 : -M_PI_2);
|
||||
|
||||
int x3 = (int)round((float)x1 + thickness / 2.0 * cos(deg + degShift));
|
||||
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 Shapes::drawGradientLine(int x1, int y1, int x2, int y2, int color1, int color2, float thickness)
|
||||
{
|
||||
int n = color2 - color1;
|
||||
|
||||
float px = (float)(x2 - x1) / (float)n;
|
||||
float py = (float)(y2 - y1) / (float)n;
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
if (abs(thickness + 1) < 0.1)
|
||||
drawLine((int)((float)x1 + (float)i * px), (int)((float)y1 + (float)i * py),
|
||||
(int)((float)x1 + (float)(i + 1) * px), (int)((float)y1 + (float)(i + 1) * py), color1 + i);
|
||||
else
|
||||
drawThickLine((int)((float)x1 + (float)i * px), (int)((float)y1 + (float)i * py),
|
||||
(int)((float)x1 + (float)(i + 1) * px), (int)((float)y1 + (float)(i + 1) * py), color1 + i,
|
||||
thickness);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __SHAPES_H__
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Triangulate.h"
|
||||
|
||||
class Shapes
|
||||
{
|
||||
|
@ -29,7 +30,16 @@ class Shapes
|
|||
void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
|
||||
void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
|
||||
|
||||
void drawElipse(int rx, int ry, int xc, int yc, int c);
|
||||
void fillElipse(int rx, int ry, int xc, int yc, int c);
|
||||
void drawPolygon(int *x, int *y, int n, int color);
|
||||
void fillPolygon(int *x, int *y, int n, int color);
|
||||
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);
|
||||
|
||||
private:
|
||||
Triangulate triangulate;
|
||||
|
||||
virtual void startWrite(void) = 0;
|
||||
virtual void writePixel(int16_t x, int16_t y, uint16_t color) = 0;
|
||||
virtual void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) = 0;
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
#include "Triangulate.h"
|
||||
#include "Arduino.h"
|
||||
#include "math.h"
|
||||
|
||||
float Triangulate::area(int x1, int y1, int x2, int y2, int x3, int y3)
|
||||
{
|
||||
return fabs((float)((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2))) / 2.0);
|
||||
}
|
||||
|
||||
bool Triangulate::isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y)
|
||||
{
|
||||
float A = area(x1, y1, x2, y2, x3, y3);
|
||||
float A1 = area(x, y, x2, y2, x3, y3);
|
||||
float A2 = area(x1, y1, x, y, x3, y3);
|
||||
float A3 = area(x1, y1, x2, y2, x, y);
|
||||
return fabs(-A + A1 + A2 + A3) < 1e-3;
|
||||
}
|
||||
|
||||
void Triangulate::preProcess(int *x, int *y, int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
int prev = (i - 1 + n) % n;
|
||||
int next = (i + 1 + n) % n;
|
||||
float deg = atan2(y[prev] - y[i], x[prev] - x[i]) - atan2(y[next] - y[i], x[next] - x[i]);
|
||||
if (deg < 0.0)
|
||||
deg += 2 * M_PI;
|
||||
innerAngle[i] = deg;
|
||||
}
|
||||
}
|
||||
|
||||
void Triangulate::updateVertex(int p, int *x, int *y, int n)
|
||||
{
|
||||
int prev = (p - 1 + n) % n;
|
||||
int next = (p + 1 + n) % n;
|
||||
float deg = atan2(y[prev] - y[p], x[prev] - x[p]) - atan2(y[next] - y[p], x[next] - x[p]);
|
||||
if (deg < 0.0)
|
||||
deg += 2 * M_PI;
|
||||
innerAngle[p] = deg;
|
||||
bool f = 0;
|
||||
for (int j = 0; j < n; ++j)
|
||||
{
|
||||
if (prev != j && p != j && next != j && innerAngle[p] > M_PI &&
|
||||
isInside(x[prev], y[prev], x[p], y[p], x[next], y[next], x[j], y[j]))
|
||||
f = 1;
|
||||
}
|
||||
earTip[p] = !f;
|
||||
}
|
||||
|
||||
bool Triangulate::isConvex(int *x, int *y, int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (innerAngle[i] > M_PI)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Triangulate::trivialTriangles(int *x, int *y, int n)
|
||||
{
|
||||
for (int i = 0; i < n - 2; ++i)
|
||||
{
|
||||
tx[tc] = x[0];
|
||||
ty[tc] = y[0];
|
||||
++tc;
|
||||
tx[tc] = x[i + 1];
|
||||
ty[tc] = y[i + 1];
|
||||
++tc;
|
||||
tx[tc] = x[i + 2];
|
||||
ty[tc] = y[i + 2];
|
||||
++tc;
|
||||
}
|
||||
}
|
||||
|
||||
void Triangulate::findEars(int *x, int *y, int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
if (innerAngle[i] > M_PI)
|
||||
continue;
|
||||
int prev = (i - 1 + n) % n;
|
||||
int next = (i + 1 + n) % n;
|
||||
bool f = 0;
|
||||
for (int j = 0; j < n; ++j)
|
||||
{
|
||||
if (prev != j && i != j && next != j && innerAngle[i] > M_PI &&
|
||||
isInside(x[prev], y[prev], x[i], y[i], x[next], y[next], x[j], y[j]))
|
||||
f = 1;
|
||||
}
|
||||
earTip[i] = !f;
|
||||
}
|
||||
}
|
||||
|
||||
int Triangulate::smallestEar(int *x, int *y, int n)
|
||||
{
|
||||
int mn = 0;
|
||||
for (int i = 1; i < n; ++i)
|
||||
if (earTip[i] && innerAngle[i] < innerAngle[mn])
|
||||
mn = i;
|
||||
return mn;
|
||||
}
|
||||
|
||||
void Triangulate::nonTrivialTriangles(int *x, int *y, int n)
|
||||
{
|
||||
findEars(x, y, n);
|
||||
int initialN = n;
|
||||
while (tc / 3 < initialN - 2)
|
||||
{
|
||||
int pos = smallestEar(x, y, n);
|
||||
int prev = (pos - 1 + n) % n;
|
||||
int next = (pos + 1 + n) % n;
|
||||
tx[tc] = x[prev];
|
||||
ty[tc] = y[prev];
|
||||
++tc;
|
||||
tx[tc] = x[pos];
|
||||
ty[tc] = y[pos];
|
||||
++tc;
|
||||
tx[tc] = x[next];
|
||||
ty[tc] = y[next];
|
||||
++tc;
|
||||
for (int i = pos; i < n - 1; i++)
|
||||
{
|
||||
x[i] = x[i + 1];
|
||||
y[i] = y[i + 1];
|
||||
innerAngle[i] = innerAngle[i + 1];
|
||||
earTip[i] = earTip[i + 1];
|
||||
}
|
||||
--n;
|
||||
updateVertex(prev, x, y, n);
|
||||
updateVertex(prev + 1, x, y, n);
|
||||
}
|
||||
}
|
||||
|
||||
void Triangulate::triangulate(int *x, int *y, int n, int *_tx, int *_ty)
|
||||
{
|
||||
tc = 0;
|
||||
preProcess(x, y, n);
|
||||
if (isConvex(x, y, n))
|
||||
trivialTriangles(x, y, n);
|
||||
else
|
||||
nonTrivialTriangles(x, y, n);
|
||||
memcpy(_tx, tx, 100);
|
||||
memcpy(_ty, ty, 100);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef TRIANGULATE_H
|
||||
#define TRIANGULATE_H
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
class Triangulate
|
||||
{
|
||||
private:
|
||||
int tx[100];
|
||||
int ty[100];
|
||||
int tc = 0;
|
||||
|
||||
float innerAngle[100];
|
||||
bool earTip[100];
|
||||
|
||||
float area(int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
bool isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y);
|
||||
void preProcess(int *x, int *y, int n);
|
||||
void updateVertex(int p, int *x, int *y, int n);
|
||||
bool isConvex(int *x, int *y, int n);
|
||||
void trivialTriangles(int *x, int *y, int n);
|
||||
void findEars(int *x, int *y, int n);
|
||||
int smallestEar(int *x, int *y, int n);
|
||||
void nonTrivialTriangles(int *x, int *y, int n);
|
||||
|
||||
public:
|
||||
void triangulate(int *x, int *y, int n, int *_tx, int *_ty);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -24,7 +24,7 @@
|
|||
#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_3BIT); // 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()
|
||||
|
@ -49,7 +49,7 @@ void loop()
|
|||
// 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("4bitish.bmp", 200, 0, 0))
|
||||
if (!display.drawBitmapFromSD("4bitTest.bmp", 0, 0, 0))
|
||||
{
|
||||
// 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
|
||||
|
|
Loading…
Reference in New Issue