Generally, to improve the user experience, after the LCD Initialization is completed in the system startup phase, the first screen is displayed quickly to avoid the black screen taking too long and causing the user to think that the system is running slowly, all electronic products are designed in this way. This screen is often used to display the product logo. In Android, there are two ways to print the logo. The first step is to copy a PPM image to FB after the device is initialized in the kernel. The second step is in the android boot phase, decompress an image in RLE format to FB.
First, the logo is displayed in the kernel. The logo displayed by the kernel uses an image in the PPM format. Ppm is a simple Linux image format that only contains information and image data such as format, image width and height, and bit number. The storage format of image data can be ascii or binary. The following lists a relatively simple one in the PPM format (24-bit color, binary saved images ):
File Header part --
P6 \ n
Width height \ n
255 \ n
Pixel part --
Rgbrgb...
P6 indicates the format of PPM. \ n indicates the line break. width and height indicate the width and height of the image, separated by spaces. 255 indicates the maximum value of each color component. RGB data is from top to bottom, discharge from left to right.
We can see from the PPM image format that this is an uncompressed image format. The advantage of using the logo is that the decoding time is reduced, and the screen can be displayed quickly. The disadvantage is that some images may be too large in size. If there are no extreme requirements, we can take some discounts to solve these problems. For example, we can compress the image during compilation and then package it into the image, then extract the image and display it in the running stage. When the compression algorithm is not very complex, the display speed should be acceptable. For example, convert an image into a raw data format, compress it into a GZ package, and package it into the root. After the FB Initialization is complete, decompress the GZ package directly to the display buffer (using the gunzip interface ). The decompression interface is as follows:
/*fileName: logo image file nameframeBuffer: display buffer*/int draw_logo(char* fileName, void* frameBuffer){int fd;char *input;struct stat st;fd =sys_open(fileName,O_RDONLY, 0);if (fd < 0){return -1;}sys_newfstat(fd, &st);len = st.st_size;input = vmalloc(st.st_size);if (!input) {return -1;}sys_read(fd, input, st.st_size);gunzip(input, st.st_size, NULL, NULL, frameBuffer, NULL, NULL);vfree(input);sys_close(fd);load_565rle_imagereturn 0;}
The following describes the android logo display. Android starts with system/CORE/init. C. The startup process is well written in many articles. I will not go into details here. I will only talk about how the logo display function is called:
Main (in system/CORE/init. c) --> lele_init_action (in system/CORE/init. c) --> load_565rle_image (located in system/CORE/init/logo. c ).
Load_565rle_image is used to print the RLE Format Image to FB. Let's talk about the RLE data format first. Rle is a lossless data compression format. during compression, the continuous data content and length are calculated. A simple example shows that aaabbbccc can be compressed to 3a3b3c, in this way, data with a length of 9 bytes is compressed to 6 bytes. The advantage of this compression method is that it can save disk space without damaging the image. The disadvantage is that if you encounter an discontinuous data segment, the data size will increase. For example, abcabcabc is compressed into 1a1b1c1a1b1c1a1b1c, so that the original data of 9bytes is changed to 18 bytes. After learning about the RLE compression format, let's take a look at the load_565rle_image code to make it easier:
/* 565rle image format: [count (2 bytes), RLE (2 bytes)] */INT load_565rle_image (char * fN) {struct FB; struct stat S; unsigned short * data, * bits, * PTR; unsigned count, Max; int FD; If (vt_set_mode (1) Return-1; FD = open (FN, o_rdonly ); // open the RLE image file 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); // map image data to the memory. data points to the first address of the memory if (Data = map_failed) goto fail_close_file; if (fb_open (& FB) // open the FB device goto fail_unmap_data; max = fb_width (& FB) * fb_height (& FB); PTR = data; Count = S. st_size; bits = FB. BITs; while (count> 3) {unsigned n = PTR [0]; If (n> MAX) break; android_memset16 (bits, PTR [1], n <1 ); // decodes RLE data to the display buffer bits + = N; max-= N; PTR + = 2; count-= 4;} 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 ;}
The load_565rle_image function does not seem to be a problem, but it is actually a risk. When the kernel is started and the RGB value of FB is set to 565, no problem is displayed. However, if it is set to another format by default, a screen is displayed. Therefore, it is safer to modify the fb_open function and use the ioctl interface to set FB. Modify fb_open as follows:
static int fb_open(struct FB *fb){ fb->fd = open("/dev/graphics/fb0", O_RDWR); if (fb->fd < 0) return -1; if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0) goto fail; if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0) goto fail; fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0); /* add by Lynn, reset fb format */ fb->vi.bits_per_pixel = 16; fb->vi.yres_virtual=fb->vi.yres*2; fb->vi.red.offset = 11; fb->vi.red.length = 5; fb->vi.green.offset = 5; fb->vi.green.length = 6; fb->vi.blue.offset = 0; fb->vi.blue.length = 5; fb->vi.transp.offset = 0; fb->vi.transp.length = 0; fb->vi.nonstd =4; fb->vi.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; if(ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi) < 0) { ERROR("Put screen info failed !!!"); goto fail; } /* end add */ if (fb->bits == MAP_FAILED) goto fail; return 0;fail: close(fb->fd); return -1;}
The above modification ensures that the logo in Android is displayed normally no matter how the kernel sets FB.
By analyzing the code and format, we can select the appropriate logo display mode based on the needs of our products.