Support GIMP bmp files.
Change-Id: I7380ceeaf696b67e1641d24e7b932e3d74770932
This commit is contained in:
parent
21ff83295e
commit
ef92ed4a6a
2 changed files with 67 additions and 44 deletions
|
@ -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)) && \
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue