lcd: Implement RLE8 bitmap decoding
Add support for drawing compressed RLE8 bitmaps. Reference: http://www.digicamsoft.com/bmp/bmp.html Signed-off-by: Che-Liang Chiou <clchiou@chromium.org> Signed-off-by: Tom Wai-Hong Tam <waihong@chromium.org> Signed-off-by: Simon Glass <sjg@chromium.org> Acked-by: Che-Liang Chiou <clchiou@chromium.org> [agust: fix some minor style issues and build warnings] Signed-off-by: Anatolij Gustschin <agust@denx.de>
This commit is contained in:
parent
fecac46cf8
commit
45d7f52511
5
README
5
README
|
@ -1469,6 +1469,11 @@ CBFS (Coreboot Filesystem) support
|
||||||
Normally display is black on white background; define
|
Normally display is black on white background; define
|
||||||
CONFIG_SYS_WHITE_ON_BLACK to get it inverted.
|
CONFIG_SYS_WHITE_ON_BLACK to get it inverted.
|
||||||
|
|
||||||
|
CONFIG_LCD_BMP_RLE8
|
||||||
|
|
||||||
|
Support drawing of RLE8-compressed bitmaps on the LCD.
|
||||||
|
|
||||||
|
|
||||||
- Splash Screen Support: CONFIG_SPLASH_SCREEN
|
- Splash Screen Support: CONFIG_SPLASH_SCREEN
|
||||||
|
|
||||||
If this option is set, the environment is checked for
|
If this option is set, the environment is checked for
|
||||||
|
|
144
common/lcd.c
144
common/lcd.c
|
@ -642,6 +642,138 @@ static void splash_align_axis(int *axis, unsigned long panel_size,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_LCD_BMP_RLE8
|
||||||
|
|
||||||
|
#define BMP_RLE8_ESCAPE 0
|
||||||
|
#define BMP_RLE8_EOL 0
|
||||||
|
#define BMP_RLE8_EOBMP 1
|
||||||
|
#define BMP_RLE8_DELTA 2
|
||||||
|
|
||||||
|
static void draw_unencoded_bitmap(ushort **fbp, uchar *bmap, ushort *cmap,
|
||||||
|
int cnt)
|
||||||
|
{
|
||||||
|
while (cnt > 0) {
|
||||||
|
*(*fbp)++ = cmap[*bmap++];
|
||||||
|
cnt--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_encoded_bitmap(ushort **fbp, ushort c, int cnt)
|
||||||
|
{
|
||||||
|
ushort *fb = *fbp;
|
||||||
|
int cnt_8copy = cnt >> 3;
|
||||||
|
|
||||||
|
cnt -= cnt_8copy << 3;
|
||||||
|
while (cnt_8copy > 0) {
|
||||||
|
*fb++ = c;
|
||||||
|
*fb++ = c;
|
||||||
|
*fb++ = c;
|
||||||
|
*fb++ = c;
|
||||||
|
*fb++ = c;
|
||||||
|
*fb++ = c;
|
||||||
|
*fb++ = c;
|
||||||
|
*fb++ = c;
|
||||||
|
cnt_8copy--;
|
||||||
|
}
|
||||||
|
while (cnt > 0) {
|
||||||
|
*fb++ = c;
|
||||||
|
cnt--;
|
||||||
|
}
|
||||||
|
(*fbp) = fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not call this function directly, must be called from
|
||||||
|
* lcd_display_bitmap.
|
||||||
|
*/
|
||||||
|
static void lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb,
|
||||||
|
int x_off, int y_off)
|
||||||
|
{
|
||||||
|
uchar *bmap;
|
||||||
|
ulong width, height;
|
||||||
|
ulong cnt, runlen;
|
||||||
|
int x, y;
|
||||||
|
int decode = 1;
|
||||||
|
|
||||||
|
width = le32_to_cpu(bmp->header.width);
|
||||||
|
height = le32_to_cpu(bmp->header.height);
|
||||||
|
bmap = (uchar *)bmp + le32_to_cpu(bmp->header.data_offset);
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
y = height - 1;
|
||||||
|
|
||||||
|
while (decode) {
|
||||||
|
if (bmap[0] == BMP_RLE8_ESCAPE) {
|
||||||
|
switch (bmap[1]) {
|
||||||
|
case BMP_RLE8_EOL:
|
||||||
|
/* end of line */
|
||||||
|
bmap += 2;
|
||||||
|
x = 0;
|
||||||
|
y--;
|
||||||
|
/* 16bpix, 2-byte per pixel, width should *2 */
|
||||||
|
fb -= (width * 2 + lcd_line_length);
|
||||||
|
break;
|
||||||
|
case BMP_RLE8_EOBMP:
|
||||||
|
/* end of bitmap */
|
||||||
|
decode = 0;
|
||||||
|
break;
|
||||||
|
case BMP_RLE8_DELTA:
|
||||||
|
/* delta run */
|
||||||
|
x += bmap[2];
|
||||||
|
y -= bmap[3];
|
||||||
|
/* 16bpix, 2-byte per pixel, x should *2 */
|
||||||
|
fb = (uchar *) (lcd_base + (y + y_off - 1)
|
||||||
|
* lcd_line_length + (x + x_off) * 2);
|
||||||
|
bmap += 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* unencoded run */
|
||||||
|
runlen = bmap[1];
|
||||||
|
bmap += 2;
|
||||||
|
if (y < height) {
|
||||||
|
if (x < width) {
|
||||||
|
if (x + runlen > width)
|
||||||
|
cnt = width - x;
|
||||||
|
else
|
||||||
|
cnt = runlen;
|
||||||
|
draw_unencoded_bitmap(
|
||||||
|
(ushort **)&fb,
|
||||||
|
bmap, cmap, cnt);
|
||||||
|
}
|
||||||
|
x += runlen;
|
||||||
|
}
|
||||||
|
bmap += runlen;
|
||||||
|
if (runlen & 1)
|
||||||
|
bmap++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* encoded run */
|
||||||
|
if (y < height) {
|
||||||
|
runlen = bmap[0];
|
||||||
|
if (x < width) {
|
||||||
|
/* aggregate the same code */
|
||||||
|
while (bmap[0] == 0xff &&
|
||||||
|
bmap[2] != BMP_RLE8_ESCAPE &&
|
||||||
|
bmap[1] == bmap[3]) {
|
||||||
|
runlen += bmap[2];
|
||||||
|
bmap += 2;
|
||||||
|
}
|
||||||
|
if (x + runlen > width)
|
||||||
|
cnt = width - x;
|
||||||
|
else
|
||||||
|
cnt = runlen;
|
||||||
|
draw_encoded_bitmap((ushort **)&fb,
|
||||||
|
cmap[bmap[1]], cnt);
|
||||||
|
}
|
||||||
|
x += runlen;
|
||||||
|
}
|
||||||
|
bmap += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_MPC823) || defined(CONFIG_MCC200)
|
#if defined(CONFIG_MPC823) || defined(CONFIG_MCC200)
|
||||||
#define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++)
|
#define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++)
|
||||||
#else
|
#else
|
||||||
|
@ -781,6 +913,18 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
|
||||||
switch (bmp_bpix) {
|
switch (bmp_bpix) {
|
||||||
case 1: /* pass through */
|
case 1: /* pass through */
|
||||||
case 8:
|
case 8:
|
||||||
|
#ifdef CONFIG_LCD_BMP_RLE8
|
||||||
|
if (le32_to_cpu(bmp->header.compression) == BMP_BI_RLE8) {
|
||||||
|
if (bpix != 16) {
|
||||||
|
/* TODO implement render code for bpix != 16 */
|
||||||
|
printf("Error: only support 16 bpix");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
lcd_display_rle8_bitmap(bmp, cmap_base, fb, x, y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (bpix != 16)
|
if (bpix != 16)
|
||||||
byte_width = width;
|
byte_width = width;
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue