您的位置:首页 > Web前端

Ubuntu 9.10 实现用framebuffer显示bmp图片

2012-10-18 13:51 309 查看
在命令行下利用framebuffer显示bmp格式的图片,首先要打开framebuffer设备,ubuntu 9.10 是打开/boot/grub/grub.cfg 文件 在“linux /boot/vmlinuz-2.6.31-22-generic root=UUID=dadb1e1d-b7b7-45c8-a031-21d2e840c608 ro quiet splash vga=791 " 这一行加入红字,注意不是recovery
mode 。 然后重启就打开了framebuffer设备,在/dev下可以看到fb0。下面是程序代码。要注意显示的图片的位数(有16位24位和32位的)这个是显示32位bmp图片的。

[cpp] view
plaincopy

#include<unistd.h>

#include<stdio.h>

#include<fcntl.h>

#include<linux/fb.h>

#include<sys/mman.h>

#include<stdlib.h>

#include<sys/ioctl.h>

#include<asm/page.h>

#include <string.h>

#include <errno.h>

#include <unistd.h>

#include <linux/kd.h>

#include <linux/keyboard.h>

#include <termios.h>

static int fbfd=0;

static long int screensize=0;

static char *fbp=0;

int x=0,y=0;

long int location =0;

static int xres=0,yres=0;

int bits_per_pixel=0;

typedef struct

{

char cfType[2]; // file type

char cfSize[4]; // file size

char cfReserved[4]; //

char cfoffBits[4]; //

}BITMAPFILEHEADER; //file head strucgt

typedef struct

{

char ciSize[4]; //

char ciWidth[4];

char ciHeight[4];

char ciPlanes[2];

char ciBitCount[2];

char ciCompress[4];

char ciSizeImage[4];

char ciXPelsPerMeter[4];

char ciYPelsPerMeter[4];

char ciClrUsed[4];

char ciClrImportant[4];

} BITMAPINFOHEADER;

typedef struct

{

char rgbBlue;

char rgbGreen;

char rgbRed;

char rgbReserved;

} RGBQUAD;

BITMAPFILEHEADER FileHead;

BITMAPINFOHEADER InfoHead;

RGBQUAD rgbquad;

int show_bmp (char *bmpfile );

long chartolong(char * string, int length );

struct fb_var_screeninfo vinfo;

struct fb_fix_screeninfo finfo;

int fb_init()

{

//struct fb_var_screeninfo vinfo;

//struct fb_fix_screeninfo finfo;

struct fb_bitfield red;//bitfield in fb mem if true colour

struct fb_bitfield green;//else only length is significant

struct fb_bitfield blue;

/*open the dev */

fbfd=open("/dev/fb0",O_RDWR);

if(!fbfd)

{

printf("erro:cannot open the dev/n");

exit(1);

}

else

//printf("the dev is opened successfully/n");

/*get sreeen information*/

if(ioctl(fbfd,FBIOGET_FSCREENINFO,&finfo)==-1)

{

printf("erro reading fixed screen/n");

exit(2);

}

/*get variable sreen info*/

if(ioctl(fbfd,FBIOGET_VSCREENINFO,&vinfo)==-1)

{

printf("erro reading variable info/n");

exit(3);

}

/*init the parse*/

xres = vinfo.xres;

yres = vinfo.yres;

red = vinfo.red;

green = vinfo.green;

blue = vinfo.blue;

bits_per_pixel=vinfo.bits_per_pixel;

/*show these information*/

//printf("vifo.xres=%d/n",xres);

//printf("vifo.yres=%d/n",yres);

// printf("vifo.bits_per_bits=%d/n",bits_per_pixel);

//printf("vifo.xoffset=%d/n",vinfo.xoffset);

// printf("vifo.yoffset=%d/n",vinfo.yoffset);

// printf("finfo.line_length=%d/n",finfo.line_length);

/*figure out the size of screen in bytes*/

screensize=vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8;

/*map the device to memory*/

fbp=(char*)mmap(0,screensize,PROT_READ|PROT_WRITE,MAP_SHARED,fbfd,0);

if((int)fbp==-1)

{

printf("erro:failed to map framebuffer/n");

exit(4);

}

else printf ("the framebuffer device was mapped to menory successfully/n");

memset(fbp,0,screensize);

return 0;

}

void fb_close()

{

munmap(fbp,screensize);

close(fbfd);

}

long chartolong(char *string,int length)

{

long number;

if(length<=4)

{

memset(&number,0x00,sizeof(long));

memcpy(&number,string,length); //

}

return (number);

}

int show_bmp(char *bmpfile)

{

FILE *fp;

int rc;

int ciBitCount,ciWidth,ciHeight;

int line_x,line_y;

long int location=0,BytesPerLine=0;

char tmp[1024*10];

/*open the bmp file*/

fp=fopen(bmpfile,"rb");

if(fp==NULL) return (-1);

//read the bmp head

rc = fread(&FileHead,1,sizeof(BITMAPFILEHEADER),fp);

if(rc!=sizeof(BITMAPFILEHEADER))

{

fclose(fp);

return(-2);

}

if(memcmp(FileHead.cfType,"BM",2)!=0)

{

fclose(fp);

return(-3);

}

rc=fread((char*)&InfoHead,1,sizeof(BITMAPINFOHEADER),fp);

if(rc!=sizeof(BITMAPINFOHEADER))

{

fclose(fp);

return(-4);

}

ciWidth=(int)chartolong(InfoHead.ciWidth,4);

ciHeight=(int)chartolong(InfoHead.ciHeight,4);

ciBitCount=(int)chartolong(InfoHead.ciBitCount,4);

line_x=line_y=0;

while(!feof(fp))

{

rc=fread((char*)&rgbquad,1,sizeof(RGBQUAD),fp);

if(rc!=sizeof(RGBQUAD)) break;

location=(line_x+200)*bits_per_pixel/8+ (ciHeight-line_y+150)*finfo.line_length;

//printf("location= %d/n", location) ;

*(fbp + location + 0)=rgbquad.rgbBlue;

*(fbp + location + 1)=rgbquad.rgbGreen;

*(fbp + location + 2)=rgbquad.rgbRed;

*(fbp + location + 3)=rgbquad.rgbReserved;

line_x++ ;

if(line_x==(ciWidth))

{

line_x=0;

line_y++ ;

}

}

fclose(fp);

return(0);

}

int main(int argc,char *argv[])

{

int x=0;

int y=0;

fb_init();

show_bmp(argv[1]);

return 0;

}

追加内容: 说到framebuffer 不得不说到一个函数ioctl ,这里只是简单用了一下,ioctl中第二个参数是cmd,比如FBIOGET_FSCREENINFO,FBIOGET_VSCREENINFO,分别是获取fbfd设备的固定信息和可改变信息,FBIOPUT_VSCREENINFO 用户设置可变屏幕参数,FBIOPUTCMAP 设置屏幕颜色表,FBIOGETCMAP 获取颜色表等。

还有个函数mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) 与之对应的是 int munmap(void *start ,size_t length)

start 是映射区开始地址, length 映射区的长度(字节),prot 期望内存保护标志,如(PROT_EXEC ,PROT_READ, PROT_WRITE, PROT_NONE) flags 指定映射对象的类型 它的值有MAP_FIXED 使用指定得映射地址,MAP_SHARED 与其它映射这个对象的进程共享映射空间,这个值不能与MAP_PRIVATE 不能同时用。MAP_LOCKED 锁定映射区的页面,防止交换内存。fd 有效文件描述词。offset 映射对象内容的起点。

mmap 成功执行返回文件映射到进程空间的地址,失败返回-1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: