1.在屏幕上分別顯示紅綠藍三個長方形:
- #ifndef LCD_APP_H
- #define LCD_APP_H
- /*自定義結構體用來在用戶空間裏管理幀緩衝的信息*/
- typedef struct fd_dev
- {
- int fd;//幀緩衝設備文件描述符
- void *pfb;//指向幀緩衝映射到用戶空間的首地址
- int xres,yres,siz;//一幀圖像的寬度、高度和大小
- int bpp;//每個像素的位數
- }fb_dev_t;
- /*實現緩衝設備的打開和關閉操作的接口*/
- int fb_open(fb_dev_t *fbd,char *fbn)
- {
- struct fb_var_screeninfo vinfo;
- if(-1 == (fbd->fd=open(fbn,O_RDWR))){
- printf("Error:cannot open framebuffer device.\n");
- _exit(EXIT_FAILURE);
- }
- /*獲取LCD的可變參數*/
- ioctl(fbd->fd,FBIOGET_VSCREENINFO,&vinfo);
- //將可變參數的中的相關數據保存到自定的結構體fbd中
- fbd->xres = vinfo.xres;
- fbd->yres = vinfo.yres;
- fbd->bpp = vinfo.bits_per_pixel;
- fbd->siz = fbd->xres * fbd->yres *fbd->bpp/8;
- printf("%dx%d,%dbpp,screensize = %d\n",fbd->xres,fbd->yres,
- fbd->bpp,fbd->siz);
- /*將幀緩衝映射到內存*/
- fbd->pfb = mmap(0,fbd->siz,PROT_READ|PROT_WRITE,
- MAP_SHARED,fbd->fd,0);
- if((int)fbd->pfb == -1){
- printf("Error:failed to map framebuffer device to memory.\n");
- _exit(EXIT_FAILURE);
- }
- return 0;
- }
- int fb_close(fb_dev_t *fbd)
- {
- munmap(fbd->pfb,fbd->siz);//解除映射
- close(fbd->fd);//關閉設備文件
- }
- /*填充制定的巨型區域*/
- int fb_drawrect(fb_dev_t *fbd,int x0,int y0,int w,int h,int color)
- {
- int x,y;
- for(y=y0;y<y0+h;y++)
- {
- for(x = x0;x<x0+w;x++)
- *((short*)(fbd->pfb)+y*fbd->xres+x)=color;
- }
- return 0;
- }
- #endif
測試程序lcd_app.c
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <linux/fb.h>
- #include <sys/mman.h>
- #include "lcd_app.h"
- #include "bmplib.h"
- #define FB_DEV_NAME "/dev/fb0"
- #define RED_COLOR565 0x0F100
- #define GREEN_COLOR565 0x007E0
- #define BLUE_COLOR565 0x0001F
- int main(int argc,char *argv[])
- {
- fb_dev_t *fbd;
- fbd = (fb_dev_t*)malloc(sizeof(fb_dev_t));
- fb_open(fbd,FB_DEV_NAME);
- if(fbd->bpp == 16){
- printf("Red/Green/Blue Screen\n");
- fb_drawrect(fbd,0,0,fbd->xres,fbd->yres/3,RED_COLOR565);
- fb_drawrect(fbd,0,fbd->yres/3,fbd->xres,fbd->yres*2/3,GREEN_COLOR565);
- fb_drawrect(fbd,0,fbd->yres*2/3,fbd->xres,fbd->yres,BLUE_COLOR565);
- }else
- printf("16 bits only!\n");
- //fb_drawbmp(fbd,0,0,argv[1]);
- fb_close(fbd);
- return 0;
- }
2.在lcd上顯示位圖bmplib.h
- #ifndef BMPLIB_H
- #define BMPLIB_H
- typedef struct
- {
- /*位圖頭文件*/
- char type[2];//文件類型,必須爲"BM"(0x4D42)
- char siz[4];//文件的大小
- char reserved[4];//保留,必須爲0
- char off[4];//位圖陣列相對於文件頭的偏移字節
- }bmp_file_header_t;
- typedef struct{
- /*位圖信息頭*/
- char siz[4];
- char width[4];//位圖的寬度
- char height[4];//位圖的高度
- char planes[2];//目標設備的位平面數,必須設置爲1
- char bitcount[2];//每個像素的位數,1,4,8,或24
- char compress[3];//位圖陣列的壓縮方法,0=不壓縮
- char img_siz[4];//圖像大小(字節)
- char xpel[4];//目標設備水平每米像素的個數
- char ypel[4];//目標像素垂直每米像素的個數
- char clr_used[4];//位圖實際使用的顏色表的顏色數
- char clr_important[4];//重要顏色索引的個數
- }bmp_info_header_t;
- /*bitmap格式的圖像文件會帶有54字節的信息頭,其中包含了圖像和文件的基本信息,
- 緊接在文件頭之後的就是實際的圖像數據*/
- typedef struct{
- char blue;
- char green;
- char red;
- char reserved;
- }rgb_32_t;
- /*對位圖進行操作*/
- typedef struct{
- rgb_32_t *curp;//指向當前像素點
- int width,height,bitcount,siz;//圖形長寬、大小等信息
- int fd;//圖像文件描述符
- void *data;//圖像有效數據
- }bmp_t;
- //字符形到整形的轉換
- int char_to_int(char *ch)
- {
- return *((int*)ch);
- }
- /*打開位圖操作*/
- int bmp_open(bmp_t *bmp,char *bmpn)
- {
- bmp_file_header_t fhr;//位圖文件頭
- bmp_info_header_t ihr;//位圖信息頭
- if(-1 == (bmp->fd=open(bmpn,O_RDONLY))){
- printf("Error:cannot open framebuffer device.\n");
- _exit(EXIT_FAILURE);
- }
- read(bmp->fd,&fhr,sizeof(bmp_file_header_t));//讀取文件頭
- read(bmp->fd,&ihr,sizeof(bmp_info_header_t));//讀取信息頭
- bmp->width = char_to_int(ihr.width);
- bmp->height = char_to_int(ihr.height);
- bmp->bitcount = char_to_int(ihr.bitcount);//像素位數
- bmp->siz = (bmp->width *bmp->height*bmp->bitcount)/8;
- printf("bmp->width = %d\n",bmp->width);
- printf("bmp->height = %d\n",bmp->height);
- printf("bmp->bitcount = %d\n",bmp->bitcount);
- printf("bmp->siz = %d\n",bmp->siz);
- bmp->data = malloc(bmp->siz);//爲位圖數據分配存儲空間
- read(bmp->fd,bmp->data,bmp->siz);//讀取數據
- bmp->curp = (rgb_32_t *)bmp->data;//獲取當前像素點
- return 0;
- }
- int bmp_close(bmp_t *bmp)
- {
- close(bmp->fd);
- free(bmp->data);
- return 1;
- }
- /*
- 因爲開發板的幀緩衝區在驅動中被設置爲16位數據表示一個像素點,因此需要對24或
- 32位的位圖進行轉換,使用下面的函數
- */
- static inline short transfer_to_16bit(char r,char g,char b)
- {
- return ((r>>3)<<11)|((g>>2)<<5)|(b>>3);
- }
- static inline short bmp_get_pixel_16bit(bmp_t *bmp)
- {
- //將當前位圖轉化爲16位位圖信息
- return transfer_to_16bit(bmp->curp->red,bmp->curp->green,bmp->curp->blue);
- }
- //移動到下一像素點
- static inline void bmp_next_pixel(bmp_t *bmp)
- {
- if(24==bmp->bitcount)//如果是24位位圖
- bmp->curp = (rgb_32_t*)((int)bmp->curp+3);
- else if(32 == bmp->bitcount)//如果是32位位圖
- bmp->curp = (rgb_32_t*)((int)bmp->curp+4);
- }
- /*繪製位圖*/
- int fb_drawbmp(fb_dev_t *fbd,int x0,int y0,char *bmpn)
- {
- int x,y,x1,y1;
- bmp_t bmp;
- bmp_open(&bmp,bmpn);
- x1 = x0+bmp.width;
- y1 = y0+bmp.height;
- for(y = y1;y>y0;y--){
- for(x = x0;x<x1;x++){
- //如果超出LCD屏幕座標範圍
- if(x>fbd->xres||y>fbd->yres){
- bmp_next_pixel(&bmp);//移動到下一個像素點
- continue;
- }
- *((short*)(fbd->pfb)+y*fbd->xres+x) = bmp_get_pixel_16bit(&bmp);
- bmp_next_pixel(&bmp);//移動到下一像素點
- }
- }
- bmp_close(&bmp);
- return 0;
- }
- #endif
測試程序:
lcd_bmp.c
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <linux/fb.h>
- #include <sys/mman.h>
- #include "lcd_app.h"
- #include "bmplib.h"
- #define FB_DEV_NAME "/dev/fb0"
- #define RED_COLOR565 0x0F100
- #define GREEN_COLOR565 0x007E0
- #define BLUE_COLOR565 0x0001F
- int main(int argc,char *argv[])
- {
- fb_dev_t *fbd;
- fbd = (fb_dev_t*)malloc(sizeof(fb_dev_t));
- fb_open(fbd,FB_DEV_NAME);
- /*
- if(fbd->bpp == 16){
- printf("Red/Green/Blue Screen\n");
- fb_drawrect(fbd,0,0,fbd->xres,fbd->yres/3,RED_COLOR565);
- fb_drawrect(fbd,0,fbd->yres/3,fbd->xres,fbd->yres*2/3,GREEN_COLOR565);
- fb_drawrect(fbd,0,fbd->yres*2/3,fbd->xres,fbd->yres,BLUE_COLOR565);
- }else
- printf("16 bits only!\n");
- */
- fb_drawbmp(fbd,0,0,argv[1]);
- fb_close(fbd);
- return 0;
- }
位圖程序測試方法,例如這裏有一張名爲clock.bmp的圖片
編譯上述文件後生成lcd_bmp
運行如下命令:
./lcd_bmp clock.bmp
實驗現象: