
Acked-by: Che-Liang Chiou clchiou@chromium.org
On Fri, Sep 28, 2012 at 6:11 PM, Simon Glass sjg@chromium.org wrote:
From: Tom Wai-Hong Tam waihong@google.com
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
README | 5 ++ common/lcd.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 0 deletions(-)
diff --git a/README b/README index 5793b0a..40899d9 100644 --- a/README +++ b/README @@ -1440,6 +1440,11 @@ The following options need to be configured: Normally display is black on white background; define 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
If this option is set, the environment is checked for
diff --git a/common/lcd.c b/common/lcd.c index 004a6be..68df6d0 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -642,6 +642,136 @@ static void splash_align_axis(int *axis, unsigned long panel_size, } #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) #define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++) #else @@ -679,6 +809,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) unsigned long width, height, byte_width; unsigned long pwidth = panel_info.vl_col; unsigned colors, bpix, bmp_bpix;
unsigned long compression; if (!bmp || !((bmp->header.signature[0] == 'B') && (bmp->header.signature[1] == 'M'))) {
@@ -691,6 +822,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) height = le32_to_cpu(bmp->header.height); bmp_bpix = le16_to_cpu(bmp->header.bit_count); colors = 1 << bmp_bpix;
compression = le32_to_cpu(bmp->header.compression); bpix = NBITS(panel_info.vl_bpix);
@@ -783,6 +915,18 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) switch (bmp_bpix) { case 1: /* pass through */ case 8: +#ifdef CONFIG_LCD_BMP_RLE8
if (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) byte_width = width; else
-- 1.7.7.3