Web and SD card dithering added.
This commit is contained in:
parent
88419ad50b
commit
95bc91e1da
108
Inkplate.cpp
108
Inkplate.cpp
|
@ -456,7 +456,7 @@ int Inkplate::drawBitmapFromSD(char *fileName, int x, int y, bool dither, bool i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inkplate::drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool invert)
|
int Inkplate::drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool dither, bool invert)
|
||||||
{
|
{
|
||||||
struct bitmapHeader bmpHeader;
|
struct bitmapHeader bmpHeader;
|
||||||
readBmpHeaderWeb(s, &bmpHeader);
|
readBmpHeaderWeb(s, &bmpHeader);
|
||||||
|
@ -478,14 +478,14 @@ int Inkplate::drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool inver
|
||||||
if (bmpHeader.color == 4)
|
if (bmpHeader.color == 4)
|
||||||
drawGrayscaleBitmap4Web(s, bmpHeader, x, y, len, invert);
|
drawGrayscaleBitmap4Web(s, bmpHeader, x, y, len, invert);
|
||||||
if (bmpHeader.color == 8)
|
if (bmpHeader.color == 8)
|
||||||
drawGrayscaleBitmap8Web(s, bmpHeader, x, y, len, invert);
|
drawGrayscaleBitmap8Web(s, bmpHeader, x, y, len, dither, invert);
|
||||||
if (bmpHeader.color == 24)
|
if (bmpHeader.color == 24)
|
||||||
drawGrayscaleBitmap24Web(s, bmpHeader, x, y, len, invert);
|
drawGrayscaleBitmap24Web(s, bmpHeader, x, y, len, dither, invert);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inkplate::drawBitmapFromWeb(char *url, int x, int y, bool invert)
|
int Inkplate::drawBitmapFromWeb(char *url, int x, int y, bool dither, bool invert)
|
||||||
{
|
{
|
||||||
if (WiFi.status() != WL_CONNECTED)
|
if (WiFi.status() != WL_CONNECTED)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -506,7 +506,7 @@ int Inkplate::drawBitmapFromWeb(char *url, int x, int y, bool invert)
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
{
|
||||||
WiFiClient *dat = http.getStreamPtr();
|
WiFiClient *dat = http.getStreamPtr();
|
||||||
ret = drawBitmapFromWeb(dat, x, y, len, invert);
|
ret = drawBitmapFromWeb(dat, x, y, len, dither, invert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1405,7 +1405,7 @@ int Inkplate::drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHead
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert)
|
int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool dither, bool invert)
|
||||||
{
|
{
|
||||||
int w = bmpHeader.width;
|
int w = bmpHeader.width;
|
||||||
int h = bmpHeader.height;
|
int h = bmpHeader.height;
|
||||||
|
@ -1416,7 +1416,7 @@ int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHead
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int pnt = 0;
|
uint32_t pnt = 0;
|
||||||
while (pnt < total)
|
while (pnt < total)
|
||||||
{
|
{
|
||||||
int toread = s->available();
|
int toread = s->available();
|
||||||
|
@ -1428,23 +1428,51 @@ int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHead
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int i, j, k = bmpHeader.startRAW - 34;
|
uint8_t *bufferPtr;
|
||||||
|
uint8_t *f_pointer = buf + (bmpHeader.startRAW - 34);
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (dither) {
|
||||||
|
bufferPtr = pixelBuffer;
|
||||||
|
for (i = 0; i < w; i++)
|
||||||
|
pixelBuffer[i] = *(f_pointer++);
|
||||||
|
|
||||||
|
ditherStart(buf, bufferPtr, w, invert, 8);
|
||||||
|
}
|
||||||
|
|
||||||
for (j = 0; j < h; j++)
|
for (j = 0; j < h; j++)
|
||||||
{
|
{
|
||||||
|
bufferPtr = pixelBuffer;
|
||||||
|
for (i = 0; i < w; i++)
|
||||||
|
pixelBuffer[i] = *(f_pointer++);
|
||||||
|
|
||||||
|
if (dither && j != h - 1) {
|
||||||
|
ditherLoadNextLine(buf, bufferPtr, w, invert, 8);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < w; i++)
|
for (i = 0; i < w; i++)
|
||||||
{
|
{
|
||||||
uint8_t px = 0;
|
if (dither)
|
||||||
if (invert)
|
drawPixel(i + x, h - 1 - j + y, ditherGetPixel(i, j, w, h) >> 5);
|
||||||
px = 255 - buf[k++];
|
else {
|
||||||
else
|
uint8_t px = 0;
|
||||||
px = buf[k++];
|
if (invert)
|
||||||
drawPixel(i + x, h - 1 - j + y, px >> 5);
|
px = 255 - *(bufferPtr++);
|
||||||
|
else
|
||||||
|
px = *(bufferPtr++);
|
||||||
|
drawPixel(i + x, h - 1 - j + y, px >> 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dither)
|
||||||
|
ditherSwap(w);
|
||||||
|
|
||||||
if (padding)
|
if (padding)
|
||||||
{
|
{
|
||||||
for (int p = 0; p < 4 - padding; p++)
|
for (int p = 0; p < 4 - padding; p++)
|
||||||
{
|
{
|
||||||
k++;
|
++bufferPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1454,7 +1482,7 @@ int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHead
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert)
|
int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool dither, bool invert)
|
||||||
{
|
{
|
||||||
int w = bmpHeader.width;
|
int w = bmpHeader.width;
|
||||||
int h = bmpHeader.height;
|
int h = bmpHeader.height;
|
||||||
|
@ -1477,9 +1505,29 @@ int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHea
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int i, j, k = bmpHeader.startRAW - 34;
|
uint8_t *bufferPtr;
|
||||||
|
uint8_t *f_pointer = buf + (bmpHeader.startRAW - 34);
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (dither) {
|
||||||
|
bufferPtr = pixelBuffer;
|
||||||
|
for (i = 0; i < w; i++)
|
||||||
|
pixelBuffer[i] = *(f_pointer++);
|
||||||
|
|
||||||
|
ditherStart(buf, bufferPtr, w, invert, 8);
|
||||||
|
}
|
||||||
|
|
||||||
for (j = 0; j < h; j++)
|
for (j = 0; j < h; j++)
|
||||||
{
|
{
|
||||||
|
bufferPtr = pixelBuffer;
|
||||||
|
for (i = 0; i < w; i++)
|
||||||
|
pixelBuffer[i] = *(f_pointer++);
|
||||||
|
|
||||||
|
if (dither && j != h - 1) {
|
||||||
|
ditherLoadNextLine(buf, bufferPtr, w, invert, 8);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < w; i++)
|
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!)
|
//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!)
|
||||||
|
@ -1488,20 +1536,28 @@ int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHea
|
||||||
//display.drawPixel(i + x, h - j + y, (uint8_t)(px*7));
|
//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.
|
//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;
|
if (dither)
|
||||||
if (invert)
|
drawPixel(i + x, h - 1 - j + y, ditherGetPixel(i, j, w, h) >> 5);
|
||||||
px = ((255 - buf[k++]) * 2126 / 10000) + ((255 - buf[k++]) * 7152 / 10000) + ((255 - buf[k++]) * 722 / 10000);
|
else {
|
||||||
else
|
uint8_t px = 0;
|
||||||
px = (buf[k++] * 2126 / 10000) + (buf[k++] * 7152 / 10000) + (buf[k++] * 722 / 10000);
|
if (invert)
|
||||||
//drawPixel(i + x, h - j + y, gammaLUT[px]);
|
px = ((255 - *(bufferPtr++)) * 2126 / 10000) + ((255 - *(bufferPtr++)) * 7152 / 10000) + ((255 - *(bufferPtr++)) * 722 / 10000);
|
||||||
drawPixel(i + x, h - 1 - j + y, px >> 5);
|
else
|
||||||
//drawPixel(i + x, h - j + y, px/32);
|
px = (*(bufferPtr++) * 2126 / 10000) + (*(bufferPtr++) * 7152 / 10000) + (*(bufferPtr++) * 722 / 10000);
|
||||||
|
//drawPixel(i + x, h - j + y, gammaLUT[px]);
|
||||||
|
drawPixel(i + x, h - 1 - j + y, px >> 5);
|
||||||
|
//drawPixel(i + x, h - j + y, px/32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dither)
|
||||||
|
ditherSwap(w);
|
||||||
|
|
||||||
if (padding)
|
if (padding)
|
||||||
{
|
{
|
||||||
for (int p = 0; p < padding; p++)
|
for (int p = 0; p < padding; p++)
|
||||||
{
|
{
|
||||||
k++;
|
++bufferPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,8 +201,8 @@ public:
|
||||||
uint8_t getDisplayMode();
|
uint8_t getDisplayMode();
|
||||||
int drawBitmapFromSD(SdFile *p, int x, int y, bool dither = false, bool invert = false);
|
int drawBitmapFromSD(SdFile *p, int x, int y, bool dither = false, bool invert = false);
|
||||||
int drawBitmapFromSD(char *fileName, int x, int y, bool dither = false, bool invert = false);
|
int drawBitmapFromSD(char *fileName, int x, int y, bool dither = false, bool invert = false);
|
||||||
int drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool invert = false);
|
int drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool dither = false, bool invert = false);
|
||||||
int drawBitmapFromWeb(char *url, int x, int y, bool invert = false);
|
int drawBitmapFromWeb(char *url, int x, int y, bool dither = false, bool invert = false);
|
||||||
void drawThickLine(int x1, int y1, int x2, int y2, int color, float thickness);
|
void 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);
|
void drawGradientLine(int x1, int y1, int x2, int y2, int color1, int color2, float thickness = -1);
|
||||||
int sdCardInit();
|
int sdCardInit();
|
||||||
|
@ -250,8 +250,8 @@ private:
|
||||||
int drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool dither, bool invert);
|
int drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool dither, bool invert);
|
||||||
int drawMonochromeBitmapWeb(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
int drawMonochromeBitmapWeb(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
||||||
int drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
int drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
||||||
int drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
int drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool dither, bool invert);
|
||||||
int drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
|
int drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool dither, bool invert);
|
||||||
void precalculateGamma(uint8_t *c, float gamma);
|
void precalculateGamma(uint8_t *c, float gamma);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
10_Inkplate_Download_And_Show example for e-radionica Inkplate6
|
10_Inkplate_Download_And_Show example for e-radionica Inkplate6
|
||||||
For this example you will need a micro USB cable, Inkplate6, and an available WiFi connection.
|
For this example you will need a micro USB cable, Inkplate6, and an available WiFi connection.
|
||||||
Select "Inkplate 6(ESP32)" from Tools -> Board menu.
|
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/
|
https://e-radionica.com/en/blog/add-inkplate-6-to-arduino-ide/
|
||||||
|
|
||||||
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.
|
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 and
|
This example will show you how you can download a .bmp file (picture) from the web and
|
||||||
display that image on e-paper display.
|
display that image on e-paper display.
|
||||||
|
|
||||||
Want to learn more about Inkplate? Visit www.inkplate.io
|
Want to learn more about Inkplate? Visit www.inkplate.io
|
||||||
|
@ -21,81 +21,82 @@
|
||||||
#include "WiFi.h" //Include library for WiFi
|
#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)
|
Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome)
|
||||||
|
|
||||||
const char* ssid = "YourWiFiSSID"; //Your WiFi SSID
|
const char* ssid = "e-radionica.com"; //Your WiFi SSID
|
||||||
const char* password = "YourPass"; //Your WiFi password
|
const char* password = "croduino"; //Your WiFi password
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
display.begin(); //Init Inkplate library (you should call this function ONLY ONCE)
|
display.begin(); //Init Inkplate library (you should call this function ONLY ONCE)
|
||||||
display.clearDisplay(); //Clear frame buffer of display
|
display.clearDisplay(); //Clear frame buffer of display
|
||||||
display.display(); //Put clear image on display
|
display.display(); //Put clear image on display
|
||||||
|
|
||||||
display.print("Connecting to WiFi...");
|
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.partialUpdate();
|
||||||
}
|
|
||||||
display.println("\nWiFi OK! Downloading...");
|
|
||||||
display.partialUpdate();
|
|
||||||
|
|
||||||
//Draw the first image from web.
|
//Connect to the WiFi network.
|
||||||
//Monochromatic bitmap with 1 bit depth. Images like this load quickest.
|
WiFi.mode(WIFI_MODE_STA);
|
||||||
//NOTE: Both drawBitmapFromWeb methods allow for an optional fourth "invert" parameter. Setting this parameter to true
|
WiFi.begin(ssid, password);
|
||||||
//will flip all colors on the image, making black white and white black. This may be necessary when exporting bitmaps from
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
//certain softwares.
|
delay(500);
|
||||||
//Photo taken by: Roberto Fernandez
|
display.print(".");
|
||||||
if(!display.drawBitmapFromWeb("https://varipass.org/neowise_mono.bmp", 0, 0, true)) {
|
display.partialUpdate();
|
||||||
//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("\nWiFi OK! Downloading...");
|
||||||
display.println("Image open error");
|
display.partialUpdate();
|
||||||
display.display();
|
|
||||||
}
|
|
||||||
display.display();
|
|
||||||
|
|
||||||
//Draw the second image from web, this time using a HTTPClient to fetch the response manually.
|
//Draw the first image from web.
|
||||||
//Full color 24 bit images are large and take a long time to load, will take around 20 secs.
|
//Monochromatic bitmap with 1 bit depth. Images like this load quickest.
|
||||||
HTTPClient http;
|
//NOTE: Both drawBitmapFromWeb methods allow for an optional fifth "invert" parameter. Setting this parameter to true
|
||||||
//Set parameters to speed up the download process.
|
//will flip all colors on the image, making black white and white black. This may be necessary when exporting bitmaps from
|
||||||
http.getStream().setNoDelay(true);
|
//certain softwares.
|
||||||
http.getStream().setTimeout(1);
|
//Forth parameter will dither the image.
|
||||||
|
//Photo taken by: Roberto Fernandez
|
||||||
//Photo taken by: Roberto Fernandez
|
if (!display.drawBitmapFromWeb("https://varipass.org/neowise_mono.bmp", 0, 0, false, true)) {
|
||||||
http.begin("https://varipass.org/neowise.bmp");
|
|
||||||
|
|
||||||
//Check response code.
|
|
||||||
int httpCode = http.GET();
|
|
||||||
if (httpCode == 200) {
|
|
||||||
//Get the response length and make sure it is not 0.
|
|
||||||
int32_t len = http.getSize();
|
|
||||||
if (len > 0) {
|
|
||||||
if(!display.drawBitmapFromWeb(http.getStreamPtr(), 0, 0, len)) {
|
|
||||||
//If is something failed (wrong filename or wrong bitmap format), write error message on the screen.
|
//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!
|
//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.println("Image open error");
|
||||||
display.display();
|
display.display();
|
||||||
}
|
}
|
||||||
display.display();
|
display.display();
|
||||||
|
|
||||||
|
//Draw the second image from web, this time using a HTTPClient to fetch the response manually.
|
||||||
|
//Full color 24 bit images are large and take a long time to load, will take around 20 secs.
|
||||||
|
HTTPClient http;
|
||||||
|
//Set parameters to speed up the download process.
|
||||||
|
http.getStream().setNoDelay(true);
|
||||||
|
http.getStream().setTimeout(1);
|
||||||
|
|
||||||
|
//Photo taken by: Roberto Fernandez
|
||||||
|
http.begin("https://varipass.org/neowise.bmp");
|
||||||
|
|
||||||
|
//Check response code.
|
||||||
|
int httpCode = http.GET();
|
||||||
|
if (httpCode == 200) {
|
||||||
|
//Get the response length and make sure it is not 0.
|
||||||
|
int32_t len = http.getSize();
|
||||||
|
if (len > 0) {
|
||||||
|
if (!display.drawBitmapFromWeb(http.getStreamPtr(), 0, 0, len)) {
|
||||||
|
//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();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
display.println("Invalid response length");
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
display.println("Invalid response length");
|
display.println("HTTP error");
|
||||||
display.display();
|
display.display();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
display.println("HTTP error");
|
|
||||||
display.display();
|
|
||||||
}
|
|
||||||
|
|
||||||
http.end();
|
|
||||||
|
|
||||||
WiFi.mode(WIFI_OFF);
|
http.end();
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
//Nothing...
|
//Nothing...
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue