基于FB的bmp显示

基于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 );   
} 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值