From 670d38946f5c695b4b42794072d08c0dea820566 Mon Sep 17 00:00:00 2001 From: nitko12 Date: Fri, 7 Aug 2020 09:33:42 +0200 Subject: [PATCH] Faster bmp loading --- Inkplate.cpp | 22 +++-- Inkplate.h | 1 + bmpTestScript/bmpTestScript.ino | 83 +++++++++++++++++++ .../5-Inkplate_SD_BMP_pictures.ino | 77 ++++++++--------- 4 files changed, 139 insertions(+), 44 deletions(-) create mode 100644 bmpTestScript/bmpTestScript.ino diff --git a/Inkplate.cpp b/Inkplate.cpp index e717bff..f126c49 100644 --- a/Inkplate.cpp +++ b/Inkplate.cpp @@ -1012,9 +1012,11 @@ int Inkplate::drawMonochromeBitmapSd(SdFile *f, struct bitmapHeader bmpHeader, i int i, j; for (j = 0; j < h; j++) { + uint8_t *bufferPtr = pixelBuffer; + f->read(pixelBuffer, w * 4); for (i = 0; i < w; i++) { - uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read(); + uint32_t pixelRow = *(bufferPtr++) << 24 | *(bufferPtr++) << 16 | *(bufferPtr++) << 8 | *(bufferPtr++); if (invert) pixelRow = ~pixelRow; for (int n = 0; n < 32; n++) @@ -1048,9 +1050,11 @@ int Inkplate::drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, i int i, j; for (j = 0; j < h; j++) { + uint8_t *bufferPtr = pixelBuffer; + f->read(pixelBuffer, w * 4); for (i = 0; i < w; i++) { - uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read(); + uint32_t pixelRow = *(bufferPtr++) << 24 | *(bufferPtr++) << 16 | *(bufferPtr++) << 8 | *(bufferPtr++); if (invert) pixelRow = ~pixelRow; for (int n = 0; n < 8; n++) @@ -1082,13 +1086,15 @@ int Inkplate::drawGrayscaleBitmap8Sd(SdFile *f, struct bitmapHeader bmpHeader, i int i, j; for (j = 0; j < h; j++) { + uint8_t *bufferPtr = pixelBuffer; + f->read(pixelBuffer, w); for (i = 0; i < w; i++) { uint8_t px = 0; if (invert) - px = 255 - f->read(); + px = 255 - *(bufferPtr++); else - px = f->read(); + px = *(bufferPtr++); drawPixel(i + x, h - 1 - j + y, px >> 5); } if (padding) @@ -1112,6 +1118,8 @@ int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int i, j; for (j = 0; j < h; j++) { + uint8_t *bufferPtr = pixelBuffer; + f->read(pixelBuffer, w * 3); for (i = 0; i < w; i++) { //This is the proper way of converting True Color (24 Bit RGB) bitmap file into grayscale, but it takes waaay too much time (full size picture takes about 17s to decode!) @@ -1119,12 +1127,12 @@ int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, //px = pow(px, 1.5); //display.drawPixel(i + x, h - j + y, (uint8_t)(px*7)); - //So then, we are convertng it to grayscale using good old average and gamma correction (from LUT). With this metod, it is still slow (full size image takes 4 seconds), but much beter than prev mentioned method. uint8_t px = 0; + //So then, we are convertng it to grayscale using good old average and gamma correction (from LUT). With this metod, it is still slow (full size image takes 4 seconds), but much beter than prev mentioned method. if (invert) - px = ((255 - f->read()) * 2126 / 10000) + ((255 - f->read()) * 7152 / 10000) + ((255 - f->read()) * 722 / 10000); + px = ((255 - *(bufferPtr++)) * 2126 / 10000) + ((255 - *(bufferPtr++)) * 7152 / 10000) + ((255 - *(bufferPtr++)) * 722 / 10000); else - px = (f->read() * 2126 / 10000) + (f->read() * 7152 / 10000) + (f->read() * 722 / 10000); + px = (*(bufferPtr++) * 2126 / 10000) + (*(bufferPtr++) * 7152 / 10000) + (*(bufferPtr++) * 722 / 10000); //drawPixel(i + x, h - j + y, gammaLUT[px]); drawPixel(i + x, h - 1 - j + y, px >> 5); //drawPixel(i + x, h - j + y, px/32); diff --git a/Inkplate.h b/Inkplate.h index 8077224..486af07 100644 --- a/Inkplate.h +++ b/Inkplate.h @@ -223,6 +223,7 @@ public: private: uint8_t gammaLUT[256]; + uint8_t pixelBuffer[800 * 3 + 5]; int8_t _temperature; uint8_t _panelOn = 0; uint8_t _rotation = 0; diff --git a/bmpTestScript/bmpTestScript.ino b/bmpTestScript/bmpTestScript.ino new file mode 100644 index 0000000..0e384e0 --- /dev/null +++ b/bmpTestScript/bmpTestScript.ino @@ -0,0 +1,83 @@ +#include "Inkplate.h" +#include "SdFat.h" + +Inkplate display(INKPLATE_3BIT); +SdFile file; + +void setup() { + Serial.begin(115200); + + display.begin(); + display.clearDisplay(); + display.display(); +} + +void loop() { + if (display.sdCardInit()) { + Serial.println("1"); + display.println("SD Card OK! Reading image..."); + display.partialUpdate(); + + if (!display.drawBitmapFromSD("1bit.bmp", 0, 0, 1)) { + display.println("Image open error"); + display.display(); + } + display.display(); + } + + delay(5000); + display.clearDisplay(); + display.clean(); + display.display(); + + if (display.sdCardInit()) { + Serial.println("2"); + display.println("SD Card OK! Reading image..."); + display.partialUpdate(); + + if (!display.drawBitmapFromSD("4bit.bmp", 0, 0)) { + display.println("Image open error"); + display.display(); + } + display.display(); + } + + delay(5000); + display.clearDisplay(); + display.clean(); + display.display(); + + if (display.sdCardInit()) { + Serial.println("3"); + display.println("SD Card OK! Reading image..."); + display.partialUpdate(); + + if (!display.drawBitmapFromSD("8bit.bmp", 0, 0)) { + display.println("Image open error"); + display.display(); + } + display.display(); + } + + delay(5000); + display.clearDisplay(); + display.clean(); + display.display(); + + if (display.sdCardInit()) { + Serial.println("4"); + display.println("SD Card OK! Reading image..."); + display.partialUpdate(); + + if (!display.drawBitmapFromSD("24bit.bmp", 0, 0)) { + display.println("Image open error"); + display.display(); + } + display.display(); + } + + delay(5000); + display.clearDisplay(); + display.clean(); + display.display(); +} \ No newline at end of file diff --git a/examples/2. Advanced Inkplate Features/5-Inkplate_SD_BMP_pictures/5-Inkplate_SD_BMP_pictures.ino b/examples/2. Advanced Inkplate Features/5-Inkplate_SD_BMP_pictures/5-Inkplate_SD_BMP_pictures.ino index d83f743..07108e9 100644 --- a/examples/2. Advanced Inkplate Features/5-Inkplate_SD_BMP_pictures/5-Inkplate_SD_BMP_pictures.ino +++ b/examples/2. Advanced Inkplate Features/5-Inkplate_SD_BMP_pictures/5-Inkplate_SD_BMP_pictures.ino @@ -1,19 +1,19 @@ /* 5_Inkplate_SD_BMP example for e-radionica Inkplate6 - For this example you will need a micro USB cable, Inkplate6 and a SD card loaded with + For this example you will need a micro USB cable, Inkplate6 and a SD card loaded with image1.bmp and image2.bmp file that can be found inside folder of this example. Select "Inkplate 6(ESP32)" from Tools -> Board menu. - Don't have "Inkplate 6(ESP32)" option? Follow our tutorial and add it: + 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), 4 bit, 8 bit and + + You can open .bmp files that have color depth of 1 bit (monochrome bitmap), 4 bit, 8 bit and 24 bit AND have resoluton smaller than 800x600 or otherwise it won't fit on screen. Format your SD card in standard FAT fileformat. - This example will show you how you can read .bmp files (pictures) from SD card and + This example will show you how you can read .bmp files (pictures) from SD card and display that image on e-paper display. Want to learn more about Inkplate? Visit www.inkplate.io @@ -27,42 +27,45 @@ Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and a SdFile file; //Create SdFile object used for accessing files on SD card void setup() { - 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 + Serial.begin(115200); - //Init SD card. Display if SD card is init propery or not. - if (display.sdCardInit()) { - display.println("SD Card OK! Reading image..."); - display.partialUpdate(); + 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 - //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)) { - //If is something failed (wrong filename or wrong bitmap format), write error message on the screen. - //REMEMBER! You can only use Windows Bitmap file with color depth of 1, 4, 8 or 24 bits with no compression! - display.println("Image open error"); - display.display(); + //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)) { + //If is something failed (wrong filename or wrong bitmap format), write error message on the screen. + //REMEMBER! You can only use Windows Bitmap file with color depth of 1, 4, 8 or 24 bits with no compression! + display.println("Image open error"); + display.display(); + } + display.display(); } - display.display(); - } 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); - } - 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); - display.display(); - } - + 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); + } + 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); + display.display(); + } + } void loop() { - //Nothing... + //Nothing... }