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