嵌入式Linux下真彩Logo的实现

目前嵌入式产品越来越多了,一般都能带Logo显示启动的。让我们来看看Logo显示是怎么做的(我仅仅做Linux方面的,没有做过WinCE的)。

参考一些嵌入式平台的做法,基本是fb_prepare_logo(struct fb_info *info, int rotate)、fb_show_logo(struct fb_info *info, int rotate)两个函数实现的。但是该两个函数其实没有参考的价值。最简单的做法就是调用该两个函数。
1. 在 xxx__probe(struct platform_device *dev) 函数 return 0 之前调用
#if defined(CONFIG_LOGO)
 // 原来代码先检查info->fbcon_par->rotate是否为FB_ROTATE_UR,这里直接设置FB_ROTATE_UR
 if (fb_prepare_logo(info, FB_ROTATE_UR))
 {
  /* Start display and show logo on boot */
  /* fb_set_cmap(info->cmap, info); */
  /* Show the logo */
  fb_show_logo(info, FB_ROTATE_UR);
 }
#endif
注意:struct fb_info *info = framebuffer_alloc(...);

2. 在编译内核时选择 Boot logo, Logo_clut224
3. 制作ppm格式logo文件
首先使用 Photoshop 制作 png 文件(Windows下)
再将png图片转成pnm(下面步骤为linux下,我使用CentOS 4.7,使用root权限用户)
# pngtopnm uclinux_logo.png > uclinux_logo.pnm
然后将pnm图片的颜色数限制在224
# pnmquant 224 uclinux_logo.pnm > logo_linux_clut224.pnm
最后将pnm图片转换成我们需要的ppm
# pnmtoplainpnm logo_linux_clut224.pnm > logo_linux_clut224.ppm
将 logo_linux_clut224.ppm 替换 linux-2.6/drivers/video/logo 中对应的图像
我在这里制作的文件是与分辨率同样大小的文件,如果小于分辨率的话,应该显示在左上角。

说实话,上面步骤制作的Logo最多为224色图片效果。能不能显示真彩的Logo呢?实际上肯定是可以的。
我的实现方法:制作自己的fb_prepare_logo、fb_show_logo函数,将真彩的颜色值直接写到Frame Buffer的内存中。

1. 将分辨率和颜色位数定义放到头文件中 truecolor_logo.h
我的定义为
#define XRES 800 /* The pixel width of the LCD */
#define YRES 480 /* The pixel height of the LCD */
#define BPX  32  /* The bits depth of the LCD */

2. 增加一个 truecolor_logo.c 文件,将该文件加入到内核中,该文件实现
int fb_prepare_truecolor_logo(void)、void fb_show_truecolor_logo(struct fb_info *info) 两个函数
static struct TrueColor
{
    int Width, Height;
    int ColorBytes;
    const char *BitData;
} _true_color_logo;
static unsigned char truecolor_logo_data[] = { ... }; 读取图片的颜色值赋值到这里
int fb_prepare_truecolor_logo(void)
{
 _true_color_logo.ColorBytes = BPX/8;
 _true_color_logo.Width = 351; /* 这里要与truecolor_logo_data的长度相对应 */
 _true_color_logo.Height = 137;
 _true_color_logo.BitData = truecolor_logo_data;
 printk("fb_prepare_truecolor_logo ok \n");
 return (_true_color_logo.ColorBytes > 1); /* 仅仅支持 16 位色或者更高位色 */
}

void fb_show_truecolor_logo(struct fb_info *info)
{
 char *framebase = info->screen_base;
 int m, n;
 int startx, starty;

 startx = (XRES- _true_color_logo.Width)/ 2;
 if(startx < 0) startx = 0;
 starty = (YRES- _true_color_logo.Height)/ 2;
 if(starty < 0) starty = 0;

 for(m=0; m<YRES; m++)
 {
  /* 设置图片之外(上、下部)是背景色为黑色 */
  if((m < starty) || (m >= _true_color_logo.Height+starty))
  {
   memset(framebase+ (m* XRES* _true_color_logo.ColorBytes), 0, XRES* _true_color_logo.ColorBytes);
  }
  else
  {
   /* 设置图片之外(左边)是背景色为黑色 */
   memset(framebase+ ((m* XRES)* _true_color_logo.ColorBytes), 0, _true_color_logo.ColorBytes* startx);

   /* 将 Logo 显示在中间, 图片上下需要翻转 */
   memcpy(framebase+ ((m* XRES+ startx)* _true_color_logo.ColorBytes),
    // (_true_color_logo.BitData+ ((m-starty)* _true_color_logo.Width)* _true_color_logo.ColorBytes),
    (_true_color_logo.BitData+ ((_true_color_logo.Height-(m-starty)-1)* _true_color_logo.Width)* _true_color_logo.ColorBytes),
    _true_color_logo.ColorBytes* _true_color_logo.Width);

   /* 设置图片之外(右边)是背景色为黑色 */
   memset(framebase+ ((m* XRES+ startx+ _true_color_logo.Width)* _true_color_logo.ColorBytes), 0,
    _true_color_logo.ColorBytes*(XRES- startx- _true_color_logo.Width));
  }
 }
}

 

3. 修改 xxx__probe(struct platform_device *dev) 函数
#if defined(SHOW_TRUECOLOR_LOGO)
 
 if(fb_prepare_truecolor_logo())

  fb_show_truecolor_logo(info);

#elif defined(CONFIG_LOGO)
 if (fb_prepare_logo(info, FB_ROTATE_UR))
 {
  /* Start display and show logo on boot */
  /* fb_set_cmap(info->cmap, info); */ /* Cancel the code */
  /* Show the logo */
  fb_show_logo(info, FB_ROTATE_UR);
 }
#endif

相关推荐