先总结下常见的几种logo方案:
1、uboot logo 需要重新编译uboot
2、kernel logo 需要重新编译kernel
3、psplash 需要重新编译psplash
那有没有办法不编译源码,直接将logo图片放入目标板中就可以实现logo替换呢?
思路:
1、制作工具将jpg、bmp、png等格式的图片转换成rgb数据,生成的文件是可以直接通过cat、dd写入framebuffer中的
2、根据需要,在uboot/kernel/fs阶段将生成的raw文件写入到fb中
实现:
1、使用开源工具imagemagick
https://imagemagick.org/index.php
这里我是使用buildroot移植的,很方便
convert -gravity center -background black -extent 1280x800 emoji.bmp bgra:logo.raw
以上命令就可以将一个bmp格式的图片转换成rgb raw格式,大小为1280*800*32/4=409600 Byte,可以先cat logo.raw > /dev/fb0验证生成的文件显示是否正常。
imagemagick工具支持多种格式,还可以裁剪图片、填充背景色等,具体看官网说明,实测是可以支持png、bmp、jpg的。
2、将生成的raw写到fb0,我是放在了rootfs阶段显示,因为我的uboot与kernel启动速度很快,基本不影响logo显示时间。原理都一样,若想在boot、kernel阶段显示,修改下即可。
#include <stdio.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
int ret = -1;
unsigned char *p_fb_base;
int fd_fb;
int fd_image;
struct fb_var_screeninfo vinfo;
memset(&vinfo, 0, sizeof(vinfo));
/* 第1步:打开设备 */
fd_fb = open("/dev/fb0", O_RDWR);
if (fd_fb < 0)
{
perror("open");
return -1;
}
/* 第2步:获取设备的硬件信息,如屏幕分辨率,颜色位深等信息 */
ret = ioctl(fd_fb, FBIOGET_VSCREENINFO, &vinfo);
if (ret < 0)
{
perror("ioctl");
return -1;
}
/* 第3步:进行mmap,申请fb */
unsigned long fb_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
p_fb_base = (unsigned char *)mmap(NULL, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
if (NULL == p_fb_base)
{
perror("mmap");
return -1;
}
fd_image = open("/home/root/logo.raw",O_RDWR);
if (fd_image < 0)
{
perror("open");
return -1;
}
read(fd_image, p_fb_base, fb_size);
close(fd_image);
close(fd_fb);
return 0;
}