From 5e96d021204679ab819b51aad067df86d9e94ebf Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Sun, 28 Feb 2016 21:08:45 +0100 Subject: [PATCH] Transparent bitmaps supported/displayed in SD browser. BitmapBuffer: fixed wrong free() when using external data buffer. --- radio/src/gui/horus/bitmapbuffer.cpp | 42 ++++++++++++------- radio/src/gui/horus/bitmapbuffer.h | 13 ++++-- radio/src/gui/horus/colors.h | 2 + .../src/gui/horus/menu_general_sdmanager.cpp | 4 +- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/radio/src/gui/horus/bitmapbuffer.cpp b/radio/src/gui/horus/bitmapbuffer.cpp index 83e2138e9..3f15b46b4 100644 --- a/radio/src/gui/horus/bitmapbuffer.cpp +++ b/radio/src/gui/horus/bitmapbuffer.cpp @@ -461,7 +461,7 @@ const stbi_io_callbacks stbCallbacks = { stbc_eof }; -BitmapBuffer * BitmapBuffer::load(const char * filename) +BitmapBuffer * BitmapBuffer::load(const char * filename, bool transparent) { FIL imgFile; @@ -471,33 +471,47 @@ BitmapBuffer * BitmapBuffer::load(const char * filename) } int w, h, n; - unsigned char *data = stbi_load_from_callbacks(&stbCallbacks, &imgFile, &w, &h, &n, 3); + unsigned char *img = stbi_load_from_callbacks(&stbCallbacks, &imgFile, &w, &h, &n, transparent ? 4 : 3); f_close(&imgFile); - if (!data) { + if (!img) { return NULL; } - //convert to 565 fromat + //convert to RGB565 or ARGB4444 fromat // todo use dma2d for conversion from 888 to 565 - unsigned char * p = data; + unsigned char * p = img; BitmapBuffer * bmp = new BitmapBuffer(w, h); uint16_t * dest = bmp->data; if (bmp == NULL) { TRACE("load_stb() malloc failed"); - stbi_image_free(data); + stbi_image_free(img); return NULL; } - for(int row = 0; row < h; ++row) { - unsigned char *l = p; - for(int col = 0; col < w; ++col) { - *dest = RGB(l[0], l[1], l[2]); - ++dest; - l += 3; + if (transparent) { + for(int row = 0; row < h; ++row) { + unsigned char *l = p; + for(int col = 0; col < w; ++col) { + *dest = ARGB(l[3], l[0], l[1], l[2]); + ++dest; + l += 4; + } + p += 4 * w; } - p += 3 * w; } - stbi_image_free(data); + else { + for(int row = 0; row < h; ++row) { + unsigned char *l = p; + for(int col = 0; col < w; ++col) { + *dest = RGB(l[0], l[1], l[2]); + ++dest; + l += 3; + } + p += 3 * w; + } + } + + stbi_image_free(img); return bmp; } diff --git a/radio/src/gui/horus/bitmapbuffer.h b/radio/src/gui/horus/bitmapbuffer.h index 54c8e5291..931630f5f 100644 --- a/radio/src/gui/horus/bitmapbuffer.h +++ b/radio/src/gui/horus/bitmapbuffer.h @@ -64,22 +64,27 @@ typedef BitmapBufferBase Bitmap; class BitmapBuffer: public BitmapBufferBase { + private: + bool dataAllocated; + public: BitmapBuffer(int width, int height): - BitmapBufferBase(width, height, NULL) + BitmapBufferBase(width, height, NULL), + dataAllocated(true) { data = (uint16_t *)malloc(width*height*sizeof(uint16_t)); } BitmapBuffer(int width, int height, uint16_t * data): - BitmapBufferBase(width, height, data) + BitmapBufferBase(width, height, data), + dataAllocated(false) { } ~BitmapBuffer() { - free(data); + if (dataAllocated && data) free(data); } inline void clear() @@ -132,7 +137,7 @@ class BitmapBuffer: public BitmapBufferBase void drawBitmapPatternPie(coord_t x0, coord_t y0, const uint8_t * img, LcdFlags flags, int startAngle, int endAngle); - static BitmapBuffer * load(const char * filename); + static BitmapBuffer * load(const char * filename, bool transparent = false); void drawBitmapPattern(coord_t x, coord_t y, const uint8_t * bmp, LcdFlags flags, coord_t offset=0, coord_t width=0); diff --git a/radio/src/gui/horus/colors.h b/radio/src/gui/horus/colors.h index c64f89188..8ea49b6bc 100644 --- a/radio/src/gui/horus/colors.h +++ b/radio/src/gui/horus/colors.h @@ -25,9 +25,11 @@ #undef OPAQUE #undef RGB +#define TO4BITS(x) ((x) >> 4) #define TO5BITS(x) ((x) >> 3) #define TO6BITS(x) ((x) >> 2) #define RGB(r, g, b) ((TO5BITS(r) << 11) + (TO6BITS(g) << 5) + (TO5BITS(b) << 0)) +#define ARGB(a, r, g, b) ((TO4BITS(a) << 12) + (TO4BITS(r) << 8) + (TO4BITS(g) << 4) + (TO4BITS(b) << 0)) #define WHITE RGB(0xFF, 0xFF, 0xFF) #define BLACK RGB(0, 0, 0) #define YELLOW RGB(0xF0, 0xD0, 0x10) diff --git a/radio/src/gui/horus/menu_general_sdmanager.cpp b/radio/src/gui/horus/menu_general_sdmanager.cpp index d07b872f0..bfe529474 100644 --- a/radio/src/gui/horus/menu_general_sdmanager.cpp +++ b/radio/src/gui/horus/menu_general_sdmanager.cpp @@ -366,11 +366,11 @@ bool menuGeneralSdManager(evt_t _event) if (currentBitmapIndex != menuVerticalPosition) { currentBitmapIndex = menuVerticalPosition; delete currentBitmap; - currentBitmap = BitmapBuffer::load(reusableBuffer.sdmanager.lines[index]); + currentBitmap = BitmapBuffer::load(reusableBuffer.sdmanager.lines[index], true); // TODO scale in case of a too large bitmap } if (currentBitmap) { - lcd->drawBitmap(LCD_W / 2, LCD_H / 2, currentBitmap); + lcd->drawAlphaBitmap(LCD_W / 2, LCD_H / 2, currentBitmap); } }