基于FB的bmp显示
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <arpa/inet.h>
char *fbp = 0;
int xres = 0;
int yres = 0;
int bits_per_pixel = 0;
//14byte
typedef struct
{
char cfType[2]; /* 文件类型, 必须为 "BM" (0x4D42)*/
char cfSize[4]; /* 文件的大小(字节) */
char cfReserved[4]; /* 保留, 必须为 0 */
char cfoffBits[4]; /* 位图阵列相对于文件头的偏移量(字节)*/
}__attribute__((packed)) BITMAPFILEHEADER; /* 文件头结构 */
//40byte
typedef struct
{
char ciSize[4]; /* size of BITMAPINFOHEADER */
char ciWidth[4]; /* 位图宽度(像素) */
char ciHeight[4]; /* 位图高度(像素) */
char ciPlanes[2]; /* 目标设备的位平面数, 必须置为1 */
char ciBitCount[2]; /* 每个像素的位数, 1,4,8或24 */
char ciCompress[4]; /* 位图阵列的压缩方法,0=不压缩 */
char ciSizeImage[4]; /* 图像大小(字节) */
char ciXPelsPerMeter[4];/* 目标设备水平每米像素个数 */
char ciYPelsPerMeter[4];/* 目标设备垂直每米像素个数 */
char ciClrUsed[4]; /* 位图实际使用的颜色表的颜色数 */
char ciClrImportant[4]; /* 重要颜色索引的个数 */
}__attribute__((packed)) BITMAPINFOHEADER; /* 位图信息头结构 */
#if 0
typedef struct
{
unsigned short blue:5;
unsigned short green:5;
unsigned short red:5;
unsigned short rev:1;
}__attribute__((packed)) PIXEL;
#else
typedef struct
{
unsigned short blue:5;
unsigned short green:6;
unsigned short red:5;
}__attribute__((packed)) PIXEL;
#endif
BITMAPFILEHEADER FileHead;
BITMAPINFOHEADER InfoHead;
int show_bmp(char *bmpfile);
long chartolong ( char * string, int length );
int main(int argc,char *argv[])
{
int fbfd;
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
long int screensize = 0;
fbfd = open("/dev/fb",O_RDWR);
if(!fbfd)
{
fprintf(stderr,"Error can't open dev fb\n");
return -1;
}
//获取固定参数
if(ioctl(fbfd,FBIOGET_FSCREENINFO,&finfo))
{
fprintf(stderr,"Error reading fixed information.\n");
return -1;
}
//获取可变参数
if(ioctl(fbfd,FBIOGET_VSCREENINFO,&vinfo))
{
fprintf(stderr,"Error reading variable information.\n");
return -1;
}
/*
printf("semem_start:%x,smem_len:%d,mmio_start:%d,mmio_len:%d,type:%d,xpan:%d,y_pan:%d,y_wrap:%d,accel:%d,id:%d,llen:%d,visual:%d\n", \
finfo.smem_start,finfo.smem_len,finfo.mmio_start,finfo.mmio_len,finfo.type,\
finfo.xpanstep,finfo.ypanstep,finfo.ywrapstep,finfo.accel,finfo.id, \
finfo.line_length,finfo.visual);
*/
xres = vinfo.xres;
yres = vinfo.yres;
bits_per_pixel = vinfo.bits_per_pixel;
//计算整个屏幕的大小
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("Failed to map framebuffer device to memory!\n");
return -1;
}
//显示一张BMP图片
show_bmp(argv[1]);
munmap(fbp,screensize);
close(fbfd);
return 0;
}
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)
{
printf("Open file %s error\b",bmpfile);
return (-1);
}
/* 读取位图文件头 */
rc = fread(&FileHead,sizeof(BITMAPFILEHEADER),1,fp);
if(rc != 1)
{
printf("Read header error\n");
fclose(fp);
return (-2);
}
if(memcmp(FileHead.cfType,"BM",2) != 0)
{
printf("Not a BMP file\n");
fclose(fp);
return (-3);
}
/* 读取位图信息头 */
rc = fread((char *)&InfoHead,sizeof(BITMAPINFOHEADER),1,fp);
if(rc != 1)
{
printf("Read infoheader error\n");
fclose(fp);
return (-4);
}
ciWidth = (int)chartolong(InfoHead.ciWidth,4);
ciHeight = (int)chartolong(InfoHead.ciHeight,4);
ciBitCount = (int)chartolong(InfoHead.ciBitCount,4);
fseek(fp,(int)chartolong(FileHead.cfoffBits,4),SEEK_SET);
BytesPerLine = (ciWidth * ciBitCount +31) /32 *4;
printf("width=%d,height=%d,bitCount=%d,offset=%d\n",ciWidth,ciHeight, \
(int)chartolong(FileHead.cfoffBits, 4));
line_x = line_y = 0;
while(!feof(fp))
{
PIXEL pix;
unsigned short tmp;
rc = fread((char *)&pix,1,sizeof(unsigned short),fp);
if(rc != sizeof(unsigned short))break;
location = line_x * bits_per_pixel / 8 + (ciHeight - line_y -1) * xres * bits_per_pixel / 8;
tmp = pix.red << 0 | pix.green << 5 | pix.blue << 11;
*((unsigned short *)(fbp + location)) = tmp;
line_x ++;
if(line_x == ciWidth)
{
line_x = 0;
line_y ++;
if(line_y == ciHeight -1)
break;
}
}
fclose(fp);
return 0;
}
long chartolong( char * string, int length )
{
long number;
if (length = 4)
{
memset( &number, 0x00, sizeof(long) );
memcpy( &number, string, length );
}
return( number );
}