diff options
author | Thomas Martitz <kugel@rockbox.org> | 2013-12-21 17:12:21 +0100 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2013-12-22 19:55:55 +0100 |
commit | ef92ed4a6a997524944f42aa7abffddca7bef05e (patch) | |
tree | 1cc9e335d5924a09e237340177fe959f1c8aa10c | |
parent | 21ff83295e391f10d9e2e7ee9fac214edf4f7d45 (diff) | |
download | rockbox-ef92ed4a6a997524944f42aa7abffddca7bef05e.tar.gz rockbox-ef92ed4a6a997524944f42aa7abffddca7bef05e.zip |
Support GIMP bmp files.
Change-Id: I7380ceeaf696b67e1641d24e7b932e3d74770932
-rw-r--r-- | apps/recorder/bmp.c | 110 | ||||
-rw-r--r-- | apps/recorder/bmp.h | 1 |
2 files changed, 67 insertions, 44 deletions
diff --git a/apps/recorder/bmp.c b/apps/recorder/bmp.c index 011a4d60fe..75d82b449f 100644 --- a/apps/recorder/bmp.c +++ b/apps/recorder/bmp.c | |||
@@ -92,35 +92,35 @@ struct bmp_header { | |||
92 | uint32_t clr_important; /* important color count */ | 92 | uint32_t clr_important; /* important color count */ |
93 | } STRUCT_PACKED; | 93 | } STRUCT_PACKED; |
94 | 94 | ||
95 | union rgb_union { | ||
96 | struct { /* Little endian */ | ||
97 | unsigned char blue; | ||
98 | unsigned char green; | ||
99 | unsigned char red; | ||
100 | unsigned char reserved; | ||
101 | }; | ||
102 | uint32_t raw; | ||
103 | }; | ||
104 | |||
105 | /* masks for supported BI_BITFIELDS encodings (16/32 bit) */ | 95 | /* masks for supported BI_BITFIELDS encodings (16/32 bit) */ |
106 | static const struct uint8_rgb bitfields[3][3] = { | 96 | static const struct uint8_rgb bitfields[][4] = { |
107 | /* 15bit */ | 97 | /* 15bit */ |
108 | { | 98 | { |
109 | { .blue = 0x00, .green = 0x7c, .red = 0x00 }, | 99 | { .blue = 0x00, .green = 0x7c, .red = 0x00, .alpha = 0x00 }, |
110 | { .blue = 0xe0, .green = 0x03, .red = 0x00 }, | 100 | { .blue = 0xe0, .green = 0x03, .red = 0x00, .alpha = 0x00 }, |
111 | { .blue = 0x1f, .green = 0x00, .red = 0x00 }, | 101 | { .blue = 0x1f, .green = 0x00, .red = 0x00, .alpha = 0x00 }, |
102 | { .blue = 0x00, .green = 0x00, .red = 0x00, .alpha = 0x00 }, | ||
112 | }, | 103 | }, |
113 | /* 16bit */ | 104 | /* 16bit */ |
114 | { | 105 | { |
115 | { .blue = 0x00, .green = 0xf8, .red = 0x00 }, | 106 | { .blue = 0x00, .green = 0xf8, .red = 0x00, .alpha = 0x00 }, |
116 | { .blue = 0xe0, .green = 0x07, .red = 0x00 }, | 107 | { .blue = 0xe0, .green = 0x07, .red = 0x00, .alpha = 0x00 }, |
117 | { .blue = 0x1f, .green = 0x00, .red = 0x00 }, | 108 | { .blue = 0x1f, .green = 0x00, .red = 0x00, .alpha = 0x00 }, |
109 | { .blue = 0x00, .green = 0x00, .red = 0x00, .alpha = 0x00 }, | ||
118 | }, | 110 | }, |
119 | /* 32bit */ | 111 | /* 32bit BGRA */ |
120 | { | 112 | { |
121 | { .blue = 0x00, .green = 0x00, .red = 0xff }, | 113 | { .blue = 0x00, .green = 0x00, .red = 0xff, .alpha = 0x00 }, |
122 | { .blue = 0x00, .green = 0xff, .red = 0x00 }, | 114 | { .blue = 0x00, .green = 0xff, .red = 0x00, .alpha = 0x00 }, |
123 | { .blue = 0xff, .green = 0x00, .red = 0x00 }, | 115 | { .blue = 0xff, .green = 0x00, .red = 0x00, .alpha = 0x00 }, |
116 | { .blue = 0x00, .green = 0x00, .red = 0x00, .alpha = 0xff }, | ||
117 | }, | ||
118 | /* 32bit ABGR */ | ||
119 | { | ||
120 | { .blue = 0x00, .green = 0x00, .red = 0x00, .alpha = 0xff }, | ||
121 | { .blue = 0x00, .green = 0x00, .red = 0xff, .alpha = 0x00 }, | ||
122 | { .blue = 0x00, .green = 0xff, .red = 0x00, .alpha = 0x00 }, | ||
123 | { .blue = 0xff, .green = 0x00, .red = 0x00, .alpha = 0x00 }, | ||
124 | }, | 124 | }, |
125 | }; | 125 | }; |
126 | 126 | ||
@@ -168,13 +168,11 @@ int read_bmp_file(const char* filename, | |||
168 | return ret; | 168 | return ret; |
169 | } | 169 | } |
170 | 170 | ||
171 | static inline void set_rgb_union(struct uint8_rgb *dst, union rgb_union src) | 171 | enum color_order { |
172 | { | 172 | /* only used for different types of 32bpp images */ |
173 | dst->red = src.red; | 173 | BGRA, /* should be most common */ |
174 | dst->green = src.green; | 174 | ABGR /* generated by some GIMP versions */ |
175 | dst->blue = src.blue; | 175 | }; |
176 | dst->alpha = 0xff; | ||
177 | } | ||
178 | 176 | ||
179 | struct bmp_args { | 177 | struct bmp_args { |
180 | int fd; | 178 | int fd; |
@@ -182,6 +180,7 @@ struct bmp_args { | |||
182 | short read_width; | 180 | short read_width; |
183 | short width; | 181 | short width; |
184 | short depth; | 182 | short depth; |
183 | enum color_order order; | ||
185 | unsigned char buf[BM_MAX_WIDTH * 4]; | 184 | unsigned char buf[BM_MAX_WIDTH * 4]; |
186 | struct uint8_rgb *palette; | 185 | struct uint8_rgb *palette; |
187 | #if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \ | 186 | #if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \ |
@@ -203,7 +202,7 @@ static unsigned int read_part_line(struct bmp_args *ba) | |||
203 | const int padded_width = ba->padded_width; | 202 | const int padded_width = ba->padded_width; |
204 | const int read_width = ba->read_width; | 203 | const int read_width = ba->read_width; |
205 | const int width = ba->width; | 204 | const int width = ba->width; |
206 | const int depth = ba->depth; | 205 | int depth = ba->depth; |
207 | #if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \ | 206 | #if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \ |
208 | defined(HAVE_BMP_SCALING) || defined(PLUGIN) | 207 | defined(HAVE_BMP_SCALING) || defined(PLUGIN) |
209 | int cur_row = ba->cur_row; | 208 | int cur_row = ba->cur_row; |
@@ -250,6 +249,11 @@ static unsigned int read_part_line(struct bmp_args *ba) | |||
250 | if (depth == 32 && ba->first_alpha_byte == 0x80) | 249 | if (depth == 32 && ba->first_alpha_byte == 0x80) |
251 | ba->first_alpha_byte = ibuf[3] ? 0xff : 0x0; | 250 | ba->first_alpha_byte = ibuf[3] ? 0xff : 0x0; |
252 | 251 | ||
252 | /* select different color orders within the switch-case to avoid | ||
253 | * nested if/switch */ | ||
254 | if (depth == 32) | ||
255 | depth += ba->order; | ||
256 | |||
253 | while (ibuf < ba->buf + (BM_MAX_WIDTH << 2)) | 257 | while (ibuf < ba->buf + (BM_MAX_WIDTH << 2)) |
254 | { | 258 | { |
255 | switch (depth) | 259 | switch (depth) |
@@ -302,7 +306,7 @@ static unsigned int read_part_line(struct bmp_args *ba) | |||
302 | buf->alpha = 0xff; | 306 | buf->alpha = 0xff; |
303 | buf++; | 307 | buf++; |
304 | break; | 308 | break; |
305 | case 32: | 309 | case 32 + BGRA: |
306 | buf->blue = *ibuf++; | 310 | buf->blue = *ibuf++; |
307 | buf->green = *ibuf++; | 311 | buf->green = *ibuf++; |
308 | buf->red = *ibuf++; | 312 | buf->red = *ibuf++; |
@@ -310,6 +314,14 @@ static unsigned int read_part_line(struct bmp_args *ba) | |||
310 | ba->alpha_detected |= (buf->alpha != ba->first_alpha_byte); | 314 | ba->alpha_detected |= (buf->alpha != ba->first_alpha_byte); |
311 | buf++; | 315 | buf++; |
312 | break; | 316 | break; |
317 | case 32 + ABGR: | ||
318 | buf->alpha = *ibuf++; | ||
319 | buf->blue = *ibuf++; | ||
320 | buf->green = *ibuf++; | ||
321 | buf->red = *ibuf++; | ||
322 | ba->alpha_detected |= (buf->alpha != ba->first_alpha_byte); | ||
323 | buf++; | ||
324 | break; | ||
313 | } | 325 | } |
314 | } | 326 | } |
315 | #if !defined(HAVE_LCD_COLOR) && \ | 327 | #if !defined(HAVE_LCD_COLOR) && \ |
@@ -365,14 +377,11 @@ static struct img_part *store_part_bmp(void *args) | |||
365 | } | 377 | } |
366 | #endif | 378 | #endif |
367 | 379 | ||
368 | static inline int rgbcmp(struct uint8_rgb rgb1, struct uint8_rgb rgb2) | 380 | static inline int rgbcmp(const struct uint8_rgb *rgb1, const struct uint8_rgb *rgb2) |
369 | { | 381 | { |
370 | if ((rgb1.red == rgb2.red) && (rgb1.green == rgb2.green) && | 382 | return memcmp(rgb1, rgb2, sizeof(struct uint8_rgb)); |
371 | (rgb1.blue == rgb2.blue)) | ||
372 | return 0; | ||
373 | else | ||
374 | return 1; | ||
375 | } | 383 | } |
384 | |||
376 | #if LCD_DEPTH > 1 | 385 | #if LCD_DEPTH > 1 |
377 | #if !defined(PLUGIN) && !defined(HAVE_JPEG) && !defined(HAVE_BMP_SCALING) | 386 | #if !defined(PLUGIN) && !defined(HAVE_JPEG) && !defined(HAVE_BMP_SCALING) |
378 | static inline | 387 | static inline |
@@ -504,6 +513,7 @@ int read_bmp_fd(int fd, | |||
504 | int ret; | 513 | int ret; |
505 | bool return_size = format & FORMAT_RETURN_SIZE; | 514 | bool return_size = format & FORMAT_RETURN_SIZE; |
506 | bool read_alpha = format & FORMAT_TRANSPARENT; | 515 | bool read_alpha = format & FORMAT_TRANSPARENT; |
516 | enum color_order order = BGRA; | ||
507 | 517 | ||
508 | unsigned char *bitmap = bm->data; | 518 | unsigned char *bitmap = bm->data; |
509 | struct uint8_rgb palette[256]; | 519 | struct uint8_rgb palette[256]; |
@@ -668,19 +678,27 @@ int read_bmp_fd(int fd, | |||
668 | numcolors = letoh32(bmph.clr_used); | 678 | numcolors = letoh32(bmph.clr_used); |
669 | if (numcolors == 0) | 679 | if (numcolors == 0) |
670 | numcolors = BIT_N(depth); | 680 | numcolors = BIT_N(depth); |
671 | } else | 681 | } else { |
672 | numcolors = (compression == 3) ? 3 : 0; | 682 | int hdr_size = letoh32(bmph.struct_size); |
683 | numcolors = 0; | ||
684 | if (compression == 3) { | ||
685 | if (hdr_size >= 56) | ||
686 | numcolors = 4; | ||
687 | else /* hdr_size == 52 */ | ||
688 | numcolors = 3; | ||
689 | } | ||
690 | } | ||
673 | 691 | ||
692 | /* read color tables. for BI_BITFIELDS this actually | ||
693 | * reads the color masks */ | ||
674 | if (numcolors > 0 && numcolors <= 256) { | 694 | if (numcolors > 0 && numcolors <= 256) { |
675 | int i; | 695 | int i; |
676 | union rgb_union pal; | ||
677 | for (i = 0; i < numcolors; i++) { | 696 | for (i = 0; i < numcolors; i++) { |
678 | if (read(fd, &pal, sizeof(pal)) != (int)sizeof(pal)) | 697 | if (read(fd, &palette[i], sizeof(struct uint8_rgb)) |
679 | { | 698 | != (int)sizeof(struct uint8_rgb)) { |
680 | DEBUGF("read_bmp_fd: Can't read color palette\n"); | 699 | DEBUGF("read_bmp_fd: Can't read color palette\n"); |
681 | return -7; | 700 | return -7; |
682 | } | 701 | } |
683 | set_rgb_union(&palette[i], pal); | ||
684 | } | 702 | } |
685 | } | 703 | } |
686 | 704 | ||
@@ -705,8 +723,9 @@ int read_bmp_fd(int fd, | |||
705 | 723 | ||
706 | /* (i == 0) is 15bit, (i == 1) is 16bit, (i == 2) is 32bit */ | 724 | /* (i == 0) is 15bit, (i == 1) is 16bit, (i == 2) is 32bit */ |
707 | for (i = 0; i < ARRAY_SIZE(bitfields); i++) { | 725 | for (i = 0; i < ARRAY_SIZE(bitfields); i++) { |
708 | for (j = 0; j < ARRAY_SIZE(bitfields[0]); j++) { | 726 | /* for 15bpp and higher numcolors has the number of color masks */ |
709 | if (!rgbcmp(palette[j], bitfields[i][j])) { | 727 | for (j = 0; j < numcolors; j++) { |
728 | if (!rgbcmp(&palette[j], &bitfields[i][j])) { | ||
710 | found = true; | 729 | found = true; |
711 | } else { | 730 | } else { |
712 | found = false; | 731 | found = false; |
@@ -716,6 +735,8 @@ int read_bmp_fd(int fd, | |||
716 | if (found) { | 735 | if (found) { |
717 | if (i == 0) /* 15bit */ | 736 | if (i == 0) /* 15bit */ |
718 | depth = 15; | 737 | depth = 15; |
738 | else if (i == 3) /* 32bit, ABGR bitmap */ | ||
739 | order = ABGR; | ||
719 | break; | 740 | break; |
720 | } | 741 | } |
721 | } | 742 | } |
@@ -752,6 +773,7 @@ int read_bmp_fd(int fd, | |||
752 | .cur_row = 0, .cur_col = 0, .part = {0,0}, | 773 | .cur_row = 0, .cur_col = 0, .part = {0,0}, |
753 | #endif | 774 | #endif |
754 | .alpha_detected = false, .first_alpha_byte = 0x80, | 775 | .alpha_detected = false, .first_alpha_byte = 0x80, |
776 | .order = order, | ||
755 | }; | 777 | }; |
756 | 778 | ||
757 | #if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \ | 779 | #if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \ |
diff --git a/apps/recorder/bmp.h b/apps/recorder/bmp.h index 3ddc3b66df..610ec29f21 100644 --- a/apps/recorder/bmp.h +++ b/apps/recorder/bmp.h | |||
@@ -36,6 +36,7 @@ | |||
36 | #define BM_MAX_WIDTH (((LCD_WIDTH) + 7) & ~7) | 36 | #define BM_MAX_WIDTH (((LCD_WIDTH) + 7) & ~7) |
37 | 37 | ||
38 | struct uint8_rgb { | 38 | struct uint8_rgb { |
39 | /* Little endian */ | ||
39 | uint8_t blue; | 40 | uint8_t blue; |
40 | uint8_t green; | 41 | uint8_t green; |
41 | uint8_t red; | 42 | uint8_t red; |