嵌入式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

4. 为了方便,最好是设计一个自动生成 truecolor_logo.c 文件的程序
源代码如下:
/*
 * Filename   : bmp2logo.c
 
 * Program    : Transform the 24 bits's BMP to 16, 24, 32 bits logo tools
 
 * Copyright  : Copyright (C) 2009~2020 XXX Co., LTD.

 * Author     : behard
 * Created at : 2009.01.09

 */
#include <stdio.h>
#include <stdlib.h>

typedef struct    /* 24 bit BMP color */
{
 unsigned char r;
 unsigned char g;
 unsigned char b;
} ColorBGR24BIT;

#define MAXROWTEXT  200

char strHead[][MAXROWTEXT] = {
 "/*/r/n",
 " * Filename   : linux/drivers/video/truecolor_logo.c/r/n",
 
 " * Program    : Show the logo with 16, 24, 32 bits color not 224 colors/r/n",

 " * Copyright  : Copyright (C) 2009~2020 XXX Co., LTD./r/n",
   
 " * Author     : behard/r/n",
   
 " * Created at : 2009.01.09/r/n",
   
 " *//r/n",
   
 "#include <linux/module.h>/r/n",
   
 "#include <linux/kernel.h>/r/n",
   
 "#include <linux/errno.h>/r/n",
   
 "#include <linux/string.h>/r/n",
   
 "#include <linux/mm.h>/r/n",
   
 "#include <linux/tty.h>/r/n",
   
 "#include <linux/slab.h>/r/n",
   
 "#include <linux/vmalloc.h>/r/n",
   
 "#include <linux/delay.h>/r/n",
   
 "#include <linux/interrupt.h>/r/n",
   
 "#include <linux/dma-mapping.h>/r/n",
   
 "#include <linux/platform_device.h>/r/n",
   
 "/r/n",
   
 "#include <asm/uaccess.h>/r/n",
   
 "#include <linux/fb.h>/r/n",
   
 "#include <linux/init.h>/r/n",
   
 "/r/n",
   
 "#include /"truecolor_logo.h/"/r/n",
   
 "/r/n",
   
 "// #define    DEBUG_TRUECOLOR_LOGO    /* Debug Output Switch *//r/n",
   
 "/r/n",
   
 "#ifdef CONFIG_FB_TRUECOLOR_LOGO/r/n",
   
 "static struct TrueColor/r/n",
   
 "{/r/n",
   
 "    int Width, Height;/r/n",
   
 "    int ColorBytes;/r/n",
   
 "    const char *BitData;/r/n",
   
 "} _true_color_logo;/r/n",
 "/r/n",
};


int Tran_24bit_BMP(const char *BMPFile, const char *CxxFile)
{
 
 int width, height;
 
 short int bitcount;
 
 FILE *fpBMP, *fpCxx;
 
 ColorBGR24BIT *colorRead24; // read the color data(24 bit)
 int i, j;
   
 int out_counter;
   
 unsigned short int Value_16;

 

 fpBMP = fopen(BMPFile, "rb");
   
 fpCxx = fopen(CxxFile, "wb");

 
 if((NULL==fpBMP) || (NULL==fpCxx))
 {
  if(NULL == fpBMP) printf("Read %s file failure. /n", BMPFile);
  else fclose(fpBMP);
  if(NULL == fpCxx) printf("Create %s file failure. /n", CxxFile);
  else fclose(fpCxx);
  return 0;
 }

 fseek(fpBMP, 18, SEEK_SET);
 fread(&width, sizeof(width), 1, fpBMP);
 fread(&height, sizeof(height), 1, fpBMP);
 fseek(fpBMP, 28, SEEK_SET);
 fread(&bitcount, sizeof(bitcount), 1, fpBMP);

 
 printf("/n Width=%d, Height=%d Bits=%d./n", width, height, (int)bitcount);

 
 if(24 != bitcount)
 
 {
  
  fclose(fpBMP);
       
  fclose(fpCxx);
  
  printf("Only support 24 bitmap file. /n");
  return 0;
 
 }

   
 for(i=0; i<sizeof(strHead)/MAXROWTEXT; i++)
       
 fprintf(fpCxx, strHead[i]);


 // color * width memory
 colorRead24 = (ColorBGR24BIT *)malloc(width* sizeof(ColorBGR24BIT));

 // BPX==32
 out_counter = 0;
 fprintf(fpCxx, "#if (BPX==32)/r/n");
 fprintf(fpCxx, "/r/n");
 fprintf(fpCxx, "/* R(8)/G(8)/B(8)/0(8) code for little endian system *//r/n");
 fprintf(fpCxx, "static unsigned char truecolor_logo_data[] =/r/n");
 fprintf(fpCxx, "{/r/n");

 fseek(fpBMP, 54, SEEK_SET);     // BMP file information head
 for(j=height-1; j>=0; j--)
 {
  fread(colorRead24, width*3, 1, fpBMP);
  if(width % 4) fseek(fpBMP, (width% 4), SEEK_CUR); // fix width and file pointer 24-bits

  for(i=0; i<width; i++)
  {
   if(0 == (out_counter % 6)) fprintf(fpCxx, "/r/n/t");
   out_counter++;
   // R/G/B/0 code for little endian system, the code for big endian system is not test
   fprintf(fpCxx, "0x%02x, 0x%02x, 0x%02x, 0x00, ", colorRead24[i].r, colorRead24[i].g, colorRead24[i].b);
  }
 }
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "};/r/n");
   
 fprintf(fpCxx, "/r/n");

   
 
 // BPX==24
   
 out_counter = 0;
   
 fprintf(fpCxx, "#elif (BPX==24)/r/n");
 fprintf(fpCxx, "/r/n");
 fprintf(fpCxx, "/* R(8)/G(8)/B(8) code for little endian system *//r/n");
 fprintf(fpCxx, "static unsigned char truecolor_logo_data[] =/r/n");
 fprintf(fpCxx, "{/r/n");

 fseek(fpBMP, 54, SEEK_SET);     // BMP file information head
 for(j=height-1; j>=0; j--)
 {
  fread(colorRead24, width*3, 1, fpBMP);
  if(width % 4) fseek(fpBMP, (width% 4), SEEK_CUR); // fix width and file pointer 24-bits

  for(i=0; i<width; i++)
  {
   if(0 == (out_counter % 8)) fprintf(fpCxx, "/r/n/t");
   out_counter++;
   // R/G/B: code for little endian system, the code for big endian system is not test
   fprintf(fpCxx, "0x%02x, 0x%02x, 0x%02x, ", colorRead24[i].r, colorRead24[i].g, colorRead24[i].b);
  }
 }
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "};/r/n");
   
 fprintf(fpCxx, "/r/n");

   

 // BPX==16
   
 out_counter = 0;
   
 fprintf(fpCxx, "#elif (BPX==16)/r/n");
 fprintf(fpCxx, "/r/n");
 fprintf(fpCxx, "/* R(5)/G(6)/B(5) code for little endian system *//r/n");
 fprintf(fpCxx, "static unsigned char truecolor_logo_data[] =/r/n");
 fprintf(fpCxx, "{/r/n");

 fseek(fpBMP, 54, SEEK_SET);     // BMP file information head
 for(j=height-1; j>=0; j--)
 {
  fread(colorRead24, width*3, 1, fpBMP);
  if(width % 4) fseek(fpBMP, (width% 4), SEEK_CUR); // fix width and file pointer 24-bits

  for(i=0; i<width; i++)
  {
   if(0 == (out_counter % 12)) fprintf(fpCxx, "/r/n/t");
   out_counter++;
   // R(5)/G(6)/B(5): code for little endian system
   Value_16 = ((colorRead24[i].r >> 3) << 11) | ((colorRead24[i].r >> 2) << 5) | (colorRead24[i].b >> 3);
   fprintf(fpCxx, "0x%02x, 0x%02x, ", (Value_16 >> 8), (Value_16 & 0xFF));
  }
 }
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "};/r/n");
   
 fprintf(fpCxx, "/r/n");

   

 // BPX < 16 (Don't support)
   
 fprintf(fpCxx, "#else/r/n");
   
 fprintf(fpCxx, "/r/n");
 fprintf(fpCxx, "static unsigned char truecolor_logo_data[] =/r/n");
 fprintf(fpCxx, "{ 0, }; /r/n");
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "#endif // BPX /r/n");
   
 fprintf(fpCxx, "/r/n");

   

 // Set the logo data information and the fb_prepare_truecolor_logo function
   
 fprintf(fpCxx, "int fb_prepare_truecolor_logo(void)/r/n");
   
 fprintf(fpCxx, "{/r/n");
 fprintf(fpCxx, "/t_true_color_logo.ColorBytes = BPX/8;/r/n");
 fprintf(fpCxx, "/t_true_color_logo.Width = %d;/r/n", width);
 fprintf(fpCxx, "/t_true_color_logo.Height = %d;/r/n", height);
   
 fprintf(fpCxx, "/t_true_color_logo.BitData = truecolor_logo_data;/r/n");
   
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "#ifdef DEBUG_TRUECOLOR_LOGO/r/n");
   
 fprintf(fpCxx, "/tprintk(/"fb_prepare_truecolor_logo ok
//n/");/r/n");
   
 fprintf(fpCxx, "#endif/r/n");
   
 fprintf(fpCxx, "/treturn (_true_color_logo.ColorBytes > 1); /* Only support 16 Bits or more color*//r/n");
   
 fprintf(fpCxx, "}/r/n");
   
 fprintf(fpCxx, "/r/n");

   

 // Set the fb_show_truecolor_logo function
   
 fprintf(fpCxx, "void fb_show_truecolor_logo(struct fb_info *info)/r/n");
   
 fprintf(fpCxx, "{/r/n");
   
 fprintf(fpCxx, "/tchar *framebase = info->screen_base;/r/n");
   
 fprintf(fpCxx, "/tint m, n;/r/n");
   
 fprintf(fpCxx, "/tint startx, starty;/r/n");
   
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "/tstartx = (XRES- _true_color_logo.Width)/ 2;/r/n");
   
 fprintf(fpCxx, "/tif(startx < 0) startx = 0;/r/n");
   
 fprintf(fpCxx, "/tstarty = (YRES- _true_color_logo.Height)/ 2;/r/n");
   
 fprintf(fpCxx, "/tif(starty < 0) starty = 0;/r/n");
   
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "#ifdef DEBUG_TRUECOLOR_LOGO/r/n");
   
 fprintf(fpCxx, "/tprintk(/"fb_show_truecolor_logo:: %%d %%d %%d %%d
//n/", XRES, YRES, startx, starty);/r/n");
   
 fprintf(fpCxx, "#endif/r/n");
   
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "/tfor(m=0; m<YRES; m++)/r/n");
   
 fprintf(fpCxx, "/t{/r/n");
   
 fprintf(fpCxx, "/t/tif((m < starty) || (m >= _true_color_logo.Height+starty)) // Set the background color to black/r/n");
   
 fprintf(fpCxx, "/t/t{/r/n");
   
 fprintf(fpCxx, "/t/t/tmemset(framebase+ (m* XRES* _true_color_logo.ColorBytes), 0, XRES* _true_color_logo.ColorBytes);/r/n");
   
 fprintf(fpCxx, "/t/t}/r/n");
   
 fprintf(fpCxx, "/t/telse/r/n");
   
 fprintf(fpCxx, "/t/t{/r/n");
   
 fprintf(fpCxx, "/t/t/t// Set the left to black color/r/n");
   
 fprintf(fpCxx, "/t/t/tmemset(framebase+ ((m* XRES)* _true_color_logo.ColorBytes), 0, _true_color_logo.ColorBytes* startx);/r/n");
   
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "/t/t/t// Set logo data, the vertical must upend/r/n");
   
 fprintf(fpCxx, "/t/t/tmemcpy(framebase+ ((m* XRES+ startx)* _true_color_logo.ColorBytes), /r/n");
 
 fprintf(fpCxx, "/t/t/t/t// (_true_color_logo.BitData+ ((m-starty)* _true_color_logo.Width)* _true_color_logo.ColorBytes), /r/n");
   
 fprintf(fpCxx, "/t/t/t/t(_true_color_logo.BitData+ ((_true_color_logo.Height-(m-starty)-1)* _true_color_logo.Width)* _true_color_logo.ColorBytes), /r/n");
   
 fprintf(fpCxx, "/t/t/t/t_true_color_logo.ColorBytes* _true_color_logo.Width);/r/n");
   
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "/t/t/t// Set the right to black color/r/n");
  
 fprintf(fpCxx, "/t/t/tmemset(framebase+ ((m* XRES+ startx+ _true_color_logo.Width)* _true_color_logo.ColorBytes), 0, /r/n");
   
 fprintf(fpCxx, "/t/t/t/t_true_color_logo.ColorBytes*(XRES- startx- _true_color_logo.Width));/r/n");

   
 fprintf(fpCxx, "/t/t}/r/n");
   
 fprintf(fpCxx, "/t}/r/n");
   
 fprintf(fpCxx, "}/r/n");
   
 fprintf(fpCxx, "/r/n");

   
 fprintf(fpCxx, "#else // CONFIG_FB_TRUECOLOR_LOGO/r/n");
   
 fprintf(fpCxx, "/r/n");
   
 fprintf(fpCxx, "int fb_prepare_truecolor_logo(void) { return 0; } /r/n");
   
 fprintf(fpCxx, "void fb_show_truecolor_logo(struct fb_info *info) { return; } /r/n");
   
 fprintf(fpCxx, "/r/n");

   
 fprintf(fpCxx, "#endif // CONFIG_FB_TRUECOLOR_LOGO/r/n");
   
 fprintf(fpCxx, "/r/n");

 
 free(colorRead24);
 
 fclose(fpBMP);
   
 fclose(fpCxx);

   
 return 1;

}


int main(int argc, char* argv[])
{
 char CxxFileName[100];
 if(argc < 2)
 {
  printf("Use: bmp2logo xxx.bmp (truecolor_logo.c)/n");
#ifdef  __WIN32__
  system("Pause");
#endif
  return;
 }

 if(argc > 2) strcpy(CxxFileName, argv[2]);
#ifdef  __WIN32__
 else strcpy(CxxFileName, ".//..//truecolor_logo.c");
#else
 else strcpy(CxxFileName, "./../truecolor_logo.c");
#endif
   
 if( ! (Tran_24bit_BMP(argv[1], CxxFileName)))
 {
  printf("Transform %s to truecolor_logo.c failure /n", argv[1]);
#ifdef  __WIN32__
  system("Pause");
#endif
  return -1;
 }

 printf("Transform %s to truecolor_logo.c success /n", argv[1]);
#ifdef  __WIN32__
 system("Pause");
#endif
 return 0;
}

 

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

Behard

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值