diff options
-rw-r--r-- | apps/recorder/bmp.c | 193 | ||||
-rw-r--r-- | firmware/export/lcd.h | 3 |
2 files changed, 125 insertions, 71 deletions
diff --git a/apps/recorder/bmp.c b/apps/recorder/bmp.c index 130505b9bc..96b915f840 100644 --- a/apps/recorder/bmp.c +++ b/apps/recorder/bmp.c | |||
@@ -35,6 +35,9 @@ | |||
35 | #include "inttypes.h" | 35 | #include "inttypes.h" |
36 | #include "debug.h" | 36 | #include "debug.h" |
37 | #include "lcd.h" | 37 | #include "lcd.h" |
38 | #ifdef HAVE_REMOTE_LCD | ||
39 | #include "lcd-remote.h" | ||
40 | #endif | ||
38 | #include "file.h" | 41 | #include "file.h" |
39 | #include "config.h" | 42 | #include "config.h" |
40 | #include "system.h" | 43 | #include "system.h" |
@@ -85,7 +88,7 @@ static const unsigned char bitfields[3][12] = { | |||
85 | { 0x00,0x00,0xff,0, 0x00,0xff,0x00,0, 0xff,0x00,0x00,0 }, /* 32 bit */ | 88 | { 0x00,0x00,0xff,0, 0x00,0xff,0x00,0, 0xff,0x00,0x00,0 }, /* 32 bit */ |
86 | }; | 89 | }; |
87 | 90 | ||
88 | #if LCD_DEPTH > 1 | 91 | #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) |
89 | /* canonical ordered dither matrix */ | 92 | /* canonical ordered dither matrix */ |
90 | static const unsigned char dither_matrix[16][16] = { | 93 | static const unsigned char dither_matrix[16][16] = { |
91 | { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, | 94 | { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, |
@@ -107,6 +110,13 @@ static const unsigned char dither_matrix[16][16] = { | |||
107 | }; | 110 | }; |
108 | #endif | 111 | #endif |
109 | 112 | ||
113 | #if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH == 2) \ | ||
114 | && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) | ||
115 | static const fb_remote_data remote_pattern[4] = { | ||
116 | 0x0101, 0x0100, 0x0001, 0x0000 | ||
117 | }; | ||
118 | #endif | ||
119 | |||
110 | /* little endian functions */ | 120 | /* little endian functions */ |
111 | static inline unsigned readshort(uint16_t *value) | 121 | static inline unsigned readshort(uint16_t *value) |
112 | { | 122 | { |
@@ -147,10 +157,21 @@ int read_bmp_file(char* filename, | |||
147 | unsigned char *bitmap = bm->data; | 157 | unsigned char *bitmap = bm->data; |
148 | uint32_t bmpbuf[LCD_WIDTH]; /* Buffer for one line */ | 158 | uint32_t bmpbuf[LCD_WIDTH]; /* Buffer for one line */ |
149 | uint32_t palette[256]; | 159 | uint32_t palette[256]; |
150 | #if LCD_DEPTH > 1 | 160 | #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) |
151 | bool transparent = false; | 161 | bool transparent = false; |
152 | bool dither = false; | 162 | bool dither = false; |
153 | 163 | #ifdef HAVE_REMOTE_LCD | |
164 | bool remote = false; | ||
165 | |||
166 | if (format & FORMAT_REMOTE) { | ||
167 | remote = true; | ||
168 | #if LCD_REMOTE_DEPTH == 1 | ||
169 | format = FORMAT_MONO; | ||
170 | #else | ||
171 | format &= ~FORMAT_REMOTE; | ||
172 | #endif | ||
173 | } | ||
174 | #endif /* HAVE_REMOTE_LCD */ | ||
154 | if (format & FORMAT_TRANSPARENT) { | 175 | if (format & FORMAT_TRANSPARENT) { |
155 | transparent = true; | 176 | transparent = true; |
156 | format &= ~FORMAT_TRANSPARENT; | 177 | format &= ~FORMAT_TRANSPARENT; |
@@ -162,7 +183,7 @@ int read_bmp_file(char* filename, | |||
162 | #else | 183 | #else |
163 | 184 | ||
164 | (void)format; | 185 | (void)format; |
165 | #endif | 186 | #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ |
166 | 187 | ||
167 | fd = open(filename, O_RDONLY); | 188 | fd = open(filename, O_RDONLY); |
168 | 189 | ||
@@ -204,7 +225,7 @@ int read_bmp_file(char* filename, | |||
204 | depth = readshort(&bmph.bit_count); | 225 | depth = readshort(&bmph.bit_count); |
205 | padded_width = ((width * depth + 31) / 8) & ~3; /* 4-byte boundary aligned */ | 226 | padded_width = ((width * depth + 31) / 8) & ~3; /* 4-byte boundary aligned */ |
206 | 227 | ||
207 | #if LCD_DEPTH > 1 | 228 | #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) |
208 | if (format == FORMAT_ANY) { | 229 | if (format == FORMAT_ANY) { |
209 | if (depth == 1) | 230 | if (depth == 1) |
210 | format = FORMAT_MONO; | 231 | format = FORMAT_MONO; |
@@ -212,28 +233,39 @@ int read_bmp_file(char* filename, | |||
212 | format = FORMAT_NATIVE; | 233 | format = FORMAT_NATIVE; |
213 | } | 234 | } |
214 | bm->format = format; | 235 | bm->format = format; |
215 | #endif | 236 | #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ |
216 | /* returning image size */ | 237 | /* returning image size */ |
217 | bm->width = width; | 238 | bm->width = width; |
218 | bm->height = height; | 239 | bm->height = height; |
219 | 240 | ||
220 | #if LCD_DEPTH > 1 | 241 | #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) |
221 | if (format == FORMAT_NATIVE) { | 242 | if (format == FORMAT_NATIVE) { |
243 | #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 | ||
244 | if (remote) { | ||
245 | #if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) | ||
246 | dst_width = width; | ||
247 | dst_height = (height + 7) / 8; | ||
248 | #endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ | ||
249 | totalsize = dst_width * dst_height * sizeof(fb_remote_data); | ||
250 | } else | ||
251 | #endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ | ||
252 | { | ||
222 | #if LCD_DEPTH == 2 | 253 | #if LCD_DEPTH == 2 |
223 | #if LCD_PIXELFORMAT == VERTICAL_PACKING | 254 | #if LCD_PIXELFORMAT == VERTICAL_PACKING |
224 | dst_width = width; | 255 | dst_width = width; |
225 | dst_height = (height + 3) / 4; | 256 | dst_height = (height + 3) / 4; |
226 | #else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ | 257 | #else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ |
227 | dst_width = (width + 3) / 4; | 258 | dst_width = (width + 3) / 4; |
228 | dst_height = height; | 259 | dst_height = height; |
229 | #endif /* LCD_PIXELFORMAT */ | 260 | #endif /* LCD_PIXELFORMAT */ |
230 | #elif LCD_DEPTH == 16 | 261 | #elif LCD_DEPTH == 16 |
231 | dst_width = width; | 262 | dst_width = width; |
232 | dst_height = height; | 263 | dst_height = height; |
233 | #endif /* LCD_DEPTH */ | 264 | #endif /* LCD_DEPTH */ |
234 | totalsize = dst_width * dst_height * sizeof(fb_data); | 265 | totalsize = dst_width * dst_height * sizeof(fb_data); |
266 | } | ||
235 | } else | 267 | } else |
236 | #endif /* LCD_DEPTH > 1 */ | 268 | #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ |
237 | { | 269 | { |
238 | dst_width = width; | 270 | dst_width = width; |
239 | dst_height = (height + 7) / 8; | 271 | dst_height = (height + 7) / 8; |
@@ -270,7 +302,10 @@ int read_bmp_file(char* filename, | |||
270 | case 16: | 302 | case 16: |
271 | #if LCD_DEPTH >= 16 | 303 | #if LCD_DEPTH >= 16 |
272 | /* don't dither 16 bit BMP to LCD with same or larger depth */ | 304 | /* don't dither 16 bit BMP to LCD with same or larger depth */ |
273 | dither = false; | 305 | #ifdef HAVE_REMOTE_LCD |
306 | if (!remote) | ||
307 | #endif | ||
308 | dither = false; | ||
274 | #endif | 309 | #endif |
275 | if (compression == 0) { /* BI_RGB, i.e. 15 bit */ | 310 | if (compression == 0) { /* BI_RGB, i.e. 15 bit */ |
276 | depth = 15; | 311 | depth = 15; |
@@ -303,10 +338,7 @@ int read_bmp_file(char* filename, | |||
303 | /* Search to the beginning of the image data */ | 338 | /* Search to the beginning of the image data */ |
304 | lseek(fd, (off_t)readlong(&bmph.off_bits), SEEK_SET); | 339 | lseek(fd, (off_t)readlong(&bmph.off_bits), SEEK_SET); |
305 | 340 | ||
306 | #if LCD_DEPTH >= 8 | 341 | memset(bitmap, 0, totalsize); |
307 | if (format == FORMAT_MONO) | ||
308 | #endif | ||
309 | memset(bitmap, 0, totalsize); | ||
310 | 342 | ||
311 | /* loop to read rows and put them to buffer */ | 343 | /* loop to read rows and put them to buffer */ |
312 | for (row = height - 1; row >= 0; row--) { | 344 | for (row = height - 1; row >= 0; row--) { |
@@ -422,65 +454,86 @@ int read_bmp_file(char* filename, | |||
422 | 454 | ||
423 | /* Convert to destination format */ | 455 | /* Convert to destination format */ |
424 | qp = (union rgb_union *)bmpbuf; | 456 | qp = (union rgb_union *)bmpbuf; |
425 | #if LCD_DEPTH > 1 | 457 | #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) |
426 | if (format == FORMAT_NATIVE) { | 458 | if (format == FORMAT_NATIVE) { |
459 | #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 | ||
460 | if (remote) { | ||
461 | #if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) | ||
462 | fb_remote_data *dest = (fb_remote_data *)bitmap | ||
463 | + dst_width * (row / 8); | ||
464 | int shift = row & 7; | ||
465 | int delta = 127; | ||
466 | unsigned bright; | ||
467 | |||
468 | for (col = 0; col < width; col++) { | ||
469 | if (dither) | ||
470 | delta = dither_matrix[row & 0xf][col & 0xf]; | ||
471 | bright = brightness(*qp++); | ||
472 | bright = (3 * bright + (bright >> 6) + delta) >> 8; | ||
473 | *dest++ |= remote_pattern[bright] << shift; | ||
474 | } | ||
475 | #endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ | ||
476 | } else | ||
477 | #endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ | ||
478 | { | ||
427 | #if LCD_DEPTH == 2 | 479 | #if LCD_DEPTH == 2 |
428 | #if LCD_PIXELFORMAT == VERTICAL_PACKING | 480 | #if LCD_PIXELFORMAT == VERTICAL_PACKING |
429 | /* iriver H1x0 */ | 481 | /* iriver H1x0 */ |
430 | fb_data *dest = (fb_data *)bitmap + dst_width * (row / 4); | 482 | fb_data *dest = (fb_data *)bitmap + dst_width * (row / 4); |
431 | int shift = 2 * (row & 3); | 483 | int shift = 2 * (row & 3); |
432 | int delta = 127; | 484 | int delta = 127; |
433 | unsigned bright; | 485 | unsigned bright; |
434 | 486 | ||
435 | for (col = 0; col < width; col++) { | 487 | for (col = 0; col < width; col++) { |
436 | if (dither) | 488 | if (dither) |
437 | delta = dither_matrix[row & 0xf][col & 0xf]; | 489 | delta = dither_matrix[row & 0xf][col & 0xf]; |
438 | bright = brightness(*qp++); | 490 | bright = brightness(*qp++); |
439 | bright = (3 * bright + (bright >> 6) + delta) >> 8; | 491 | bright = (3 * bright + (bright >> 6) + delta) >> 8; |
440 | *dest++ |= (~bright & 3) << shift; | 492 | *dest++ |= (~bright & 3) << shift; |
441 | } | 493 | } |
442 | #else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ | 494 | #else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ |
443 | /* greyscale iPods */ | 495 | /* greyscale iPods */ |
444 | fb_data *dest = (fb_data *)bitmap + dst_width * row; | 496 | fb_data *dest = (fb_data *)bitmap + dst_width * row; |
445 | int shift = 6; | 497 | int shift = 6; |
446 | int delta = 127; | 498 | int delta = 127; |
447 | unsigned bright; | 499 | unsigned bright; |
448 | unsigned data = 0; | 500 | unsigned data = 0; |
449 | 501 | ||
450 | for (col = 0; col < width; col++) { | 502 | for (col = 0; col < width; col++) { |
451 | if (dither) | 503 | if (dither) |
452 | delta = dither_matrix[row & 0xf][col & 0xf]; | 504 | delta = dither_matrix[row & 0xf][col & 0xf]; |
453 | bright = brightness(*qp++); | 505 | bright = brightness(*qp++); |
454 | bright = (3 * bright + (bright >> 6) + delta) >> 8; | 506 | bright = (3 * bright + (bright >> 6) + delta) >> 8; |
455 | data |= (~bright & 3) << shift; | 507 | data |= (~bright & 3) << shift; |
456 | shift -= 2; | 508 | shift -= 2; |
457 | if (shift < 0) { | 509 | if (shift < 0) { |
458 | *dest++ = data; | 510 | *dest++ = data; |
459 | data = 0; | 511 | data = 0; |
460 | shift = 6; | 512 | shift = 6; |
513 | } | ||
461 | } | 514 | } |
462 | } | 515 | if (shift < 6) |
463 | if (shift < 6) | 516 | *dest++ = data; |
464 | *dest++ = data; | ||
465 | #endif /* LCD_PIXELFORMAT */ | 517 | #endif /* LCD_PIXELFORMAT */ |
466 | #elif LCD_DEPTH == 16 | 518 | #elif LCD_DEPTH == 16 |
467 | /* iriver h300, colour iPods, X5 */ | 519 | /* iriver h300, colour iPods, X5 */ |
468 | fb_data *dest = (fb_data *)bitmap + dst_width * row; | 520 | fb_data *dest = (fb_data *)bitmap + dst_width * row; |
469 | int delta = 127; | 521 | int delta = 127; |
470 | unsigned r, g, b; | 522 | unsigned r, g, b; |
471 | 523 | ||
472 | for (col = 0; col < width; col++) { | 524 | for (col = 0; col < width; col++) { |
473 | if (dither) | 525 | if (dither) |
474 | delta = dither_matrix[row & 0xf][col & 0xf]; | 526 | delta = dither_matrix[row & 0xf][col & 0xf]; |
475 | q0 = *qp++; | 527 | q0 = *qp++; |
476 | r = (31 * q0.red + (q0.red >> 3) + delta) >> 8; | 528 | r = (31 * q0.red + (q0.red >> 3) + delta) >> 8; |
477 | g = (63 * q0.green + (q0.green >> 2) + delta) >> 8; | 529 | g = (63 * q0.green + (q0.green >> 2) + delta) >> 8; |
478 | b = (31 * q0.blue + (q0.blue >> 3) + delta) >> 8; | 530 | b = (31 * q0.blue + (q0.blue >> 3) + delta) >> 8; |
479 | *dest++ = LCD_RGBPACK_LCD(r, g, b); | 531 | *dest++ = LCD_RGBPACK_LCD(r, g, b); |
480 | } | 532 | } |
481 | #endif /* LCD_DEPTH */ | 533 | #endif /* LCD_DEPTH */ |
534 | } | ||
482 | } else | 535 | } else |
483 | #endif /* LCD_DEPTH > 1 */ | 536 | #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ |
484 | { | 537 | { |
485 | p = bitmap + dst_width * (row / 8); | 538 | p = bitmap + dst_width * (row / 8); |
486 | mask = 1 << (row & 7); | 539 | mask = 1 << (row & 7); |
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index ceb0f6e3d2..1ccbc513d2 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h | |||
@@ -277,13 +277,14 @@ enum | |||
277 | 277 | ||
278 | #define FORMAT_TRANSPARENT 0x40000000 | 278 | #define FORMAT_TRANSPARENT 0x40000000 |
279 | #define FORMAT_DITHER 0x20000000 | 279 | #define FORMAT_DITHER 0x20000000 |
280 | #define FORMAT_REMOTE 0x10000000 | ||
280 | 281 | ||
281 | #define TRANSPARENT_COLOR LCD_RGBPACK(255,0,255) | 282 | #define TRANSPARENT_COLOR LCD_RGBPACK(255,0,255) |
282 | 283 | ||
283 | struct bitmap { | 284 | struct bitmap { |
284 | int width; | 285 | int width; |
285 | int height; | 286 | int height; |
286 | #if LCD_DEPTH > 1 | 287 | #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) |
287 | int format; | 288 | int format; |
288 | unsigned char *maskdata; | 289 | unsigned char *maskdata; |
289 | #endif | 290 | #endif |