diff --git a/include/image.h b/include/image.h new file mode 100644 index 0000000..9186f8b --- /dev/null +++ b/include/image.h @@ -0,0 +1,13 @@ +#ifndef IMAGE_H +#define IMAGE_H + +#include + +#include "imageWBMP.h" +#include "imagePNG.h" + +void ImageNew(int x, int y, int w, int h, bool dithering); +void ImageWriteBuffer(uint8_t buff[], size_t c); +void ImageFlushBuffer(); + +#endif \ No newline at end of file diff --git a/src/image.cpp b/src/image.cpp new file mode 100644 index 0000000..7951a46 --- /dev/null +++ b/src/image.cpp @@ -0,0 +1,91 @@ +#include "image.h" + +typedef struct +{ + size_t format; + int x; + int y; + int w; + int h; + bool dithering; +} ImageProcess; +ImageProcess Image; + +void ImageNew(int x, int y, int w, int h, bool dithering) +{ + Image.x = x; + Image.y = y; + Image.w = w; + Image.h = h; + Image.dithering = dithering; +} + +void ImageWriteBuffer(uint8_t buff[], size_t c) +{ + // initial detect format + if (Image.format == 0) + { + if (memcmp(buff, ImageHeaderWBMP, sizeof(ImageHeaderWBMP) - 1) == 0) + { + Serial.println(" image format: WBMP"); + Image.format = 2; + + wbmpOpenFramebuffer(); + } + else if (memcmp(buff, ImageHeaderPNG, sizeof(ImageHeaderPNG) - 1) == 0) + { + Serial.println(" image format: PNG"); + Image.format = 3; + + pngOpenFramebuffer(); + } + else + { + Image.format = 1; + Serial.println(" unkown image format. first header are:"); + Serial.println(buff[0]); + Serial.println(buff[1]); + Serial.println(buff[2]); + Serial.println(buff[3]); + Serial.println(buff[4]); + Serial.println(buff[5]); + } + } + + // write display frame + switch (Image.format) + { + // WBMP + case 2: + wbmpWriteFramebuffer(0, buff, c); + break; + // PNG + case 3: + pngWriteFramebuffer(0, buff, c); + break; + } +} + +void ImageFlushBuffer() +{ + // update display + switch (Image.format) + { + // WBMP + case 2: + wbmpFlushFramebuffer(); + break; + // PNG + case 3: + pngFlushFramebuffer(); + break; + } + + // clear settings + Image.format = 0; + Image.x = 0; + Image.y = 0; + Image.w = 0; + Image.h = 0; + Image.dithering = false; +} \ No newline at end of file diff --git a/src/imagePNG.cpp b/src/imagePNG.cpp index 24021a6..9f54dd7 100644 --- a/src/imagePNG.cpp +++ b/src/imagePNG.cpp @@ -1,11 +1,17 @@ #include #include "imagePNG.h" #include "pngle.h" -//#include "SPIFFS.h" #include "display.h" pngle_t *pngle; +// TODO use dynamic display width +static constexpr int MAX_WIDTH = 640; +static int16_t curRowDelta[MAX_WIDTH + 1]; +static int16_t nextRowDelta[MAX_WIDTH + 1]; + +bool dithering = true; + void on_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]); void setupImagePNG() @@ -19,16 +25,28 @@ void pngOpenFramebuffer() { displayOpen(); + if (pngle) + { + pngle_destroy(pngle); + } + pngle = pngle_new(); pngle_set_draw_callback(pngle, on_draw); } void pngWriteFramebuffer(int offset, uint8_t bitmap[], int c) { - int fed = pngle_feed(pngle, bitmap, c); - if (fed < 0) + if (pngle) { - Serial.println(pngle_error(pngle)); + int fed = pngle_feed(pngle, bitmap, c); + if (fed < 0) + { + Serial.println(pngle_error(pngle)); + } + } + else + { + Serial.println("forgot pngle_new() ?"); } } @@ -38,63 +56,52 @@ void pngFlushFramebuffer() displayFlush(); } -/* -void setupImagePNG__demo() +void on_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]) { - SPIFFS.begin(); - displayOpen(); + uint8_t r = rgba[0]; // 0 - 255 + uint8_t g = rgba[1]; // 0 - 255 + uint8_t b = rgba[2]; // 0 - 255 - pngle_t *pngle = pngle_new(); - pngle_set_draw_callback(pngle, on_draw); + int16_t gray = round(r * 0.3 + g * 0.59 + b * 0.11); + int16_t blackOrWhite; - File file = SPIFFS.open("/blackPNG.png", "r"); - if (!file) + // Add errors to color if there are + if (dithering) { - Serial.println(" file not found"); + gray += curRowDelta[x]; } - // get filesize - long size = file.size(); - - // read contents of the file into the vector - char *buffer = (char *)malloc((unsigned long)size); - if (!buffer) + if (gray <= 127) { - file.close(); - Serial.println(" allow failedd"); + blackOrWhite = 0; + } + else + { + blackOrWhite = 255; } - file.readBytes(buffer, (size_t)size); - file.close(); - - Serial.println(" read png"); - int ret = pngle_feed(pngle, buffer, size); - - //Serial.println(" return: " + ret); - //Serial.println(" width: " + pngle_get_width(pngle)); - //Serial.println(" height: " + pngle_get_height(pngle)); - Serial.println(" read png done"); - pngle_destroy(pngle); + if (dithering) + { + int16_t oldPixel = gray; + int16_t newPixel = blackOrWhite; - displayFlush(); -} -*/ + int err = oldPixel - newPixel; -void on_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]) -{ - uint8_t r = rgba[0]; // 0 - 255 - //uint8_t g = rgba[1]; // 0 - 255 - //uint8_t b = rgba[2]; // 0 - 255 - uint8_t a = rgba[3]; // 0: fully transparent, 255: fully opaque - - if (a) - { - // 640 x 384 - if (true) // x == 0 + if (x > 0) { - //printf("put pixel at (%d, %d) with color #%02x%02x%02x\n", x, y, r, g, b); + nextRowDelta[x - 1] += err * 3 / 16; } + nextRowDelta[x] += err * 5 / 16; + nextRowDelta[x + 1] += err * 1 / 16; + curRowDelta[x + 1] += err * 7 / 16; - displayWritePixel(x, y, r); + if (x == 0 && y > 0) + { + // new line + memcpy(curRowDelta, nextRowDelta, sizeof(&curRowDelta)); + memset(nextRowDelta, 0, sizeof(&nextRowDelta)); + } } + + displayWritePixel(x, y, blackOrWhite); } \ No newline at end of file