一个操作FB填充位图的例子:
/****************/
/* Header Files */
/****************/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <pthread.h>
#include <linux/fb.h>
#include "cnxtfb.h"
#pragma pack(1)
typedef struct{
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
unsigned int biSize;
unsigned int Width;
unsigned int Height;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
unsigned int biXPelsPerMeter;
unsigned int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
}BMP_Header;
#pragma pack()
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
unsigned long screen_size;
unsigned long bmp_size;
unsigned char * lpScreenMem;//mmap to fb memory
unsigned char * lpPicMem;//memory for load pictrue
unsigned char * lpScreenMem_bak;//for ready the images and copy all size to lpScreenMem at once
BMP_Header bmp_header;
//#define DBG 1
/*************************************************
function:Draw one image to lpScreenMem_bak.
parameter:
bitmap_file: The path of image which will be load.
x_pos: The image's x position in srceen.
y_pos: The image's y position in srceen.
*************************************************/
int DrawImage(char * bitmap_file,int x_pos,int y_pos)
{
int i,j,k,l;
unsigned char * pMem;//point to lpScreenMem_bak
unsigned char * pMem1;//point to lpPicMem
int draw_end_x = 0;
int draw_end_y = 0;
int bmp_end_x = 0;
int bmp_end_y = 0;
pMem = lpScreenMem_bak;
pMem1 = lpPicMem;
draw_end_y = (vinfo.yres - y_pos < bmp_header.Height)?(vinfo.yres):(bmp_header.Height + y_pos) ;
bmp_end_y = (vinfo.yres - y_pos < bmp_header.Height)?(vinfo.yres - y_pos):bmp_header.Height;
draw_end_x = (vinfo.xres - x_pos)<bmp_header.Width?(vinfo.xres ):(bmp_header.Width + x_pos);
bmp_end_x = (vinfo.xres - x_pos)<bmp_header.Width?(vinfo.xres - x_pos):bmp_header.Width;
//printf("draw_end_x = %d, draw_end_y = %d\n",draw_end_x,draw_end_y);
//printf("bmp_end_x = %d, bmp_end_y = %d\n",bmp_end_x,bmp_end_y);
lpPicMem += bmp_header.bfOffBits;
k = bmp_header.Height;
for(i = y_pos;i<draw_end_y;i++)
{
pMem = lpScreenMem_bak + (vinfo.xres*i + x_pos)*(vinfo.bits_per_pixel / 8);
pMem1 = lpPicMem + bmp_header.Width*3*(k-1);
j = 0;
while(j<((draw_end_x < bmp_end_x)?draw_end_x:bmp_end_x))
{
*pMem = *pMem1;
pMem++;
pMem1++;
*pMem = *pMem1;
pMem++;
pMem1++;
*pMem = *pMem1;
pMem++;
pMem1++;
*pMem = 0xff;
pMem++;
j++;
}
k--;
if(k < (bmp_header.Height-bmp_end_y))
{
break;
}
}
printf("DrawImage complete...\n");
return 0;
}
int main(int argc, char ** argv)
{
int x = 0;
int y = 0;
int fd = -1;
int fb = -1;
if(argc == 1)
{
printf("you must specify [FILE] options\n");
printf("Try `fb_splash--help' or `fb_splash --usage' for more information.\n");
return -1;
}
else if(argc == 2)
{
if(access(argv[1], 0) != 0)
{
if((strcmp(argv[1],"--help") == 0)||(strcmp(argv[1],"--usage") == 0))
{
printf("Usage: fb_splash [FILE] [POS_X] [POS_Y]\n");
printf("\t[FILE]\t24bit RGB format bmp file supported only\n");
printf("\t[POS_X]\tx offset you want draw\n");
printf("\t[POS_Y]\ty offset you want draw\n");
return -1;
}
else
{
printf("BMP file %s not exit!\n",argv[1]);
return -1;
}
}
else
{
x = 0;
y = 0;
}
}
else if(argc == 4)
{
if(access(argv[1], 0) != 0)
{
printf("bmp file %s not exit!\n",argv[1]);
return -1;
}
x = atoi(argv[2]);
y = atoi(argv[3]);
}
else
{
//printf("Usage: fb_splash [FILE] [POS_X] [POS_Y]\n");
printf("Try `fb_splash --help' or `fb_splash --usage' for more information.\n");
return -1;
}
fb = open("/dev/fb0", O_RDWR);
if (fb < 0)
{
fprintf(stderr, "open /dev/fb0 error!\n");
return -1;
}
if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo))
{
fprintf(stderr, "error get var screeninfo!\n");
close(fb);
return -1;
}
//printf("%dx%d %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
screen_size = vinfo.xres * vinfo.yres * (vinfo.bits_per_pixel / 8);
//printf("screen_size = 0x%x , %d bytes\n",screen_size,screen_size);
if((y >= vinfo.yres)||(x >= vinfo.xres))
{
printf("can't show bmp file out of screen!\n");
close(fb);
return -1;
}
lpScreenMem_bak = (unsigned char *) malloc(screen_size);
if(lpScreenMem_bak != NULL)
{
printf("lpScreenMem_bak = %p\n",lpScreenMem_bak);
}
lpScreenMem = (unsigned char *)mmap(0, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
if (lpScreenMem == -1)
{
printf("mmap error\n");
return -1;
}
//use lpScreenMem_bak to parse bmp file header
fd = open(argv[1], O_RDONLY);
if (fd < 0)
{
printf("Error opening %s\n", argv[1]);
return -1;
}
int count = read(fd, lpScreenMem_bak, sizeof(BMP_Header));
if(count <=0)
{
printf("Read bmp header of %s error\n", argv[1]);
return -1;
}
memcpy(&bmp_header,lpScreenMem_bak,(sizeof(BMP_Header)));
bmp_size = bmp_header.bfSize;
//printf("bmp file's height is %d,width is %d\n",bmp_header.Height,bmp_header.Width);
lpPicMem = (unsigned char *) malloc(bmp_size);
if(lpPicMem != NULL)
{
if(lseek(fd,0,SEEK_SET ) != 0)
{
printf("Read bmp file of %s error\n", argv[1]);
return -1;
}
count = read(fd, lpPicMem, bmp_size);
if(count <=0)
{
printf("Read bmp file of %s error\n", argv[1]);
return -1;
}
}
//clear buffer
memset(lpScreenMem_bak,0,screen_size);
if (ioctl(fb, FBIO_STOPDISPLAY, NULL) < 0)
{
printf("ioctl PHSTBOSD_IOCTL_DISPLAY_OSD failed");
close(fb);
fb=-1;
return -1;
}
//printf("show %s at %d,%d\n",argv[1],x,y);
DrawImage(argv[1],x,y);
memcpy(lpScreenMem,lpScreenMem_bak,screen_size);
if (ioctl(fb, FBIO_STARTDISPLAY, NULL) < 0)
{
printf("ioctl PHSTBOSD_IOCTL_DISPLAY_OSD failed");
close(fb);
fb=-1;
return -1;
}
if (ioctl(fb, FBIO_SCALE_SD_OSD, NULL) < 0)
{
printf("ioctl PHSTBOSD_IOCTL_DISPLAY_OSD failed");
close(fb);
fb=-1;
return -1;
}
free(lpPicMem);
free(lpScreenMem_bak);
close(fb);
close(fd);
fb=-1;
return 0;
}