[U-Boot] [PATCH 6/7] lcd: Implement RLE8 bitmap decoding
Che-liang Chiou
clchiou at chromium.org
Mon Oct 1 19:01:09 CEST 2012
Acked-by: Che-Liang Chiou <clchiou at chromium.org>
On Fri, Sep 28, 2012 at 6:11 PM, Simon Glass <sjg at chromium.org> wrote:
> From: Tom Wai-Hong Tam <waihong at google.com>
>
> Add support for drawing compressed RLE8 bitmaps.
>
> Reference: http://www.digicamsoft.com/bmp/bmp.html
>
> Signed-off-by: Che-Liang Chiou <clchiou at chromium.org>
> Signed-off-by: Tom Wai-Hong Tam <waihong at chromium.org>
> Signed-off-by: Simon Glass <sjg at 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
>
More information about the U-Boot
mailing list