summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2013-12-21 17:12:21 +0100
committerThomas Martitz <kugel@rockbox.org>2013-12-22 19:55:55 +0100
commitef92ed4a6a997524944f42aa7abffddca7bef05e (patch)
tree1cc9e335d5924a09e237340177fe959f1c8aa10c
parent21ff83295e391f10d9e2e7ee9fac214edf4f7d45 (diff)
downloadrockbox-ef92ed4a6a997524944f42aa7abffddca7bef05e.tar.gz
rockbox-ef92ed4a6a997524944f42aa7abffddca7bef05e.zip
Support GIMP bmp files.
Change-Id: I7380ceeaf696b67e1641d24e7b932e3d74770932
-rw-r--r--apps/recorder/bmp.c110
-rw-r--r--apps/recorder/bmp.h1
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
95union 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) */
106static const struct uint8_rgb bitfields[3][3] = { 96static 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
171static inline void set_rgb_union(struct uint8_rgb *dst, union rgb_union src) 171enum 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
179struct bmp_args { 177struct 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
368static inline int rgbcmp(struct uint8_rgb rgb1, struct uint8_rgb rgb2) 380static 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)
378static inline 387static 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
38struct uint8_rgb { 38struct 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;