summaryrefslogtreecommitdiffstats
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-ef92ed4.tar.gz
rockbox-ef92ed4.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 {
uint32_t clr_important; /* important color count */
} STRUCT_PACKED;
-union rgb_union {
- struct { /* Little endian */
- unsigned char blue;
- unsigned char green;
- unsigned char red;
- unsigned char reserved;
- };
- uint32_t raw;
-};
-
/* masks for supported BI_BITFIELDS encodings (16/32 bit) */
-static const struct uint8_rgb bitfields[3][3] = {
+static const struct uint8_rgb bitfields[][4] = {
/* 15bit */
{
- { .blue = 0x00, .green = 0x7c, .red = 0x00 },
- { .blue = 0xe0, .green = 0x03, .red = 0x00 },
- { .blue = 0x1f, .green = 0x00, .red = 0x00 },
+ { .blue = 0x00, .green = 0x7c, .red = 0x00, .alpha = 0x00 },
+ { .blue = 0xe0, .green = 0x03, .red = 0x00, .alpha = 0x00 },
+ { .blue = 0x1f, .green = 0x00, .red = 0x00, .alpha = 0x00 },
+ { .blue = 0x00, .green = 0x00, .red = 0x00, .alpha = 0x00 },
},
/* 16bit */
{
- { .blue = 0x00, .green = 0xf8, .red = 0x00 },
- { .blue = 0xe0, .green = 0x07, .red = 0x00 },
- { .blue = 0x1f, .green = 0x00, .red = 0x00 },
+ { .blue = 0x00, .green = 0xf8, .red = 0x00, .alpha = 0x00 },
+ { .blue = 0xe0, .green = 0x07, .red = 0x00, .alpha = 0x00 },
+ { .blue = 0x1f, .green = 0x00, .red = 0x00, .alpha = 0x00 },
+ { .blue = 0x00, .green = 0x00, .red = 0x00, .alpha = 0x00 },
},
- /* 32bit */
+ /* 32bit BGRA */
{
- { .blue = 0x00, .green = 0x00, .red = 0xff },
- { .blue = 0x00, .green = 0xff, .red = 0x00 },
- { .blue = 0xff, .green = 0x00, .red = 0x00 },
+ { .blue = 0x00, .green = 0x00, .red = 0xff, .alpha = 0x00 },
+ { .blue = 0x00, .green = 0xff, .red = 0x00, .alpha = 0x00 },
+ { .blue = 0xff, .green = 0x00, .red = 0x00, .alpha = 0x00 },
+ { .blue = 0x00, .green = 0x00, .red = 0x00, .alpha = 0xff },
+ },
+ /* 32bit ABGR */
+ {
+ { .blue = 0x00, .green = 0x00, .red = 0x00, .alpha = 0xff },
+ { .blue = 0x00, .green = 0x00, .red = 0xff, .alpha = 0x00 },
+ { .blue = 0x00, .green = 0xff, .red = 0x00, .alpha = 0x00 },
+ { .blue = 0xff, .green = 0x00, .red = 0x00, .alpha = 0x00 },
},
};
@@ -168,13 +168,11 @@ int read_bmp_file(const char* filename,
return ret;
}
-static inline void set_rgb_union(struct uint8_rgb *dst, union rgb_union src)
-{
- dst->red = src.red;
- dst->green = src.green;
- dst->blue = src.blue;
- dst->alpha = 0xff;
-}
+enum color_order {
+ /* only used for different types of 32bpp images */
+ BGRA, /* should be most common */
+ ABGR /* generated by some GIMP versions */
+};
struct bmp_args {
int fd;
@@ -182,6 +180,7 @@ struct bmp_args {
short read_width;
short width;
short depth;
+ enum color_order order;
unsigned char buf[BM_MAX_WIDTH * 4];
struct uint8_rgb *palette;
#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)
const int padded_width = ba->padded_width;
const int read_width = ba->read_width;
const int width = ba->width;
- const int depth = ba->depth;
+ int depth = ba->depth;
#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
defined(HAVE_BMP_SCALING) || defined(PLUGIN)
int cur_row = ba->cur_row;
@@ -250,6 +249,11 @@ static unsigned int read_part_line(struct bmp_args *ba)
if (depth == 32 && ba->first_alpha_byte == 0x80)
ba->first_alpha_byte = ibuf[3] ? 0xff : 0x0;
+ /* select different color orders within the switch-case to avoid
+ * nested if/switch */
+ if (depth == 32)
+ depth += ba->order;
+
while (ibuf < ba->buf + (BM_MAX_WIDTH << 2))
{
switch (depth)
@@ -302,7 +306,7 @@ static unsigned int read_part_line(struct bmp_args *ba)
buf->alpha = 0xff;
buf++;
break;
- case 32:
+ case 32 + BGRA:
buf->blue = *ibuf++;
buf->green = *ibuf++;
buf->red = *ibuf++;
@@ -310,6 +314,14 @@ static unsigned int read_part_line(struct bmp_args *ba)
ba->alpha_detected |= (buf->alpha != ba->first_alpha_byte);
buf++;
break;
+ case 32 + ABGR:
+ buf->alpha = *ibuf++;
+ buf->blue = *ibuf++;
+ buf->green = *ibuf++;
+ buf->red = *ibuf++;
+ ba->alpha_detected |= (buf->alpha != ba->first_alpha_byte);
+ buf++;
+ break;
}
}
#if !defined(HAVE_LCD_COLOR) && \
@@ -365,14 +377,11 @@ static struct img_part *store_part_bmp(void *args)
}
#endif
-static inline int rgbcmp(struct uint8_rgb rgb1, struct uint8_rgb rgb2)
+static inline int rgbcmp(const struct uint8_rgb *rgb1, const struct uint8_rgb *rgb2)
{
- if ((rgb1.red == rgb2.red) && (rgb1.green == rgb2.green) &&
- (rgb1.blue == rgb2.blue))
- return 0;
- else
- return 1;
+ return memcmp(rgb1, rgb2, sizeof(struct uint8_rgb));
}
+
#if LCD_DEPTH > 1
#if !defined(PLUGIN) && !defined(HAVE_JPEG) && !defined(HAVE_BMP_SCALING)
static inline
@@ -504,6 +513,7 @@ int read_bmp_fd(int fd,
int ret;
bool return_size = format & FORMAT_RETURN_SIZE;
bool read_alpha = format & FORMAT_TRANSPARENT;
+ enum color_order order = BGRA;
unsigned char *bitmap = bm->data;
struct uint8_rgb palette[256];
@@ -668,19 +678,27 @@ int read_bmp_fd(int fd,
numcolors = letoh32(bmph.clr_used);
if (numcolors == 0)
numcolors = BIT_N(depth);
- } else
- numcolors = (compression == 3) ? 3 : 0;
+ } else {
+ int hdr_size = letoh32(bmph.struct_size);
+ numcolors = 0;
+ if (compression == 3) {
+ if (hdr_size >= 56)
+ numcolors = 4;
+ else /* hdr_size == 52 */
+ numcolors = 3;
+ }
+ }
+ /* read color tables. for BI_BITFIELDS this actually
+ * reads the color masks */
if (numcolors > 0 && numcolors <= 256) {
int i;
- union rgb_union pal;
for (i = 0; i < numcolors; i++) {
- if (read(fd, &pal, sizeof(pal)) != (int)sizeof(pal))
- {
+ if (read(fd, &palette[i], sizeof(struct uint8_rgb))
+ != (int)sizeof(struct uint8_rgb)) {
DEBUGF("read_bmp_fd: Can't read color palette\n");
return -7;
}
- set_rgb_union(&palette[i], pal);
}
}
@@ -705,8 +723,9 @@ int read_bmp_fd(int fd,
/* (i == 0) is 15bit, (i == 1) is 16bit, (i == 2) is 32bit */
for (i = 0; i < ARRAY_SIZE(bitfields); i++) {
- for (j = 0; j < ARRAY_SIZE(bitfields[0]); j++) {
- if (!rgbcmp(palette[j], bitfields[i][j])) {
+ /* for 15bpp and higher numcolors has the number of color masks */
+ for (j = 0; j < numcolors; j++) {
+ if (!rgbcmp(&palette[j], &bitfields[i][j])) {
found = true;
} else {
found = false;
@@ -716,6 +735,8 @@ int read_bmp_fd(int fd,
if (found) {
if (i == 0) /* 15bit */
depth = 15;
+ else if (i == 3) /* 32bit, ABGR bitmap */
+ order = ABGR;
break;
}
}
@@ -752,6 +773,7 @@ int read_bmp_fd(int fd,
.cur_row = 0, .cur_col = 0, .part = {0,0},
#endif
.alpha_detected = false, .first_alpha_byte = 0x80,
+ .order = order,
};
#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 @@
#define BM_MAX_WIDTH (((LCD_WIDTH) + 7) & ~7)
struct uint8_rgb {
+ /* Little endian */
uint8_t blue;
uint8_t green;
uint8_t red;