Added bmp dither.
This commit is contained in:
parent
e5ca63391a
commit
82a082003a
|
@ -16,32 +16,41 @@
|
|||
*/
|
||||
|
||||
#include "Inkplate.h" //Include Inkplate library to the sketch
|
||||
#include <WiFi.h> //Include ESP32 WiFi library to our sketch
|
||||
#include <HTTPClient.h> //Include HTTP library to this sketch
|
||||
#include <WiFi.h> //Include ESP32 WiFi library to our sketch
|
||||
|
||||
#define ssid "" //Name of the WiFi network (SSID) that you want to connect Inkplate to
|
||||
#define pass "" //Password of that WiFi network
|
||||
#define ssid "" // Name of the WiFi network (SSID) that you want to connect Inkplate to
|
||||
#define pass "" // Password of that WiFi network
|
||||
|
||||
Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome)
|
||||
Inkplate display(
|
||||
INKPLATE_1BIT); // Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome)
|
||||
|
||||
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.setTextSize(2); //Set text scaling to two (text will be two times bigger)
|
||||
display.setCursor(0, 0); //Set print position
|
||||
display.setTextColor(BLACK, WHITE); //Set text color to black and background color to white
|
||||
display.println("Scanning for WiFi networks..."); //Write text
|
||||
display.display(); //Send everything to display (refresh display)
|
||||
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.setTextSize(2); // Set text scaling to two (text will be two times bigger)
|
||||
display.setCursor(0, 0); // Set print position
|
||||
display.setTextColor(BLACK, WHITE); // Set text color to black and background color to white
|
||||
display.println("Scanning for WiFi networks..."); // Write text
|
||||
display.display(); // Send everything to display (refresh display)
|
||||
|
||||
int n = WiFi.scanNetworks(); //Start searching WiFi networks and put the nubmer of found WiFi networks in variable n
|
||||
if (n == 0) { //If you did not find any network, show the message and stop the program.
|
||||
int n = WiFi.scanNetworks(); // Start searching WiFi networks and put the nubmer of found WiFi networks in variable
|
||||
// n
|
||||
if (n == 0)
|
||||
{ // If you did not find any network, show the message and stop the program.
|
||||
display.print("No WiFi networks found!");
|
||||
display.partialUpdate();
|
||||
while (true);
|
||||
} else {
|
||||
if (n > 10) n = 0; //If you did find, print name (SSID), encryption and signal strength of first 10 networks
|
||||
for (int i = 0; i < n; i++) {
|
||||
while (true)
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n > 10)
|
||||
n = 0; // If you did find, print name (SSID), encryption and signal strength of first 10 networks
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
display.print(WiFi.SSID(i));
|
||||
display.print((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? 'O' : '*');
|
||||
display.print('\n');
|
||||
|
@ -50,25 +59,29 @@ void setup() {
|
|||
display.partialUpdate(); //(Partial) refresh thescreen
|
||||
}
|
||||
|
||||
display.clearDisplay(); //Clear everything in frame buffer
|
||||
display.setCursor(0,0); //Set print cursor to new position
|
||||
display.print("Connecting to "); //Print the name of WiFi network
|
||||
display.clearDisplay(); // Clear everything in frame buffer
|
||||
display.setCursor(0, 0); // Set print cursor to new position
|
||||
display.print("Connecting to "); // Print the name of WiFi network
|
||||
display.print(ssid);
|
||||
WiFi.begin(ssid, pass); //Try to connect to WiFi network
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(1000); //While it is connecting to network, display dot every second, just to know that Inkplate is alive.
|
||||
WiFi.begin(ssid, pass); // Try to connect to WiFi network
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
delay(1000); // While it is connecting to network, display dot every second, just to know that Inkplate is
|
||||
// alive.
|
||||
display.print('.');
|
||||
display.partialUpdate();
|
||||
}
|
||||
display.print("connected"); //If it's connected, notify user
|
||||
display.print("connected"); // If it's connected, notify user
|
||||
display.partialUpdate();
|
||||
|
||||
HTTPClient http;
|
||||
if(http.begin("http://example.com/index.html")) { //Now try to connect to some web page (in this example www.example.com. And yes, this is a valid Web page :))
|
||||
if(http.GET()>0) { //If connection was successful, try to read content of the Web page and display it on screen
|
||||
if (http.begin("http://example.com/index.html"))
|
||||
{ // Now try to connect to some web page (in this example www.example.com. And yes, this is a valid Web page :))
|
||||
if (http.GET() > 0)
|
||||
{ // If connection was successful, try to read content of the Web page and display it on screen
|
||||
String htmlText;
|
||||
htmlText = http.getString();
|
||||
display.setTextSize(1); //Set smaller text size, so everything can fit on screen
|
||||
display.setTextSize(1); // Set smaller text size, so everything can fit on screen
|
||||
display.clearDisplay();
|
||||
display.setCursor(0, 0);
|
||||
display.print(htmlText);
|
||||
|
@ -77,6 +90,7 @@ void setup() {
|
|||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
//Nothing
|
||||
void loop()
|
||||
{
|
||||
// Nothing
|
||||
}
|
||||
|
|
|
@ -23,50 +23,58 @@
|
|||
|
||||
#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)
|
||||
SdFile file; //Create SdFile object used for accessing files on SD card
|
||||
Inkplate display(
|
||||
INKPLATE_1BIT); // Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome)
|
||||
SdFile file; // Create SdFile object used for accessing files on SD card
|
||||
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
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
|
||||
display.begin(); // Init Inkplate library (you should call this function ONLY ONCE)
|
||||
display.clearDisplay(); // Clear frame buffer of display
|
||||
display.display(); // Put clear image on display
|
||||
|
||||
//Init SD card. Display if SD card is init propery or not.
|
||||
if (display.sdCardInit()) {
|
||||
// Init SD card. Display if SD card is init propery or not.
|
||||
if (display.sdCardInit())
|
||||
{
|
||||
display.println("SD Card OK! Reading image...");
|
||||
display.partialUpdate();
|
||||
|
||||
//If card is properly init, try to load image and display it on e-paper at position X=0, Y=0
|
||||
//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, 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
|
||||
// If card is properly init, try to load image and display it on e-paper at position X=0, Y=0
|
||||
// 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, 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 {
|
||||
//If SD card init not success, display error on screen and stop the program (using infinite loop)
|
||||
else
|
||||
{
|
||||
// If SD card init not success, display error on screen and stop the program (using infinite loop)
|
||||
display.println("SD Card error!");
|
||||
display.partialUpdate();
|
||||
while (true);
|
||||
while (true)
|
||||
;
|
||||
}
|
||||
delay(5000);
|
||||
|
||||
//Now try to load image using SdFat library class (for more advanced users) and display image on epaper.
|
||||
if (file.open("image2.bmp", O_RDONLY)) {
|
||||
display.drawBitmapFromSD(&file, 0, 0);
|
||||
// Now try to load image using SdFat library class (for more advanced users) and display image on epaper.
|
||||
if (file.open("image2.bmp", O_RDONLY))
|
||||
{
|
||||
display.drawBitmapFromSd(&file, 0, 0);
|
||||
display.display();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
//Nothing...
|
||||
void loop()
|
||||
{
|
||||
// Nothing...
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
If we missed some function, you can modify this and make yor own.
|
||||
Also, every Inkplate comes with this slave mode right from the factory.
|
||||
|
||||
Learn more about Slave Mode in this update: https://www.crowdsupply.com/e-radionica/inkplate-6/updates/successfully-funded-also-third-party-master-controllers-and-partial-updates
|
||||
Learn more about Slave Mode in this update:
|
||||
https://www.crowdsupply.com/e-radionica/inkplate-6/updates/successfully-funded-also-third-party-master-controllers-and-partial-updates
|
||||
|
||||
UART settings are: 115200 baud, standard parity, ending with "\n\r" (both)
|
||||
You can send commands via USB port or by directly connecting to ESP32 TX and RX pins.
|
||||
|
@ -31,17 +32,22 @@ Inkplate display(INKPLATE_1BIT);
|
|||
#define BUFFER_SIZE 1000
|
||||
char commandBuffer[BUFFER_SIZE + 1];
|
||||
char strTemp[2001];
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
display.begin();
|
||||
Serial.begin(115200);
|
||||
memset(commandBuffer, 0, BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
// put your main code here, to run repeatedly:
|
||||
if (Serial.available()) {
|
||||
while (Serial.available()) {
|
||||
for (int i = 0; i < (BUFFER_SIZE - 1); i++) {
|
||||
if (Serial.available())
|
||||
{
|
||||
while (Serial.available())
|
||||
{
|
||||
for (int i = 0; i < (BUFFER_SIZE - 1); i++)
|
||||
{
|
||||
commandBuffer[i] = commandBuffer[i + 1];
|
||||
}
|
||||
commandBuffer[BUFFER_SIZE - 1] = Serial.read();
|
||||
|
@ -49,170 +55,185 @@ void loop() {
|
|||
}
|
||||
char *s = NULL;
|
||||
char *e = NULL;
|
||||
for (int i = 0; i < BUFFER_SIZE; i++) {
|
||||
if (commandBuffer[i] == '#' && s == NULL) s = &commandBuffer[i];
|
||||
if (commandBuffer[i] == '*' && e == NULL) e = &commandBuffer[i];
|
||||
for (int i = 0; i < BUFFER_SIZE; i++)
|
||||
{
|
||||
if (commandBuffer[i] == '#' && s == NULL)
|
||||
s = &commandBuffer[i];
|
||||
if (commandBuffer[i] == '*' && e == NULL)
|
||||
e = &commandBuffer[i];
|
||||
}
|
||||
if (s != NULL && e != NULL) {
|
||||
if ((e - s) > 0) {
|
||||
if (s != NULL && e != NULL)
|
||||
{
|
||||
if ((e - s) > 0)
|
||||
{
|
||||
int x, x1, x2, y, y1, y2, x3, y3, l, c, w, h, r, n;
|
||||
char b;
|
||||
char temp[150];
|
||||
switch (*(s + 1)) {
|
||||
switch (*(s + 1))
|
||||
{
|
||||
case '?':
|
||||
Serial.print("OK");
|
||||
break;
|
||||
|
||||
case '0':
|
||||
sscanf(s + 3, "%d,%d,%d", &x, &y, &c);
|
||||
//sprintf(temp, "display.drawPixel(%d, %d, %d)\n\r", x, y, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.drawPixel(%d, %d, %d)\n\r", x, y, c);
|
||||
// Serial.print(temp);
|
||||
display.drawPixel(x, y, c);
|
||||
break;
|
||||
|
||||
case '1':
|
||||
sscanf(s + 3, "%d,%d,%d,%d,%d", &x1, &y1, &x2, &y2, &c);
|
||||
//sprintf(temp, "display.drawLine(%d, %d, %d, %d, %d)\n\r", x1, y1, x2, y2, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.drawLine(%d, %d, %d, %d, %d)\n\r", x1, y1, x2, y2, c);
|
||||
// Serial.print(temp);
|
||||
display.drawLine(x1, y1, x2, y2, c);
|
||||
break;
|
||||
|
||||
case '2':
|
||||
sscanf(s + 3, "%d,%d,%d,%d", &x, &y, &l, &c);
|
||||
//sprintf(temp, "display.drawFastVLine(%d, %d, %d, %d)\n\r", x, y, l, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.drawFastVLine(%d, %d, %d, %d)\n\r", x, y, l, c);
|
||||
// Serial.print(temp);
|
||||
display.drawFastVLine(x, y, l, c);
|
||||
break;
|
||||
|
||||
case '3':
|
||||
sscanf(s + 3, "%d,%d,%d,%d", &x, &y, &l, &c);
|
||||
//sprintf(temp, "display.drawFastHLine(%d, %d, %d, %d)\n\r", x, y, l, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.drawFastHLine(%d, %d, %d, %d)\n\r", x, y, l, c);
|
||||
// Serial.print(temp);
|
||||
display.drawFastHLine(x, y, l, c);
|
||||
break;
|
||||
|
||||
case '4':
|
||||
sscanf(s + 3, "%d,%d,%d,%d,%d", &x, &y, &w, &h, &c);
|
||||
//sprintf(temp, "display.drawRect(%d, %d, %d, %d, %d)\n\r", x, y, w, h, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.drawRect(%d, %d, %d, %d, %d)\n\r", x, y, w, h, c);
|
||||
// Serial.print(temp);
|
||||
display.drawRect(x, y, w, h, c);
|
||||
break;
|
||||
|
||||
case '5':
|
||||
sscanf(s + 3, "%d,%d,%d,%d", &x, &y, &r, &c);
|
||||
//sprintf(temp, "display.drawCircle(%d, %d, %d, %d)\n\r", x, y, r, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.drawCircle(%d, %d, %d, %d)\n\r", x, y, r, c);
|
||||
// Serial.print(temp);
|
||||
display.drawCircle(x, y, r, c);
|
||||
break;
|
||||
|
||||
case '6':
|
||||
sscanf(s + 3, "%d,%d,%d,%d,%d,%d,%d", &x1, &y1, &x2, &y2, &x3, &y3, &c);
|
||||
//sprintf(temp, "display.drawTriangle(%d, %d, %d, %d, %d, %d, %d)\n\r", x1, y1, x2, y2, x3, y3, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.drawTriangle(%d, %d, %d, %d, %d, %d, %d)\n\r", x1, y1, x2, y2, x3, y3, c);
|
||||
// Serial.print(temp);
|
||||
display.drawTriangle(x1, y1, x2, y2, x3, y3, c);
|
||||
break;
|
||||
|
||||
case '7':
|
||||
sscanf(s + 3, "%d,%d,%d,%d,%d,%d", &x, &y, &w, &h, &r, &c);
|
||||
//sprintf(temp, "display.drawRoundRect(%d, %d, %d, %d, %d, %d)\n\r", x, y, w, h, r, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.drawRoundRect(%d, %d, %d, %d, %d, %d)\n\r", x, y, w, h, r, c);
|
||||
// Serial.print(temp);
|
||||
display.drawRoundRect(x, y, w, h, r, c);
|
||||
break;
|
||||
|
||||
case '8':
|
||||
sscanf(s + 3, "%d,%d,%d,%d,%d", &x, &y, &w, &h, &c);
|
||||
//sprintf(temp, "display.fillRect(%d, %d, %d, %d, %d)\n\r", x, y, w, h, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.fillRect(%d, %d, %d, %d, %d)\n\r", x, y, w, h, c);
|
||||
// Serial.print(temp);
|
||||
display.fillRect(x, y, w, h, c);
|
||||
break;
|
||||
|
||||
case '9':
|
||||
sscanf(s + 3, "%d,%d,%d,%d", &x, &y, &r, &c);
|
||||
//sprintf(temp, "display.fillCircle(%d, %d, %d, %d)\n\r", x, y, r, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.fillCircle(%d, %d, %d, %d)\n\r", x, y, r, c);
|
||||
// Serial.print(temp);
|
||||
display.fillCircle(x, y, r, c);
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
sscanf(s + 3, "%d,%d,%d,%d,%d,%d,%d", &x1, &y1, &x2, &y2, &x3, &y3, &c);
|
||||
//sprintf(temp, "display.fillTriangle(%d, %d, %d, %d, %d, %d, %d)\n\r", x1, y1, x2, y2, x3, y3, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.fillTriangle(%d, %d, %d, %d, %d, %d, %d)\n\r", x1, y1, x2, y2, x3, y3, c);
|
||||
// Serial.print(temp);
|
||||
display.fillTriangle(x1, y1, x2, y2, x3, y3, c);
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
sscanf(s + 3, "%d,%d,%d,%d,%d,%d", &x, &y, &w, &h, &r, &c);
|
||||
//sprintf(temp, "display.fillRoundRect(%d, %d, %d, %d, %d, %d)\n\r", x, y, w, h, r, c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.fillRoundRect(%d, %d, %d, %d, %d, %d)\n\r", x, y, w, h, r, c);
|
||||
// Serial.print(temp);
|
||||
display.fillRoundRect(x, y, w, h, r, c);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
sscanf(s + 3, "\"%2000[^\"]\"", strTemp);
|
||||
n = strlen(strTemp);
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
strTemp[i] = toupper(strTemp[i]);
|
||||
}
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
for (int i = 0; i < n; i += 2)
|
||||
{
|
||||
strTemp[i / 2] = (hexToChar(strTemp[i]) << 4) | (hexToChar(strTemp[i + 1]) & 0x0F);
|
||||
}
|
||||
strTemp[n / 2] = 0;
|
||||
//Serial.print("display.print(\"");
|
||||
//Serial.print(strTemp);
|
||||
//Serial.println("\");");
|
||||
// Serial.print("display.print(\"");
|
||||
// Serial.print(strTemp);
|
||||
// Serial.println("\");");
|
||||
display.print(strTemp);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
sscanf(s + 3, "%d", &c);
|
||||
//sprintf(temp, "display.setTextSize(%d)\n", c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.setTextSize(%d)\n", c);
|
||||
// Serial.print(temp);
|
||||
display.setTextSize(c);
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
sscanf(s + 3, "%d,%d", &x, &y);
|
||||
//sprintf(temp, "display.setCursor(%d, %d)\n", x, y);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.setCursor(%d, %d)\n", x, y);
|
||||
// Serial.print(temp);
|
||||
display.setCursor(x, y);
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
sscanf(s + 3, "%c", &b);
|
||||
//sprintf(temp, "display.setTextWrap(%s)\n", b == 'T' ? "True" : "False");
|
||||
//Serial.print(temp);
|
||||
if (b == 'T') display.setTextWrap(true);
|
||||
if (b == 'F') display.setTextWrap(false);
|
||||
// sprintf(temp, "display.setTextWrap(%s)\n", b == 'T' ? "True" : "False");
|
||||
// Serial.print(temp);
|
||||
if (b == 'T')
|
||||
display.setTextWrap(true);
|
||||
if (b == 'F')
|
||||
display.setTextWrap(false);
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
sscanf(s + 3, "%d", &c);
|
||||
c &= 3;
|
||||
//sprintf(temp, "display.setRotation(%d)\n", c);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.setRotation(%d)\n", c);
|
||||
// Serial.print(temp);
|
||||
display.setRotation(c);
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
sscanf(s + 3, "%d,%d,\"%149[^\"]\"", &x, &y, strTemp);
|
||||
n = strlen(strTemp);
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
strTemp[i] = toupper(strTemp[i]);
|
||||
}
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
for (int i = 0; i < n; i += 2)
|
||||
{
|
||||
strTemp[i / 2] = (hexToChar(strTemp[i]) << 4) | (hexToChar(strTemp[i + 1]) & 0x0F);
|
||||
}
|
||||
strTemp[n / 2] = 0;
|
||||
r = display.sdCardInit();
|
||||
if (r) {
|
||||
r = display.drawBitmapFromSD(strTemp, x, y);
|
||||
if (r)
|
||||
{
|
||||
r = display.drawBitmapFromSd(strTemp, x, y);
|
||||
Serial.print("#H(");
|
||||
Serial.print(r, DEC);
|
||||
Serial.println(")*");
|
||||
Serial.flush();
|
||||
//sprintf(temp, "display.drawBitmap(%d, %d, %s)\n", x, y, strTemp);
|
||||
//Serial.print(temp);
|
||||
} else {
|
||||
// sprintf(temp, "display.drawBitmap(%d, %d, %s)\n", x, y, strTemp);
|
||||
// Serial.print(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("#H(-1)*");
|
||||
Serial.flush();
|
||||
}
|
||||
|
@ -220,25 +241,30 @@ void loop() {
|
|||
|
||||
case 'I':
|
||||
sscanf(s + 3, "%d", &c);
|
||||
//sprintf(temp, "display.setDisplayMode(%s)\n", c == 0 ? "INKPLATE_1BIT" : "INKPLATE_3BIT");
|
||||
//Serial.print(temp);
|
||||
if (c == INKPLATE_1BIT) display.selectDisplayMode(INKPLATE_1BIT);
|
||||
if (c == INKPLATE_3BIT) display.selectDisplayMode(INKPLATE_3BIT);
|
||||
// sprintf(temp, "display.setDisplayMode(%s)\n", c == 0 ? "INKPLATE_1BIT" : "INKPLATE_3BIT");
|
||||
// Serial.print(temp);
|
||||
if (c == INKPLATE_1BIT)
|
||||
display.selectDisplayMode(INKPLATE_1BIT);
|
||||
if (c == INKPLATE_3BIT)
|
||||
display.selectDisplayMode(INKPLATE_3BIT);
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
sscanf(s + 3, "%c", &b);
|
||||
if (b == '?') {
|
||||
//if (0 == 0) {
|
||||
if (b == '?')
|
||||
{
|
||||
// if (0 == 0) {
|
||||
// Serial.println("#J(0)*");
|
||||
//} else {
|
||||
// Serial.println("#J(1)*");
|
||||
//}
|
||||
if (display.getDisplayMode() == INKPLATE_1BIT) {
|
||||
if (display.getDisplayMode() == INKPLATE_1BIT)
|
||||
{
|
||||
Serial.println("#J(0)*");
|
||||
Serial.flush();
|
||||
}
|
||||
if (display.getDisplayMode() == INKPLATE_3BIT) {
|
||||
if (display.getDisplayMode() == INKPLATE_3BIT)
|
||||
{
|
||||
Serial.println("#J(1)*");
|
||||
Serial.flush();
|
||||
}
|
||||
|
@ -247,33 +273,36 @@ void loop() {
|
|||
|
||||
case 'K':
|
||||
sscanf(s + 3, "%c", &b);
|
||||
if (b == '1') {
|
||||
//Serial.print("display.clearDisplay();\n");
|
||||
if (b == '1')
|
||||
{
|
||||
// Serial.print("display.clearDisplay();\n");
|
||||
display.clearDisplay();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
sscanf(s + 3, "%c", &b);
|
||||
if (b == '1') {
|
||||
//Serial.print("display.display();\n");
|
||||
if (b == '1')
|
||||
{
|
||||
// Serial.print("display.display();\n");
|
||||
display.display();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
sscanf(s + 3, "%d,%d,%d", &y1, &x2, &y2);
|
||||
//sprintf(temp, "display.partialUpdate(%d, %d, %d);\n", y1, x2, y2);
|
||||
//Serial.print(temp);
|
||||
// sprintf(temp, "display.partialUpdate(%d, %d, %d);\n", y1, x2, y2);
|
||||
// Serial.print(temp);
|
||||
display.partialUpdate();
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
sscanf(s + 3, "%c", &b);
|
||||
if (b == '?') {
|
||||
if (b == '?')
|
||||
{
|
||||
Serial.print("#N(");
|
||||
Serial.print(display.readTemperature(), DEC);
|
||||
//Serial.print(23, DEC);
|
||||
// Serial.print(23, DEC);
|
||||
Serial.println(")*");
|
||||
Serial.flush();
|
||||
}
|
||||
|
@ -281,10 +310,11 @@ void loop() {
|
|||
|
||||
case 'O':
|
||||
sscanf(s + 3, "%d", &c);
|
||||
if (c >= 0 && c <= 2) {
|
||||
if (c >= 0 && c <= 2)
|
||||
{
|
||||
Serial.print("#O(");
|
||||
Serial.print(display.readTouchpad(c), DEC);
|
||||
//Serial.print(0, DEC);
|
||||
// Serial.print(0, DEC);
|
||||
Serial.println(")*");
|
||||
Serial.flush();
|
||||
}
|
||||
|
@ -292,10 +322,11 @@ void loop() {
|
|||
|
||||
case 'P':
|
||||
sscanf(s + 3, "%c", &b);
|
||||
if (b == '?') {
|
||||
if (b == '?')
|
||||
{
|
||||
Serial.print("#P(");
|
||||
Serial.print(display.readBattery(), 2);
|
||||
//Serial.print(3.54, 2);
|
||||
// Serial.print(3.54, 2);
|
||||
Serial.println(")*");
|
||||
Serial.flush();
|
||||
}
|
||||
|
@ -304,18 +335,21 @@ void loop() {
|
|||
case 'Q':
|
||||
sscanf(s + 3, "%d", &c);
|
||||
c &= 1;
|
||||
//if (c == 0) Serial.print("display.einkOff();\n");
|
||||
//if (c == 1) Serial.print("display.einkOn();\n");
|
||||
if (c == 0) display.einkOff();
|
||||
if (c == 1) display.einkOn();
|
||||
// if (c == 0) Serial.print("display.einkOff();\n");
|
||||
// if (c == 1) Serial.print("display.einkOn();\n");
|
||||
if (c == 0)
|
||||
display.einkOff();
|
||||
if (c == 1)
|
||||
display.einkOn();
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
sscanf(s + 3, "%c", &b);
|
||||
if (b == '?') {
|
||||
if (b == '?')
|
||||
{
|
||||
Serial.print("#R(");
|
||||
Serial.print(display.getPanelState(), DEC);
|
||||
//Serial.print(1, DEC);
|
||||
// Serial.print(1, DEC);
|
||||
Serial.println(")*");
|
||||
Serial.flush();
|
||||
}
|
||||
|
@ -327,7 +361,8 @@ void loop() {
|
|||
}
|
||||
}
|
||||
|
||||
int hexToChar(char c) {
|
||||
int hexToChar(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
if (c >= 'A' && c <= 'F')
|
||||
|
|
|
@ -29,7 +29,7 @@ bool Image::drawImage(const char *path, int x, int y, bool dither, bool invert)
|
|||
else
|
||||
{
|
||||
if (strstr(path, ".bmp") != NULL)
|
||||
return drawBitmapFromSD(path, x, y, dither, invert);
|
||||
return drawBitmapFromSd(path, x, y, dither, invert);
|
||||
if (strstr(path, ".jpg") != NULL || strstr(path, ".jpeg") != NULL)
|
||||
return drawJpegFromSD(path, x, y, dither, invert);
|
||||
}
|
||||
|
@ -43,143 +43,6 @@ bool Image::drawImage(const WiFiClient *s, int x, int y, int len, bool dither, b
|
|||
|
||||
};
|
||||
|
||||
// Loads first line in current dither buffer
|
||||
void Image::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 Image::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 Image::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 Image::ditherSwap(int w)
|
||||
{
|
||||
for (int i = 0; i < w; ++i)
|
||||
ditherBuffer[0][i] = ditherBuffer[1][i];
|
||||
}
|
||||
|
||||
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) >> 3; // Bitmap scanline pad = whole byte
|
||||
|
|
|
@ -28,8 +28,8 @@ class Image : virtual public Network
|
|||
uint16_t bg = 0xFFFF);
|
||||
void drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char *_p, int16_t _w, int16_t _h);
|
||||
|
||||
bool drawBitmapFromSD(SdFile *p, int x, int y, bool dither = 0, bool invert = 0);
|
||||
bool drawBitmapFromSD(const char *fileName, int x, int y, bool dither = 0, bool invert = 0);
|
||||
bool drawBitmapFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0);
|
||||
bool drawBitmapFromSd(const char *fileName, int x, int y, bool dither = 0, bool invert = 0);
|
||||
|
||||
bool drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool dither = 0, bool invert = 0);
|
||||
bool drawBitmapFromWeb(const char *url, int x, int y, bool dither = 0, bool invert = 0);
|
||||
|
@ -54,15 +54,16 @@ class Image : virtual public Network
|
|||
bool _invert);
|
||||
|
||||
uint8_t pixelBuffer[800 * 4 + 5];
|
||||
uint8_t ditherBuffer[800 * 3 + 5][2];
|
||||
uint8_t pallete[128]; // 2 colors per byte, _###_###
|
||||
uint8_t ditherBuffer[2][800 + 5];
|
||||
uint8_t ditherPalette[256]; // 8 bit colors
|
||||
uint8_t palette[128]; // 2 3 bit colors per byte, _###_###
|
||||
|
||||
bool legalBmp(bitmapHeader *bmpHeader);
|
||||
|
||||
void ditherStart(uint8_t *pixelBuffer, uint8_t *bufferPtr, int w, bool invert, uint8_t bits);
|
||||
void ditherLoadNextLine(uint8_t *pixelBuffer, uint8_t *bufferPtr, int w, bool invert, uint8_t bits);
|
||||
uint8_t ditherGetPixel(int i, int j, int w, int h);
|
||||
uint8_t ditherSwap(int w);
|
||||
uint8_t ditherGetPixel(uint8_t px, int i, int w, bool paletted);
|
||||
void ditherSwap(int w);
|
||||
|
||||
void readBmpHeader(uint8_t *buf, bitmapHeader *_h);
|
||||
void readBmpHeaderSd(SdFile *_f, bitmapHeader *_h);
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
#include "Image.h"
|
||||
|
||||
bool Image::legalBmp(bitmapHeader *bmpHeader)
|
||||
{
|
||||
return bmpHeader->signature == 0x4D42 && bmpHeader->compression == 0 &&
|
||||
(bmpHeader->color == 1 || bmpHeader->color == 4 || bmpHeader->color == 8 || bmpHeader->color == 16 ||
|
||||
bmpHeader->color == 24 || bmpHeader->color == 32);
|
||||
}
|
||||
|
||||
void Image::readBmpHeaderSd(SdFile *_f, bitmapHeader *_h)
|
||||
{
|
||||
uint8_t header[55];
|
||||
|
@ -7,8 +14,8 @@ void Image::readBmpHeaderSd(SdFile *_f, bitmapHeader *_h)
|
|||
_f->rewind();
|
||||
_f->read(header, 55);
|
||||
|
||||
uint16_t color = read16(header + 28);
|
||||
uint32_t totalColors = read32(header + 46);
|
||||
uint16_t color = READ16(header + 28);
|
||||
uint32_t totalColors = READ32(header + 46);
|
||||
|
||||
if (color <= 8)
|
||||
{
|
||||
|
@ -31,16 +38,16 @@ void Image::readBmpHeaderSd(SdFile *_f, bitmapHeader *_h)
|
|||
|
||||
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);
|
||||
_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);
|
||||
uint32_t totalColors = READ32(buf + 46);
|
||||
|
||||
uint8_t paletteRGB[1024];
|
||||
|
||||
|
@ -50,110 +57,33 @@ void Image::readBmpHeader(uint8_t *buf, bitmapHeader *_h)
|
|||
totalColors = (1ULL << _h->color);
|
||||
|
||||
memcpy(paletteRGB, buf + 53, totalColors * 4);
|
||||
memset(pallete, 0, sizeof pallete);
|
||||
memset(palette, 0, sizeof palette);
|
||||
|
||||
for (int i = 0; i < totalColors; ++i)
|
||||
{
|
||||
uint32_t c = read32(paletteRGB + (i << 2));
|
||||
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;
|
||||
|
||||
pallete[i >> 1] |= RGB3BIT(r, g, b) << (i & 1 ? 0 : 4);
|
||||
palette[i >> 1] |= RGB3BIT(r, g, b) << (i & 1 ? 0 : 4);
|
||||
ditherPalette[i] = RGB8BIT(r, g, b);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool Image::legalBmp(bitmapHeader *bmpHeader)
|
||||
{
|
||||
return bmpHeader->signature == 0x4D42 && bmpHeader->compression == 0 &&
|
||||
(bmpHeader->color == 1 || bmpHeader->color == 4 || bmpHeader->color == 8 || bmpHeader->color == 16 ||
|
||||
bmpHeader->color == 24 || bmpHeader->color == 32);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
startWrite();
|
||||
|
||||
for (int j = 0; j < w; ++j)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 1:
|
||||
// Should we ignore palette on 1 bit?
|
||||
writePixel(x + j, y, (invert ^ (pallete[0] < pallete[1])) ^ !!(pixelBuffer[j >> 3] & (1 << (7 - j & 7))));
|
||||
break;
|
||||
// as for 2 bit, literally cannot find an example online or in PS, so skipped
|
||||
case 4: {
|
||||
uint8_t px = pixelBuffer[j >> 1] & (j & 1 ? 0x0F : 0xF0) >> (j & 1 ? 0 : 4);
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - (pallete[px >> 1] & (px & 1 ? 0x0F : 0xF0) >> (px & 1 ? 0 : 4)));
|
||||
else
|
||||
writePixel(x + j, y, pallete[px >> 1] & (px & 1 ? 0x0F : 0xF0) >> (px & 1 ? 0 : 4));
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
uint8_t px = pixelBuffer[j];
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - (pallete[px >> 1] & (px & 1 ? 0x0F : 0xF0) >> (px & 1 ? 0 : 4)));
|
||||
else
|
||||
writePixel(x + j, y, pallete[px >> 1] & (px & 1 ? 0x0F : 0xF0) >> (px & 1 ? 0 : 4));
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
uint16_t px = ((uint16_t)pixelBuffer[(j << 1) | 1] << 8) | pixelBuffer[(j << 1)];
|
||||
|
||||
uint8_t r = (px & 0x7C00) >> 7;
|
||||
uint8_t g = (px & 0x3E0) >> 2;
|
||||
uint8_t b = (px & 0x1F) << 3;
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - RGB3BIT(r, g, b));
|
||||
else
|
||||
writePixel(x + j, y, RGB3BIT(r, g, b));
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
uint8_t r = pixelBuffer[j * 3];
|
||||
uint8_t g = pixelBuffer[j * 3 + 1];
|
||||
uint8_t b = pixelBuffer[j * 3 + 2];
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - RGB3BIT(r, g, b));
|
||||
else
|
||||
writePixel(x + j, y, RGB3BIT(r, g, b));
|
||||
break;
|
||||
}
|
||||
case 32:
|
||||
uint8_t r = pixelBuffer[j * 4];
|
||||
uint8_t g = pixelBuffer[j * 4 + 1];
|
||||
uint8_t b = pixelBuffer[j * 4 + 2];
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - RGB3BIT(r, g, b));
|
||||
else
|
||||
writePixel(x + j, y, RGB3BIT(r, g, b));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
endWrite();
|
||||
}
|
||||
|
||||
bool Image::drawBitmapFromSD(const char *fileName, int x, int y, bool dither, bool invert)
|
||||
bool Image::drawBitmapFromSd(const char *fileName, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
SdFile dat;
|
||||
if (dat.open(fileName, O_RDONLY))
|
||||
return drawBitmapFromSD(&dat, x, y, dither, invert);
|
||||
return drawBitmapFromSd(&dat, x, y, dither, invert);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Image::drawBitmapFromSD(SdFile *p, int x, int y, bool dither, bool invert)
|
||||
bool Image::drawBitmapFromSd(SdFile *p, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
bitmapHeader bmpHeader;
|
||||
|
||||
|
@ -174,11 +104,11 @@ bool Image::drawBitmapFromSD(SdFile *p, int x, int y, bool dither, bool invert)
|
|||
int8_t c = bmpHeader.color;
|
||||
|
||||
p->seekSet(bmpHeader.startRAW);
|
||||
|
||||
if (dither)
|
||||
memset(ditherBuffer, 0, sizeof ditherBuffer);
|
||||
for (int i = 0; i < h; ++i)
|
||||
{
|
||||
int16_t n = rowSize(w, c);
|
||||
|
||||
int16_t n = ROWSIZE(w, c);
|
||||
p->read(pixelBuffer, n);
|
||||
displayBmpLine(x, y + bmpHeader.height - i, &bmpHeader, dither, invert);
|
||||
}
|
||||
|
@ -203,15 +133,125 @@ bool Image::drawBitmapFromWeb(const char *url, int x, int y, bool dither, bool i
|
|||
getDisplayMode() != INKPLATE_3BIT)
|
||||
selectDisplayMode(INKPLATE_3BIT);
|
||||
|
||||
if (dither)
|
||||
memset(ditherBuffer, 0, sizeof ditherBuffer);
|
||||
uint8_t *bufferPtr = buf + bmpHeader.startRAW;
|
||||
for (int i = 0; i < bmpHeader.height; ++i)
|
||||
{
|
||||
memcpy(pixelBuffer, bufferPtr, rowSize(bmpHeader.width, bmpHeader.color));
|
||||
memcpy(pixelBuffer, bufferPtr, ROWSIZE(bmpHeader.width, bmpHeader.color));
|
||||
displayBmpLine(x, y + bmpHeader.height - i, &bmpHeader, dither, invert);
|
||||
bufferPtr += rowSize(bmpHeader.width, bmpHeader.color);
|
||||
bufferPtr += ROWSIZE(bmpHeader.width, bmpHeader.color);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
startWrite();
|
||||
for (int j = 0; j < w; ++j)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 1:
|
||||
writePixel(x + j, y, (invert ^ (palette[0] < palette[1])) ^ !!(pixelBuffer[j >> 3] & (1 << (7 - j & 7))));
|
||||
break;
|
||||
// as for 2 bit, literally cannot find an example online or in PS, so skipped
|
||||
case 4: {
|
||||
uint8_t px = pixelBuffer[j >> 1] & (j & 1 ? 0x0F : 0xF0) >> (j & 1 ? 0 : 4);
|
||||
uint8_t val;
|
||||
|
||||
if (dither)
|
||||
val = ditherGetPixel(px, j, w, 1);
|
||||
else
|
||||
val = palette[px >> 1] & (px & 1 ? 0x0F : 0xF0) >> (px & 1 ? 0 : 4);
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - val);
|
||||
else
|
||||
writePixel(x + j, y, val);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
uint8_t px = pixelBuffer[j];
|
||||
uint8_t val;
|
||||
|
||||
if (dither)
|
||||
val = ditherGetPixel(px, j, w, 1);
|
||||
else
|
||||
{
|
||||
val = palette[px >> 1] & (px & 1 ? 0x0F : 0xF0) >> (px & 1 ? 0 : 4);
|
||||
}
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - val);
|
||||
else
|
||||
writePixel(x + j, y, val);
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
uint16_t px = ((uint16_t)pixelBuffer[(j << 1) | 1] << 8) | pixelBuffer[(j << 1)];
|
||||
|
||||
uint8_t r = (px & 0x7C00) >> 7;
|
||||
uint8_t g = (px & 0x3E0) >> 2;
|
||||
uint8_t b = (px & 0x1F) << 3;
|
||||
|
||||
uint8_t val;
|
||||
|
||||
if (dither)
|
||||
val = ditherGetPixel(RGB8BIT(r, g, b), j, w, 0);
|
||||
else
|
||||
val = RGB3BIT(r, g, b);
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - val);
|
||||
else
|
||||
writePixel(x + j, y, val);
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
uint8_t r = pixelBuffer[j * 3];
|
||||
uint8_t g = pixelBuffer[j * 3 + 1];
|
||||
uint8_t b = pixelBuffer[j * 3 + 2];
|
||||
|
||||
uint8_t val;
|
||||
|
||||
if (dither)
|
||||
val = ditherGetPixel(RGB8BIT(r, g, b), j, w, 0);
|
||||
else
|
||||
val = RGB3BIT(r, g, b);
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - val);
|
||||
else
|
||||
writePixel(x + j, y, val);
|
||||
break;
|
||||
}
|
||||
case 32:
|
||||
uint8_t r = pixelBuffer[j * 4];
|
||||
uint8_t g = pixelBuffer[j * 4 + 1];
|
||||
uint8_t b = pixelBuffer[j * 4 + 2];
|
||||
|
||||
uint8_t val;
|
||||
|
||||
if (dither)
|
||||
val = ditherGetPixel(RGB8BIT(r, g, b), j, w, 0);
|
||||
else
|
||||
val = RGB3BIT(r, g, b);
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - RGB3BIT(r, g, b));
|
||||
else
|
||||
writePixel(x + j, y, RGB3BIT(r, g, b));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ditherSwap(w);
|
||||
endWrite();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#include "Image.h"
|
||||
|
||||
uint8_t Image::ditherGetPixel(uint8_t px, int i, int w, bool paletted)
|
||||
{
|
||||
if (paletted)
|
||||
px = ditherPalette[px];
|
||||
|
||||
uint8_t oldPixel = min((uint16_t)0xFF, (uint16_t)((uint16_t)ditherBuffer[0][i] + px));
|
||||
|
||||
uint8_t newPixel = oldPixel & B11100000;
|
||||
uint8_t quantError = oldPixel - newPixel;
|
||||
|
||||
ditherBuffer[1][i + 0] += (quantError * 5) >> 4;
|
||||
if (i != w - 1)
|
||||
{
|
||||
ditherBuffer[0][i + 1] += (quantError * 7) >> 4;
|
||||
ditherBuffer[1][i + 1] += (quantError * 1) >> 4;
|
||||
}
|
||||
if (i != 0)
|
||||
ditherBuffer[1][i - 1] += (quantError * 3) >> 4;
|
||||
|
||||
return newPixel >> 5;
|
||||
}
|
||||
|
||||
void Image::ditherSwap(int w)
|
||||
{
|
||||
for (int i = 0; i < w; ++i)
|
||||
{
|
||||
ditherBuffer[0][i] = ditherBuffer[1][i];
|
||||
ditherBuffer[1][i] = 0;
|
||||
}
|
||||
}
|
|
@ -16,8 +16,10 @@
|
|||
#define PAD3 2
|
||||
|
||||
#define RGB3BIT(r, g, b) ((54UL * (r) + 183UL * (g) + 19UL * (b)) >> 13)
|
||||
#define read32(c) (uint32_t)(*(c) | (*((c) + 1) << 8) | (*((c) + 2) << 16) | (*((c) + 3) << 24));
|
||||
#define read16(c) (uint16_t)(*(c) | (*((c) + 1) << 8));
|
||||
#define rowSize(w, c) (((int16_t)c * w + 31) >> 5) << 2
|
||||
#define RGB8BIT(r, g, b) ((54UL * (r) + 183UL * (g) + 19UL * (b)) >> 8)
|
||||
|
||||
#define READ32(c) (uint32_t)(*(c) | (*((c) + 1) << 8) | (*((c) + 2) << 16) | (*((c) + 3) << 24));
|
||||
#define READ16(c) (uint16_t)(*(c) | (*((c) + 1) << 8));
|
||||
#define ROWSIZE(w, c) (((int16_t)c * w + 31) >> 5) << 2
|
||||
|
||||
#endif
|
|
@ -6,7 +6,17 @@
|
|||
|
||||
Inkplate display(INKPLATE_1BIT);
|
||||
|
||||
#define DELAYMS 1000
|
||||
|
||||
const char *images[] = {"1bit.bmp", "4bit.bmp", "8bit.bmp", "16bit.bmp", "24bit.bmp", "32bit.bmp"};
|
||||
const char *imageUrls[] = {
|
||||
"https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/1bit.bmp",
|
||||
"https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/4bit.bmp",
|
||||
"https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/8bit.bmp",
|
||||
"https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/16bit.bmp",
|
||||
"https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/24bit.bmp",
|
||||
"https://raw.githubusercontent.com/nitko12/Inkplate-revision/master/test/bitmaps/32bit.bmp",
|
||||
};
|
||||
const bool depth[] = {INKPLATE_1BIT, INKPLATE_3BIT, INKPLATE_3BIT, INKPLATE_3BIT, INKPLATE_3BIT, INKPLATE_3BIT};
|
||||
|
||||
void setup()
|
||||
|
@ -91,7 +101,7 @@ void loop()
|
|||
display.clearDisplay();
|
||||
delay(5000);
|
||||
|
||||
display.drawBitmapFromSD(images[j], 0, 0, dither, invert);
|
||||
display.drawBitmapFromSd(images[j], 0, 0, dither, invert);
|
||||
display.display();
|
||||
display.clearDisplay();
|
||||
delay(5000);
|
||||
|
@ -111,6 +121,7 @@ void loop()
|
|||
display.setCursor(100, 100);
|
||||
display.print("Displaying ");
|
||||
display.print(images[j]);
|
||||
display.print(" from web");
|
||||
if (!dither)
|
||||
display.print(" non");
|
||||
display.print(" dithered and");
|
||||
|
@ -122,7 +133,7 @@ void loop()
|
|||
display.clearDisplay();
|
||||
delay(5000);
|
||||
|
||||
display.drawBitmapFromSD(images[j], 0, 0, dither, invert);
|
||||
display.drawBitmapFromWeb(imageUrls[j], 0, 0, dither, invert);
|
||||
display.display();
|
||||
display.clearDisplay();
|
||||
delay(5000);
|
||||
|
|
|
@ -22,7 +22,17 @@ void loop()
|
|||
|
||||
if (display.sdCardInit())
|
||||
{
|
||||
Serial.println(display.drawBitmapFromSD("8bit.bmp", 0, 0));
|
||||
Serial.println(display.drawBitmapFromSd("Lenna.bmp", 0, 0, 0, 0));
|
||||
}
|
||||
display.display();
|
||||
|
||||
delay(5000);
|
||||
|
||||
if (display.sdCardInit())
|
||||
{
|
||||
int16_t t = millis();
|
||||
Serial.println(display.drawBitmapFromSd("Lenna.bmp", 0, 0, 1, 0));
|
||||
Serial.println(millis() - t);
|
||||
}
|
||||
display.display();
|
||||
|
||||
|
|
Loading…
Reference in New Issue