diff options
-rw-r--r-- | apps/recorder/backdrop.c | 3 | ||||
-rw-r--r-- | apps/recorder/bmp.c | 70 | ||||
-rw-r--r-- | firmware/export/lcd.h | 1 |
3 files changed, 56 insertions, 18 deletions
diff --git a/apps/recorder/backdrop.c b/apps/recorder/backdrop.c index d230a6ec5a..374dba9f4b 100644 --- a/apps/recorder/backdrop.c +++ b/apps/recorder/backdrop.c | |||
@@ -36,7 +36,8 @@ bool load_backdrop(char* filename, fb_data* backdrop_buffer) | |||
36 | 36 | ||
37 | /* load the image */ | 37 | /* load the image */ |
38 | bm.data=(char*)backdrop_buffer; | 38 | bm.data=(char*)backdrop_buffer; |
39 | ret = read_bmp_file(filename, &bm, sizeof(main_backdrop), FORMAT_NATIVE); | 39 | ret = read_bmp_file(filename, &bm, sizeof(main_backdrop), |
40 | FORMAT_NATIVE | FORMAT_DITHER); | ||
40 | 41 | ||
41 | if ((ret > 0) && (bm.width == LCD_WIDTH) && (bm.height == LCD_HEIGHT)) | 42 | if ((ret > 0) && (bm.width == LCD_WIDTH) && (bm.height == LCD_HEIGHT)) |
42 | { | 43 | { |
diff --git a/apps/recorder/bmp.c b/apps/recorder/bmp.c index 9d0968a03b..b490158b2c 100644 --- a/apps/recorder/bmp.c +++ b/apps/recorder/bmp.c | |||
@@ -94,6 +94,39 @@ inline int getpix(int px, unsigned char *bmpbuf) { | |||
94 | return (bmpbuf[a] & (1 << b)) != 0; | 94 | return (bmpbuf[a] & (1 << b)) != 0; |
95 | } | 95 | } |
96 | 96 | ||
97 | #if LCD_DEPTH == 16 | ||
98 | /* Cheapo 24 -> 16 bit dither */ | ||
99 | #if LCD_PIXELFORMAT == RGB565SWAPPED | ||
100 | #define RGBSWAPPED(rgb) swap16(rgb) | ||
101 | #else | ||
102 | #define RGBSWAPPED(rgb) rgb | ||
103 | #endif | ||
104 | static unsigned short dither_24_to_16(struct rgb_quad rgb, int row, int col) | ||
105 | { | ||
106 | static const unsigned char dith[2][16] = { | ||
107 | { /* 5 bit */ | ||
108 | 0,6,1,7, | ||
109 | 4,2,5,3, | ||
110 | 1,7,0,6, | ||
111 | 5,3,4,2 | ||
112 | }, | ||
113 | { /* 6 bit */ | ||
114 | 0,3,0,3, | ||
115 | 2,1,2,1, | ||
116 | 0,3,0,3, | ||
117 | 2,1,2,1 | ||
118 | } | ||
119 | }; | ||
120 | |||
121 | const int elm = (row & 3) + ((col & 3) << 2); | ||
122 | short b = 31*((unsigned short)rgb.blue + dith[0][elm]) >> 8; | ||
123 | short g = 63*((unsigned short)rgb.green + dith[1][elm]) >> 8; | ||
124 | short r = 31*((unsigned short)rgb.red + dith[0][elm]) >> 8; | ||
125 | |||
126 | return RGBSWAPPED(b | (g << 5) | (r << 11)); | ||
127 | } | ||
128 | #endif /* LCD_DEPTH == 16 */ | ||
129 | |||
97 | 130 | ||
98 | /****************************************************************************** | 131 | /****************************************************************************** |
99 | * read_bmp_file() | 132 | * read_bmp_file() |
@@ -115,21 +148,25 @@ int read_bmp_file(char* filename, | |||
115 | int depth; | 148 | int depth; |
116 | int totalsize; | 149 | int totalsize; |
117 | char *bitmap = bm->data; | 150 | char *bitmap = bm->data; |
118 | |||
119 | unsigned char bmpbuf[LCD_WIDTH*sizeof(struct rgb_quad)]; /* Buffer for one line */ | 151 | unsigned char bmpbuf[LCD_WIDTH*sizeof(struct rgb_quad)]; /* Buffer for one line */ |
120 | 152 | #if LCD_DEPTH != 1 | |
121 | #if LCD_DEPTH == 1 | 153 | bool transparent = false; |
122 | format = FORMAT_MONO; | 154 | #if LCD_DEPTH == 16 |
123 | #else | 155 | /* Should adapt dithering to all native depths */ |
124 | bool transparent; | 156 | bool dither = false; |
125 | 157 | if(format & FORMAT_DITHER) { | |
158 | dither = true; | ||
159 | format &= ~FORMAT_DITHER; | ||
160 | } | ||
161 | #endif | ||
126 | if(format & FORMAT_TRANSPARENT) { | 162 | if(format & FORMAT_TRANSPARENT) { |
127 | transparent = true; | 163 | transparent = true; |
128 | format &= ~FORMAT_TRANSPARENT; | 164 | format &= ~FORMAT_TRANSPARENT; |
129 | } | 165 | } |
166 | #else | ||
167 | format = FORMAT_MONO; | ||
130 | #endif | 168 | #endif |
131 | 169 | ||
132 | |||
133 | fd = open(filename, O_RDONLY); | 170 | fd = open(filename, O_RDONLY); |
134 | 171 | ||
135 | /* Exit if file opening failed */ | 172 | /* Exit if file opening failed */ |
@@ -362,12 +399,11 @@ int read_bmp_file(char* filename, | |||
362 | #elif LCD_DEPTH == 16 | 399 | #elif LCD_DEPTH == 16 |
363 | } else { | 400 | } else { |
364 | /* 8-bit RGB24 palette -> RGB16 */ | 401 | /* 8-bit RGB24 palette -> RGB16 */ |
365 | for (col = 0; col < width; col++) { | 402 | for (col = 0; col < width; col++, p++) { |
366 | struct rgb_quad rgb = palette[*p]; | 403 | struct rgb_quad rgb = palette[*p]; |
367 | unsigned short rgb16 = | 404 | dest[width * (height - row - 1) + col] = dither ? |
405 | dither_24_to_16(rgb, row, col) : | ||
368 | LCD_RGBPACK(rgb.red, rgb.green, rgb.blue); | 406 | LCD_RGBPACK(rgb.red, rgb.green, rgb.blue); |
369 | dest[width * (height - row - 1) + col] = rgb16; | ||
370 | p++; | ||
371 | } | 407 | } |
372 | } | 408 | } |
373 | #endif | 409 | #endif |
@@ -429,10 +465,10 @@ int read_bmp_file(char* filename, | |||
429 | #elif LCD_DEPTH == 16 | 465 | #elif LCD_DEPTH == 16 |
430 | } else { | 466 | } else { |
431 | /* RGB24 -> RGB16 */ | 467 | /* RGB24 -> RGB16 */ |
432 | for (col = 0; col < width; col++) { | 468 | for (col = 0; col < width; col++, p += 3) { |
433 | unsigned short rgb = LCD_RGBPACK(p[2],p[1],p[0]); | 469 | dest[width * (height - row - 1) + col] = dither ? |
434 | dest[width * (height - row - 1) + col] = rgb; | 470 | dither_24_to_16(*(struct rgb_quad *)p, row, col) : |
435 | p += 3; | 471 | LCD_RGBPACK(p[2], p[1], p[0]); |
436 | } | 472 | } |
437 | } | 473 | } |
438 | #endif | 474 | #endif |
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index b74a9d30c7..7fe76a5366 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h | |||
@@ -246,6 +246,7 @@ enum | |||
246 | }; | 246 | }; |
247 | 247 | ||
248 | #define FORMAT_TRANSPARENT 0x40000000 | 248 | #define FORMAT_TRANSPARENT 0x40000000 |
249 | #define FORMAT_DITHER 0x20000000 | ||
249 | 250 | ||
250 | #define TRANSPARENT_COLOR LCD_RGBPACK(255,0,255) | 251 | #define TRANSPARENT_COLOR LCD_RGBPACK(255,0,255) |
251 | 252 | ||