在指令行下利用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 plain copy
- #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;
- 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");
- if(ioctl(fbfd,FBIOGET_FSCREENINFO,&finfo)==-1)
- {
- printf("erro reading fixed screen/n");
- exit(2);
- }
- if(ioctl(fbfd,FBIOGET_VSCREENINFO,&vinfo)==-1)
- {
- printf("erro reading variable info/n");
- exit(3);
- }
- xres = vinfo.xres;
- yres = vinfo.yres;
- red = vinfo.red;
- green = vinfo.green;
- blue = vinfo.blue;
- bits_per_pixel=vinfo.bits_per_pixel;
- //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);
- screensize=vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8;
- 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];
- 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