Merge pull request #7 from Thorinair/master
Added drawBitmapFromWeb method
This commit is contained in:
commit
a3f684d59d
181
Inkplate.cpp
181
Inkplate.cpp
|
@ -1,6 +1,8 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "Adafruit_GFX.h"
|
||||
#include "WiFi.h"
|
||||
#include "HTTPClient.h"
|
||||
#include "Inkplate.h"
|
||||
Adafruit_MCP23017 mcp;
|
||||
SPIClass spi2(HSPI);
|
||||
|
@ -331,7 +333,7 @@ uint8_t Inkplate::getDisplayMode() {
|
|||
int Inkplate::drawBitmapFromSD(SdFile* p, int x, int y) {
|
||||
if(sdCardOk == 0) return 0;
|
||||
struct bitmapHeader bmpHeader;
|
||||
readBmpHeader(p, &bmpHeader);
|
||||
readBmpHeaderSd(p, &bmpHeader);
|
||||
if (bmpHeader.signature != 0x4D42 || bmpHeader.compression != 0 || !(bmpHeader.color == 1 || bmpHeader.color == 24)) return 0;
|
||||
|
||||
if ((bmpHeader.color == 24 || bmpHeader.color == 32) && getDisplayMode() != INKPLATE_3BIT) {
|
||||
|
@ -342,8 +344,8 @@ int Inkplate::drawBitmapFromSD(SdFile* p, int x, int y) {
|
|||
selectDisplayMode(INKPLATE_1BIT);
|
||||
}
|
||||
|
||||
if (bmpHeader.color == 1) drawMonochromeBitmap(p, bmpHeader, x, y);
|
||||
if (bmpHeader.color == 24) drawGrayscaleBitmap24(p, bmpHeader, x, y);
|
||||
if (bmpHeader.color == 1) drawMonochromeBitmapSd(p, bmpHeader, x, y);
|
||||
if (bmpHeader.color == 24) drawGrayscaleBitmap24Sd(p, bmpHeader, x, y);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -358,6 +360,51 @@ int Inkplate::drawBitmapFromSD(char* fileName, int x, int y) {
|
|||
}
|
||||
}
|
||||
|
||||
int Inkplate::drawBitmapFromWeb(WiFiClient* s, int x, int y, int len, bool invert) {
|
||||
struct bitmapHeader bmpHeader;
|
||||
readBmpHeaderWeb(s, &bmpHeader);
|
||||
if (bmpHeader.signature != 0x4D42 || bmpHeader.compression != 0 || !(bmpHeader.color == 1 || bmpHeader.color == 24)) return 0;
|
||||
|
||||
if ((bmpHeader.color == 24 || bmpHeader.color == 32) && getDisplayMode() != INKPLATE_3BIT) {
|
||||
selectDisplayMode(INKPLATE_3BIT);
|
||||
}
|
||||
|
||||
if (bmpHeader.color == 1 && getDisplayMode() != INKPLATE_1BIT) {
|
||||
selectDisplayMode(INKPLATE_1BIT);
|
||||
}
|
||||
|
||||
if (bmpHeader.color == 1) drawMonochromeBitmapWeb(s, bmpHeader, x, y, len, invert);
|
||||
if (bmpHeader.color == 24) drawGrayscaleBitmap24Web(s, bmpHeader, x, y, len, invert);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawBitmapFromWeb(char* url, int x, int y, bool invert) {
|
||||
if (WiFi.status() != WL_CONNECTED) return 0;
|
||||
int ret = 0;
|
||||
|
||||
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) {
|
||||
int32_t len = http.getSize();
|
||||
if (len > 0) {
|
||||
WiFiClient * dat = http.getStreamPtr();
|
||||
ret = drawBitmapFromWeb(dat, x, y, len, invert);
|
||||
}
|
||||
}
|
||||
|
||||
http.end();
|
||||
WiFi.setSleep(sleep);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Inkplate::sdCardInit() {
|
||||
spi2.begin(14, 12, 13, 15);
|
||||
sdCardOk = sd.begin(15, SD_SCK_MHZ(25));
|
||||
|
@ -768,7 +815,7 @@ uint16_t Inkplate::read16(uint8_t* c) {
|
|||
return (*(c) | (*(c + 1) << 8));
|
||||
}
|
||||
|
||||
void Inkplate::readBmpHeader(SdFile *_f, struct bitmapHeader *_h) {
|
||||
void Inkplate::readBmpHeaderSd(SdFile *_f, struct bitmapHeader *_h) {
|
||||
uint8_t header[100];
|
||||
_f->rewind();
|
||||
_f->read(header, 100);
|
||||
|
@ -783,7 +830,21 @@ void Inkplate::readBmpHeader(SdFile *_f, struct bitmapHeader *_h) {
|
|||
return;
|
||||
}
|
||||
|
||||
int Inkplate::drawMonochromeBitmap(SdFile *f, struct bitmapHeader bmpHeader, int x, int y) {
|
||||
void Inkplate::readBmpHeaderWeb(WiFiClient *_s, struct bitmapHeader *_h) {
|
||||
uint8_t header[34];
|
||||
_s->read(header, 34);
|
||||
_h->signature = read16(header + 0);
|
||||
_h->fileSize = read32(header + 2);
|
||||
_h->startRAW = read32(header + 10);
|
||||
_h->dibHeaderSize = read32(header + 14);
|
||||
_h->width = read32(header + 18);
|
||||
_h->height = read32(header + 22);
|
||||
_h->color = read16(header + 28);
|
||||
_h->compression = read32(header + 30);
|
||||
return;
|
||||
}
|
||||
|
||||
int Inkplate::drawMonochromeBitmapSd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y) {
|
||||
int w = bmpHeader.width;
|
||||
int h = bmpHeader.height;
|
||||
uint8_t paddingBits = w % 32;
|
||||
|
@ -809,7 +870,7 @@ int Inkplate::drawMonochromeBitmap(SdFile *f, struct bitmapHeader bmpHeader, int
|
|||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawGrayscaleBitmap24(SdFile *f, struct bitmapHeader bmpHeader, int x, int y) {
|
||||
int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y) {
|
||||
int w = bmpHeader.width;
|
||||
int h = bmpHeader.height;
|
||||
char padding = w % 4;
|
||||
|
@ -838,6 +899,114 @@ int Inkplate::drawGrayscaleBitmap24(SdFile *f, struct bitmapHeader bmpHeader, in
|
|||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawMonochromeBitmapWeb(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert) {
|
||||
int w = bmpHeader.width;
|
||||
int h = bmpHeader.height;
|
||||
uint8_t paddingBits = w % 32;
|
||||
int total = len - 34;
|
||||
w /= 32;
|
||||
|
||||
uint8_t* buf = (uint8_t*) ps_malloc(total);
|
||||
if (buf == NULL)
|
||||
return 0;
|
||||
|
||||
int pnt = 0;
|
||||
while (pnt < total) {
|
||||
int toread = s->available();
|
||||
if (toread > 0) {
|
||||
int read = s->read(buf+pnt, toread);
|
||||
if (read > 0)
|
||||
pnt += read;
|
||||
}
|
||||
}
|
||||
|
||||
int i, j, k = bmpHeader.startRAW - 34;
|
||||
for (j = 0; j < h; j++) {
|
||||
for (i = 0; i < w; i++) {
|
||||
uint8_t a = buf[k++];
|
||||
uint8_t b = buf[k++];
|
||||
uint8_t c = buf[k++];
|
||||
uint8_t d = buf[k++];
|
||||
uint32_t pixelRow = a << 24 | b << 16 | c << 8 | d;
|
||||
if (invert)
|
||||
pixelRow = ~pixelRow;
|
||||
for (int n = 0; n < 32; n++) {
|
||||
drawPixel((i * 32) + n + x, h - j + y, !(pixelRow & (1ULL << (31 - n))));
|
||||
}
|
||||
}
|
||||
if (paddingBits) {
|
||||
uint8_t a = buf[k++];
|
||||
uint8_t b = buf[k++];
|
||||
uint8_t c = buf[k++];
|
||||
uint8_t d = buf[k++];
|
||||
uint32_t pixelRow = a << 24 | b << 16 | c << 8 | d;
|
||||
if (invert)
|
||||
pixelRow = ~pixelRow;
|
||||
for (int n = 0; n < paddingBits; n++) {
|
||||
drawPixel((i * 32) + n + x, h - j + y, !(pixelRow & (1ULL << (31 - n))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert) {
|
||||
int w = bmpHeader.width;
|
||||
int h = bmpHeader.height;
|
||||
char padding = w % 4;
|
||||
int total = len - 34;
|
||||
|
||||
uint8_t* buf = (uint8_t*) ps_malloc(total);
|
||||
if (buf == NULL)
|
||||
return 0;
|
||||
|
||||
int pnt = 0;
|
||||
while (pnt < total) {
|
||||
int toread = s->available();
|
||||
if (toread > 0) {
|
||||
int read = s->read(buf+pnt, toread);
|
||||
if (read > 0)
|
||||
pnt += read;
|
||||
}
|
||||
}
|
||||
|
||||
int i, j, k = bmpHeader.startRAW - 34;
|
||||
for (j = 0; j < h; j++) {
|
||||
for (i = 0; i < w; i++) {
|
||||
uint8_t r = buf[k++];
|
||||
uint8_t g = buf[k++];
|
||||
uint8_t b = buf[k++];
|
||||
if (invert) {
|
||||
r = 255 - r;
|
||||
g = 255 - g;
|
||||
b = 255 - b;
|
||||
}
|
||||
//This is the proper way of converting True Color (24 Bit RGB) bitmap file into grayscale, but it takes waaay too much time (full size picture takes about 17s to decode!)
|
||||
//float px = (0.2126 * (readByteFromSD(&file) / 255.0)) + (0.7152 * (readByteFromSD(&file) / 255.0)) + (0.0722 * (readByteFromSD(&file) / 255.0));
|
||||
//px = pow(px, 1.5);
|
||||
//display.drawPixel(i + x, h - j + y, (uint8_t)(px*7));
|
||||
|
||||
//So then, we are convertng it to grayscale using good old average and gamma correction (from LUT). With this metod, it is still slow (full size image takes 4 seconds), but much beter than prev mentioned method.
|
||||
uint8_t px = (r * 2126 / 10000) + (g * 7152 / 10000) + (b * 722 / 10000);
|
||||
//drawPixel(i + x, h - j + y, gammaLUT[px]);
|
||||
drawPixel(i + x, h - j + y, px>>5);
|
||||
//drawPixel(i + x, h - j + y, px/32);
|
||||
}
|
||||
if (padding) {
|
||||
for (int p = 0; p < padding; p++) {
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Inkplate::precalculateGamma(uint8_t* c, float gamma) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
c[i] = int(round((pow(i / 255.0, gamma)) * 15));
|
||||
|
|
12
Inkplate.h
12
Inkplate.h
|
@ -15,6 +15,7 @@
|
|||
#include "SPI.h"
|
||||
#include "Adafruit_MCP23017.h"
|
||||
#include "SdFat.h"
|
||||
#include "WiFiClient.h"
|
||||
|
||||
#define INKPLATE_GAMMA 1.45
|
||||
#define E_INK_WIDTH 800
|
||||
|
@ -132,6 +133,8 @@ class Inkplate : public Adafruit_GFX {
|
|||
uint8_t getDisplayMode();
|
||||
int drawBitmapFromSD(SdFile* p, int x, int y);
|
||||
int drawBitmapFromSD(char* fileName, int x, int y);
|
||||
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 sdCardInit();
|
||||
SdFat getSdFat();
|
||||
SPIClass getSPI();
|
||||
|
@ -163,9 +166,12 @@ class Inkplate : public Adafruit_GFX {
|
|||
void display3b();
|
||||
uint32_t read32(uint8_t* c);
|
||||
uint16_t read16(uint8_t* c);
|
||||
void readBmpHeader(SdFile *_f, struct bitmapHeader *_h);
|
||||
int drawMonochromeBitmap(SdFile *f, struct bitmapHeader bmpHeader, int x, int y);
|
||||
int drawGrayscaleBitmap24(SdFile *f, struct bitmapHeader bmpHeader, int x, int y);
|
||||
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);
|
||||
int drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y);
|
||||
int drawMonochromeBitmapWeb(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);
|
||||
void precalculateGamma(uint8_t* c, float gamma);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
10_Inkplate_Download_And_Show example for e-radionica Inkplate6
|
||||
For this example you will need a micro USB cable, Inkplate6, an SD card and an
|
||||
available WiFi connection.
|
||||
Select "Inkplate 6(ESP32)" from Tools -> Board menu.
|
||||
Don't have "Inkplate 6(ESP32)" option? Follow our tutorial and add it:
|
||||
https://e-radionica.com/en/blog/add-inkplate-6-to-arduino-ide/
|
||||
|
||||
To work with SD card on Inkplate, you will need to add one extra library.
|
||||
Download and install it from here: https://github.com/e-radionicacom/Inkplate-6-SDFat-Arduino-Library
|
||||
|
||||
You can open .bmp files that have color depth of 1 bit (monochrome bitmap) and
|
||||
24 bit AND have resoluton smaller than 800x600 or otherwise it won't fit on screen.
|
||||
|
||||
This example will show you how you can download a .bmp file (picture) from the web to the SD card and
|
||||
display that image on e-paper display.
|
||||
|
||||
Want to learn more about Inkplate? Visit www.inkplate.io
|
||||
Looking to get support? Write on our forums: http://forum.e-radionica.com/en/
|
||||
23 July 2020 by e-radionica.com
|
||||
*/
|
||||
|
||||
#include "Inkplate.h" //Include Inkplate library to the sketch
|
||||
#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)
|
||||
SdFile file; //Create SdFile object used for accessing files on SD card
|
||||
|
||||
const char* ssid = "YourWiFiSSID"; //Your WiFi SSID
|
||||
const char* password = "YourPass"; //Your WiFi password
|
||||
|
||||
void setup() {
|
||||
display.begin(); //Init Inkplate library (you should call this function ONLY ONCE)
|
||||
display.clearDisplay(); //Clear frame buffer of display
|
||||
display.display(); //Put clear image on display
|
||||
|
||||
display.print("Connecting to WiFi...");
|
||||
display.partialUpdate();
|
||||
|
||||
//Connect to the WiFi network.
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
display.print(".");
|
||||
display.partialUpdate();
|
||||
}
|
||||
display.println("\nWiFi OK! Downloading...");
|
||||
display.partialUpdate();
|
||||
|
||||
//Draw the first image from web.
|
||||
//Monochromatic bitmap with 1 bit depth. Images like this load quickest.
|
||||
//The parameter set to true at the end may be used to swap the black and white channels.
|
||||
//Photo taken by: Roberto Fernandez
|
||||
if(!display.drawBitmapFromWeb("https://varipass.org/neowise_mono.bmp", 0, 0, 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 or 24 bits with no compression!
|
||||
display.println("Image open error");
|
||||
display.display();
|
||||
}
|
||||
display.display();
|
||||
|
||||
//Draw the second image from web.
|
||||
//Full color 24 bit images are large and take a long time to load, will take around 20 secs.
|
||||
//Photo taken by: Roberto Fernandez
|
||||
if(!display.drawBitmapFromWeb("https://varipass.org/neowise.bmp", 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 or 24 bits with no compression!
|
||||
display.println("Image open error");
|
||||
display.display();
|
||||
}
|
||||
display.display();
|
||||
|
||||
WiFi.mode(WIFI_OFF);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
//Nothing...
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
Loading…
Reference in New Issue