[Android] Boot Animation 開機動畫

Android系統開機動畫包括三部分:

bootloader部份

bootloader

bootloader在開機階段會show一個小機器人的圖片

fastboot/main.c
BootMenuImagesLOGO[0] = (Icon *)&s_logo;
BootMenu_LOGO = FastbootCreateRadioMenu(1, 0, 3,

   NVIDIA_GREEN, BootMenuImagesLOGO);
FastbootDrawRadioMenu(&s_Frontbuffer, s_FrontbufferPixels, BootMenu_LOGO);


fastboot/logo_h
#ifndef logo_h
#define logo_h
typedef struct _logo {
    NvU16 width;
    NvU16 height;
    NvS32 stride;
    NvU8 bpp;
    NvU32 data[65536];
} logo_t;

static const logo_t s_logo = {
    256,
    256,
    768,
    24,
    {
        0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
         0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,

          ...
          0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
         0x000000, 0x000000, 0x000000, 0x000000,
    }
};

const logo_t *logo = &s_logo;

#endif


看source code,可以得知他是把bmp當成raw data儲存。
但是我找不到合適的轉檔程式,於是我自己寫了一隻,有些bug,只能輸入正方形的圖,而且因為little-endian之類的問題,輸入的圖會顛倒,但是我懶得修了:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define DIGISIZE 6
#define HEADERSIZE 28

int main(int argc, const char *argv[])
{
   int fd_in, fd_out;
   int k=0, i=0, j=0, ret;
   unsigned char result[2*DIGISIZE+4];
   unsigned char d1, d2;
   unsigned char header[HEADERSIZE];
   unsigned int filesize = 0, offset = 0, heigh = 0, width = 0, datasize = 0;
   unsigned char *data;
   char *header_name;
   char *tmp_name;
   char *delim=".";

   tmp_name = malloc(sizeof(argv[2])+1);
   memcpy(tmp_name, argv[2], sizeof(argv[2])+1);
   header_name = strtok(tmp_name, delim);

   fd_in = open(argv[1], O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
   fd_out = open(argv[2], O_RDWR| O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
   //fd_in = fopen(argv[1], "wb+");
   //fd_out = fopen(header_name, "wb+");

   ret = read(fd_in, header, HEADERSIZE);
   filesize = header[2] + (header[3] << 8) + (header[4] << 16) + (header[5] << 24);
   offset = header[10] + (header[11] << 8) + (header[12] << 16) + (header[13] << 24);
   width = header[18] + (header[19] << 8) + (header[20] << 16) + (header[21] << 24);
   heigh = header[22] + (header[23] << 8) + (header[24] << 16) + (header[25] << 24);
   datasize = filesize - offset;
   
   printf("\n===========\nfilename: %s\n", header_name);
   printf("filesize: %d\n", filesize);
   printf("offset: %d\n", offset);
   printf("datasize: %d\n", datasize);
   printf("width: %d\n", width);
   printf("heigh: %d\n", heigh);

   char buf1[2048];
   sprintf(buf1, "#ifndef %s_h\n#define %s_h\ntypedef struct _%s\n{\n    NvU16 width;\n    NvU16 height;\n    NvS32 stride;\n    NvU8  bpp;\n    NvU32 data[ %d ];\n} %s_t;\n\nstatic const %s_t s_%s = \n{\n", header_name, header_name, header_name, filesize, header_name, header_name, header_name);

   char buf2[1024];
   sprintf(buf2,"    %d,\n    %d,\n    %d,\n    24,\n    {\n", width, heigh, width*3);

   write(fd_out, buf1, strlen(buf1));
   lseek(fd_out, 0, SEEK_END);
   write(fd_out, buf2, strlen(buf2));
   lseek(fd_out, 0, SEEK_END);

   result[0]='0';
   result[1]='x';
   result[DIGISIZE+2]=',';
   result[DIGISIZE+3]=' ';

   data = (unsigned char *) malloc(datasize+1);
   lseek(fd_in, offset, SEEK_SET);
   read(fd_in, data, datasize);
   data[datasize]='\0';

   for (i = 1; i <= datasize; i++) {
       //while(ret = read(fd_in, buf1, DIGISIZE)) {
       //for (j = 0; j < DIGISIZE; j++) {
       d1 = (*(data + datasize - i)) / 0x10;
       d2 = (*(data + datasize - i)) % 0x10;
       if(d1<0xa){
           d1 += 0x30;
       }else{
           d1 += 0x57;
       }
       if(d2<0xa){
           d2 += 0x30;
       }else{
           d2 += 0x57;
       }
       result[j+2]=d1;
       result[j+3]=d2;
       //}
       j+=2;
       if(j==6){
           write(fd_out, result, DIGISIZE+4);
           j=0;
       }
       k++;
       if(!(k%18))
           write(fd_out, "\n", 1);
   }

   char buf3[1024];
   sprintf(buf3,"\n    }\n};\n\nconst %s_t *%s = &s_%s;\n\n#endif\n", header_name, header_name, header_name);
   lseek(fd_out, 0, SEEK_END);
   write(fd_out, buf3, strlen(buf3));

   free(data);
   close(fd_in);
   close(fd_out);
   return 0;
}


android system部份

ANDROID文字

RLE製作方法一

#使用ubuntu ImageMagick自帶的convert命令,進行raw格式轉換 (註:好像只支持png-24,其他格式生成的rle文件顯示不正常,有興趣大家可以再驗證一下。)
convert -depth 8 logo.png rgb:logo.raw

android自帶的rgb2565工具,對raw文件進行rle565格式轉換
$(SRC_HOME)/out/host/linux-x86/bin/l

刪除中間文件
rm -f logo.raw logo.png

然後將initlogo.rle拷貝到android系統根目錄,也就是root目錄底下
cp initlogo.rle system/core/rootdir/

system/core/init/init.h
 184    #define INIT_IMAGE_FILE "/initlogo.rle"

system/core/init/init.c
 901     if( load_565rle_image(INIT_IMAGE_FILE) ) {

system/core/rootdir/Android.mk 
#++ Vincent
    PRODUCT_COPY_FILES += \
    $(LOCAL_PATH)/initlogo.rle:/root/initlogo.rle
#-- Vincent

RLE製作方法二

1. sudo apt-get install netpbm
2. create a new splash.png file (using gimp or whatever)
3. convert it to "pnm" by using "pngtopnm" as in 
    pngtopnm splash.png > splash.pnm
4. convert it to "rle" by using "ppmtolss16" as in
    ppmtolss16 "#000000=0" "#ffffff=7" < splash.pnm > splash.rle

ANDROID閃爍動畫

android預設
frameworks/base/core/res/assets/images/android-logo-mask.png

自製動畫檔
frameworks/base/cmds/bootanimation/bootanimation.zip

我們可以使用任意的文字編輯器來打開該 desc.txt 檔,打開後其內容為:
320 480 15
p 1 30 eris
p 1 0 peeking
設定檔中第一行說明了即將使用 320x480 大小的圖檔,並以每秒鐘顯示一個 圖檔的方式(fps)來播放動畫。
第二行到第六行都是由 p 帶頭,它們代表 即將播放的規則:
p之後的第一個數字代表播放次數,如果該數字為 0,即代表 不限次數的播放;
第二個數字代表播放後所需要暫停(pause)的時間,以第二行的 30 為例,由於每秒播放 15 個 frame(圖檔),所以暫停約兩秒;
最後一個代表撥放的圖檔目錄名稱。

請在"壓縮方式"的下拉式選單中選取"僅儲存",否則產生的 bootanimation.zip 是無法正常顯示動畫的。
zip -r -Z store bootanimation.zip ./*

Reference

http://www.xn--yeto30a.com/?p=302
http://www.cnmsdn.com/html/201005/1274840322ID5052.html
http://anemospring.blogspot.com/2010/11/kernel-uboot-logo.html
http://web.nchu.edu.tw/~jlu/cyut/android/animation.shtml

留言

這個網誌中的熱門文章

Mac起步:常用軟體及設定

台灣可用線上音樂串流網站

醍醐味