Init进程中Logo显示支持RGB888格式

       在Init进程中(system/core/init),有一个功能,显示一个开机画面,在system/core/init/init.c中console_init_action()函数中。

#if !defined(BOOT_ANIMATION)

   if( load_565rle_image(INIT_IMAGE_FILE) ){

       fd = open("/dev/tty0", O_WRONLY);

       if (fd >= 0) {

           const char *msg;

                msg = "\n"

           "\n"

           "\n"

           "\n"

           "\n"

           "\n"

           "\n"  // console is 40cols x 30 lines

           "\n"

           "\n"

           "\n"

           "\n"

           "\n"

           "\n"

           "\n"

           "             A N D R O I D";

           write(fd, msg, strlen(msg));

           close(fd);

       }

    }

#endif

 

load_565rle_image()支持RGB888的LCD

       简单来讲就是Load一个RLE-565格式的文件,然后拷贝到Framebuffer中显示。load_565rle_image()在同logo.c中实现。看了一下当前的实现,比较老,居然不支持RGB888格式的LCD,如果是RGB888的LCD,在Framebuffer中是24bpp的,但按照16bpp送到Framebuffer的话,会显示成四个只有四分之一大小的LOGO。

 

       为了支持RGB888正常显示,需要修改一下,当LCD为24bpp时,把每个像素的值扩展成32bit( 还有8bit为Alpha通道)。修改文件system/core/init/logo.c

--- a/system/core/init/logo.c

+++ b/system/core/init/logo.c

@@ -38,6 +38,15 @@ static void android_memset16(void *_ptr, unsignedshort val, unsigned count)

    while(count--)

        *ptr++ = val;

 }

+

+typedef unsigned intuint32_t;

+static voidandroid_memset32(uint32_t* dst, uint32_t value, size_t size)

+{

+    size >>= 2;

+    while (size--) {

+        *dst++ = value;

+    }

+}

 #endif

 

 struct FB {

@@ -50,7 +59,9 @@ struct FB {

 

 #define fb_width(fb) ((fb)->vi.xres)

 #define fb_height(fb) ((fb)->vi.yres)

-#define fb_size(fb)((fb)->vi.xres * (fb)->vi.yres * 2)

+#define fb_bpp(fb)((fb)->vi.bits_per_pixel)

+#define fb_size(fb)((fb)->vi.xres * (fb)->vi.yres * \

+       ((fb)->vi.bits_per_pixel/8))

 

 static int fb_open(struct FB *fb)

 {

@@ -108,6 +119,7 @@ intload_565rle_image(char *fn)

    struct FB fb;

    struct stat s;

    unsigned short *data, *bits, *ptr;

+    uint32_t rgb32, red, green, blue, alpha;

    unsigned count, max;

    int fd;

 

@@ -139,8 +151,24 @@ intload_565rle_image(char *fn)

         unsigned n = ptr[0];

        if (n > max)

            break;

-        android_memset16(bits, ptr[1], n<< 1);

-        bits += n;

+        if (fb_bpp(&fb) == 16) {

+            android_memset16(bits, ptr[1], n<< 1);

+            bits += n;

+        }else {

+            /* convert 16 bits to 32 bits */

+            red = ((ptr[1] >> 11) &0x1F);

+            red = (red << 3) | (red>> 2);

+            green = ((ptr[1] >> 5) &0x3F);

+            green = (green << 2) | (green>> 4);

+            blue = ((ptr[1]) & 0x1F);

+            blue = (blue << 3) | (blue>> 2);

+            alpha = 0xff;

+            rgb32 = (alpha << 24) | (red<< 16)

+                    | (green << 8) |(blue << 0);

+            android_memset32((uint32_t *)bits,rgb32, n << 2);

+            bits += (n * 2);

+        }

+

        max -= n;

        ptr += 2;

        count -= 4;

 

       这样就可以在RGB888的LCD上正常显示Logo了,但这只要把RGB565的图扩展成RGB888显示,并不是真正的RGB888的图。如果图形中有一些过渡色的话,就会比较容易出现色阶现象。

 

增加load_888rle_­image()函数

       为了能够真正支持24bpp的图,需要实现加载24bppRLE格式图像的功能,RLE属于游程编码,格式是颜色值+连续点数。自己扩展一下RLE-565的格式,把它变成RLE-888的格式。实现的函数如下:

+intload_888rle_image(char *fn)

+{

+    struct FB fb;

+    struct stat s;

+    int fd, count, err = 0;

+    unsigned max;

+    uint32_t rgb32, red, green, blue, alpha;

+    unsigned short *data, *ptr, *bits, rgb16;

+

+    NOTICE("%s: load_888rle_imagefilename: %s\n",

+                       __func__, fn);

+

+    if (vt_set_mode(1))

+        return -1;

+

+    fd = open(fn, O_RDONLY);

+    if (fd < 0) {

+        ERROR("cannot open '%s'\n",fn);

+        goto fail_restore_text;

+    }

+

+    if (fstat(fd, &s) < 0) {

+        goto fail_close_file;

+    }

+

+    data = mmap(0, s.st_size, PROT_READ,MAP_SHARED, fd, 0);

+    if (data == MAP_FAILED)

+        goto fail_close_file;

+

+    if (fb_open(&fb))

+        goto fail_unmap_data;

+

+    max = fb_width(&fb) *fb_height(&fb);

+    ptr = data;

+    count = s.st_size;

+    bits = fb.bits;

+       NOTICE("load_888rle_image %d x %d @%d\n",

+                       fb_width(&fb),fb_height(&fb),fb_bpp(&fb));

+

+    while (count > 7) {

+        unsigned n = ptr[0];

+        if (n > max)

+            break;

+        red = blue = (ptr[1] & 0xFF);

+        green = ((ptr[1] >> 8) &0xFF);

+        red = ((ptr[3] >> 8) & 0xFF);

+        if (fb_bpp(&fb) == 16) {

+            /* convert 32 bits to 16 bits */

+            rgb16 = ((((red) >> 3)<< 11) | (((green) >> 2) << 5) | ((blue) >> 3));

+            android_memset16(bits, rgb16, n<< 1);

+            bits += n;

+        } else {

+            alpha = 0x0;

+            rgb32 = (alpha << 24) | (red<< 16) | (green << 8) | (blue << 0);

+            android_memset32((uint32_t *)bits,rgb32, n << 2);

+            bits += (n * 2);

+        }

+

+        max -= n;

+        ptr += 4;

+        count -= 8;

+    }

+    munmap(data, s.st_size);

+    fb_update(&fb);

+    fb_close(&fb);

+    close(fd);

+    unlink(fn);

+       return 0;

+

+fail_unmap_data:

+    munmap(data, s.st_size);   

+fail_close_file:

+    close(fd);

+fail_restore_text:

+    vt_set_mode(0);

+    return -1;

+}

 

rgb2888的小工具

当然还需要实现rgb2888的小工具来转换原始图像为RLE-888格式。参考to565的实现,自己写一个to888。to565位于build/tools/rgb2565下。

 

       转换函数实现示例如下

void to_888_rle(int maxcount)

{

   unsigned char in[3], c1[3];

   unsigned short last, color, count;

    unsignedtotal = 0;

   int subtotal = 0;

   count = 0;

 

   while(read(0, in, 3) == 3) {

       subtotal ++;

       if ( (maxcount != -1) && (subtotal > maxcount ) )

           break;

       color = to565(in[0],in[1],in[2]);

       if (count) {

            if(((in[0]==in[2])||(color==0xffff)||(!color)) && (color == last)&& (count != 65535)) {

                count++;

                continue;

           } else {

                write(1, &count, 2);

                write(1, &c1[0], 1);

                write(1, &c1[1], 1);

                write(1, &count, 2);

                write(1, &c1[2], 1);

                write(1, &c1[2], 1);

                total += count;

           }

       }

       last = color;

       memcpy(c1,in,3);

       count = 1;

    }

   if (count) {

       write(1, &count, 2);

        write(1, &c1[0], 1);

       write(1, &c1[1], 1);

       write(1, &count, 2);

       write(1, &c1[2], 1);

       write(1, &c1[2], 1);

       total += count;

    }

   fprintf(stderr,"%d pixels\n",total);

}

 

       编译生成小工具Makefile

include$(CLEAR_VARS)

 

LOCAL_SRC_FILES:= to888.c

 

LOCAL_CFLAGS +=-O2 -Wall -Wno-unused-parameter

LOCAL_MODULE :=rgb2888

 

include$(BUILD_HOST_EXECUTABLE)

 

       用法和rgb2565相同,示例如下:

       convert-depth 8 foo.png rgb:foo.raw

       rgb2888  -rle < foo.raw > foo.rle

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值