转自 http://qiushao.net/2015/12/20/replace_android_recovery_picture/
替换recovery动画图片
最近在做一个项目是android 系统各部分动画的定制,有一个模块是recovery界面的定制,包括用户升级,重置系统时的动画效果修改。与recovery相关的代码在android4.4/bootable/recovery
目录下。
我大概看了一下与界面相关的代码,觉得应该只是替换几张图片,修改一下参数而已,没啥工作量,所以也就不细看具体实现了。但当美工把图交给我后,我把图片替换后,发现美工给的彩色的图片变成灰度图的效果了,而且图片被拉伸,显示不全。这咋回事啊,问同事,百度,google 一圈之后,也找不到原因。只能 read the fucking source code 了。
周末加班看了一下午的recovery代码,终于找到原因啦。原来是recovery的图片资源必须为png格式,且不能带alhpa通道信息
。真是个大坑。
相关代码在 android4.4/bootable/recovery/minui/resources.c
文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| int res_create_surface(const char* name, gr_surface* pSurface) { printf("qiushao: res_create_surface: /res/images/%s.png\n", name); ... int color_type = info_ptr->color_type; int bit_depth = info_ptr->bit_depth; int channels = info_ptr->channels; ... size_t width = info_ptr->width; size_t height = info_ptr->height; size_t stride = (color_type == PNG_COLOR_TYPE_GRAY ? 1 : 4) * width; size_t pixelSize = stride * height;
...
printf("qiushao: color_type = %d\n", color_type); printf("qiushao: bit_depth = %d\n", bit_depth); printf("qiushao: channels = %d\n", channels); printf("qiushao: width = %lu\n", width); printf("qiushao: height = %lu\n", height); printf("qiushao: stride = %lu\n", stride); printf("qiushao: alpha = %d\n", alpha); unsigned int y; if (channels == 3 || (channels == 1 && !alpha)) { printf("qiushao: channels == 3 || (channels == 1 && !alpha)\n"); for (y = 0; y < height; ++y) { unsigned char* pRow = pData + y * stride; png_read_row(png_ptr, pRow, NULL);
int x; for(x = width - 1; x >= 0; x--) { int sx = x * 3; int dx = x * 4; unsigned char r = pRow[sx]; unsigned char g = pRow[sx + 1]; unsigned char b = pRow[sx + 2]; unsigned char a = 0xff; pRow[dx ] = r; pRow[dx + 1] = g; pRow[dx + 2] = b; pRow[dx + 3] = a; } } } else { printf("qiushao: channels != 3 && (channels == 1 && !alpha)\n"); for (y = 0; y < height; ++y) { unsigned char* pRow = pData + y * stride; png_read_row(png_ptr, pRow, NULL); } }
*pSurface = (gr_surface) surface; ...
|
这个函数将图片文件的数据读取到内存,我在其中输出了一些调试信息,输出图片的 color_type, channels 等信息。查看LOG发现,android原生的图片 channels == 3,channels 即色彩通道个数,等于 3 的话,意味着只有 R,G,B 三个通道的信息,没有 ALPHA 通道信息!这段代码的逻辑是如果channels 不等于3, 则按channels = 1 来处理,即灰度图。
美工给的图片是带 alpha通道信息的,即channels = 4,被当成灰度图像来处理了,怪不得显示的效果是灰度图像。我一直以为 png 图像就只有一种格式,都是带有 alpha通道的。。。
使用图像处理工具(photoshop 或者 gimp),将美工给的图片去掉 alpha 通道信息,再替换recovery 的图片,编译,替换recovery.img ,reboot -r 。图片终于正常显示啦。