[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