Support GIMP bmp files.

Change-Id: I7380ceeaf696b67e1641d24e7b932e3d74770932
This commit is contained in:
Thomas Martitz 2013-12-21 17:12:21 +01:00
parent 21ff83295e
commit ef92ed4a6a
2 changed files with 67 additions and 44 deletions

View file

@ -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)) && \

View file

@ -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;