zoukankan      html  css  js  c++  java
  • FrameBuffer系列 之 显示图片

    

    摘自:http://blog.csdn.net/luxiaoxun/article/details/7622988

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <string.h>
    #include <linux/fb.h>
    #include <sys/mman.h>
    #include <sys/ioctl.h>
    #include <arpa/inet.h>
    
    
    //14byte文件头
    typedef struct
    {
    	char cfType[2];//文件类型,"BM"(0x4D42)
    	long cfSize;//文件大小(字节)
    	long cfReserved;//保留,值为0
    	long cfoffBits;//数据区相对于文件头的偏移量(字节)
    }__attribute__((packed)) BITMAPFILEHEADER;
    //__attribute__((packed))的作用是告诉编译器取消结构在编译过程中的优化对齐
    
    //40byte信息头
    typedef struct
    {
    	char ciSize[4];//BITMAPFILEHEADER所占的字节数
    	long ciWidth;//宽度
    	long ciHeight;//高度
    	char ciPlanes[2];//目标设备的位平面数,值为1
    	int ciBitCount;//每个像素的位数
    	char ciCompress[4];//压缩说明
    	char ciSizeImage[4];//用字节表示的图像大小,该数据必须是4的倍数
    	char ciXPelsPerMeter[4];//目标设备的水平像素数/米
    	char ciYPelsPerMeter[4];//目标设备的垂直像素数/米
    	char ciClrUsed[4]; //位图使用调色板的颜色数
    	char ciClrImportant[4]; //指定重要的颜色数,当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要
    }__attribute__((packed)) BITMAPINFOHEADER;
    
    typedef struct
    {
    	unsigned short blue;
    	unsigned short green;
    	unsigned short red;
    	unsigned short reserved;
    }__attribute__((packed)) PIXEL;//颜色模式RGB
    
    BITMAPFILEHEADER FileHead;
    BITMAPINFOHEADER InfoHead;
    
    static char *fbp = 0;
    static int xres = 0;
    static int yres = 0;
    static int bits_per_pixel = 0;
    
    int show_bmp();
    
    int main ( int argc, char *argv[] )
    {
    	int fbfd = 0;
    	struct fb_var_screeninfo vinfo;
    	struct fb_fix_screeninfo finfo;
    	long int screensize = 0;
    	struct fb_bitfield red;
    	struct fb_bitfield green;
    	struct fb_bitfield blue;
    
    	//打开显示设备
    	fbfd = open("/dev/fb0", O_RDWR);
    	if (!fbfd)
    	{
    		printf("Error: cannot open framebuffer device.
    ");
    		exit(1);
    	}
    
    	if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
    	{
    		printf("Error:reading fixed information.
    ");
    		exit(2);
    	}
    
    	if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
    	{
    		printf("Error: reading variable information.
    ");
    		exit(3);
    	}
    
    	printf("R:%d,G:%d,B:%d 
    ", vinfo.red, vinfo.green, vinfo.blue );
    
    	printf("%dx%d, %dbpp
    ", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
    	xres = vinfo.xres;
    	yres = vinfo.yres;
    	bits_per_pixel = vinfo.bits_per_pixel;
    
    	//计算屏幕的总大小(字节)
    	screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    	printf("screensize=%d byte
    ",screensize);
    
    	//对象映射
    	fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    	if ((int)fbp == -1)
    	{
    		printf("Error: failed to map framebuffer device to memory.
    ");
    		exit(4);
    	}
    
    	printf("sizeof file header=%d
    ", sizeof(BITMAPFILEHEADER));
    
    	printf("into show_bmp function
    ");
    
    	//显示图像
    	show_bmp();
    
    	//删除对象映射
    	munmap(fbp, screensize);
    	close(fbfd);
    	return 0;
    }
    
    int show_bmp()
    {
    	FILE *fp;
    	int rc;
    	int line_x, line_y;
    	long int location = 0, BytesPerLine = 0;
    	char tmp[1024*10];
    
    	fp = fopen( "./niu.bmp", "rb" );
    	if (fp == NULL)
    	{
    		return( -1 );
    	}
    
    	rc = fread( &FileHead, sizeof(BITMAPFILEHEADER),1, fp );
    	if ( rc != 1)
    	{
    		printf("read header error!
    ");
    		fclose( fp );
    		return( -2 );
    	}
    
    	//检测是否是bmp图像
    	if (memcmp(FileHead.cfType, "BM", 2) != 0)
    	{
    		printf("it's not a BMP file
    ");
    		fclose( fp );
    		return( -3 );
    	}
    
    	rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
    	if ( rc != 1)
    	{
    		printf("read infoheader error!
    ");
    		fclose( fp );
    		return( -4 );
    	}
    
    	//跳转的数据区
    	fseek(fp, FileHead.cfoffBits, SEEK_SET);
    	//每行字节数
    	BytesPerLine = (InfoHead.ciWidth * InfoHead.ciBitCount + 31) / 32 * 4;
    
    	line_x = line_y = 0;
    	//向framebuffer中写BMP图片
    	while(!feof(fp))
    	{
    		PIXEL pix;
    		unsigned short int tmp;
    		rc = fread( (char *)&pix, 1, sizeof(PIXEL), fp);
    		if (rc != sizeof(PIXEL))
    			break;
    		location = line_x * bits_per_pixel / 8 + (InfoHead.ciHeight - line_y - 1) * xres * bits_per_pixel / 8;
    
    		//显示每一个像素
    		*(fbp + location + 0)=pix.blue;
    		*(fbp + location + 1)=pix.green;
    		*(fbp + location + 2)=pix.red;
    		*(fbp + location + 3)=pix.reserved;
    
    		line_x++;
    		if (line_x == InfoHead.ciWidth )
    		{
    			line_x = 0;
    			line_y++;
    			if(line_y == InfoHead.ciHeight)
    				break;
    		}
    	}
    	fclose( fp );
    	return( 0 );
    }
    


    注意:上面的程序只在framebuffer上显示图片,却没有删除刷新屏幕,可以使用下面的命令恢复屏幕

    保存屏幕信息:dd if=/dev/fb0 of=fbfile 或: cp /dev/fb0 fbfile

    恢复屏幕信息:dd if=fbfile of=/dev/fb0 或: cat fbfile > /dev/fb0






    FrameBuffer系列 之 介绍


    http://blog.csdn.net/younger_china/article/details/14479859


    FrameBuffer系列 之 相关结构与结构体


    http://blog.csdn.net/younger_china/article/details/14480967


    FrameBuffer系列 之 简单编程


    http://blog.csdn.net/younger_china/article/details/14236251


    FrameBuffer系列显示图片


    http://blog.csdn.net/younger_china/article/details/14481755


    FrameBuffer系列一点资源


    http://blog.csdn.net/younger_china/article/details/14482049






    
  • 相关阅读:
    二叉树后序遍历
    [编程题] 赛马
    [编程题] 糖果谜题 C++实现输入未知个整数
    [编程题] 时钟
    [编程题] 会话列表
    A Fast Lock-Free Queue for C++
    Design Hangman
    Design a URL shortener [转]
    ostream 和 ostringsteam 的区别
    Hash Table Collision Handling
  • 原文地址:https://www.cnblogs.com/youngerchina/p/5624535.html
Copyright © 2011-2022 走看看