#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>
/***************************************************
* BMP文件信息头结构
***************************************************/
//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]; /* 重要颜色索引的个数 */
} BITMAPINFOHEADER; /* 位图信息头结构 */
typedef struct
{
unsigned char blue;
unsigned char green;
unsigned char red;
} PIXEL;
/****************************************************/
BITMAPFILEHEADER FileHead;
BITMAPINFOHEADER InfoHead;
char *fbp = 0;
int xres = 0;
int yres = 0;
int bits_per_pixel = 0;
int put_to_framebuf ( char *bmpfile );
long chartolong ( char * string, int length );
/******************************************************************************
*
******************************************************************************/
int main ( int argc, char *argv[] )
{
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
/***********************************************************帧缓存相关的*/
// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd)
{
printf("Error cannot open framebuffer device.\n");
exit(1);
}
// Get fixed screen information
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)){
printf("Error reading fixed information.\n");
exit(2);
}
// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
printf("Error reading variable information.\n");
exit(3);
}
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
xres = vinfo.xres;
yres = vinfo.yres;
bits_per_pixel = vinfo.bits_per_pixel;
// Figure out the size of the screen in bytes
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
// Map the device to memory
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.\n");
exit(4);
}
printf("sizeof header=%d\n", sizeof(BITMAPFILEHEADER));
printf("into show_bmp fun\n");
/*******************************************************************************/
int i;
for(i = 1; i < sizeof(argv);i++){
put_to_framebuf( argv ); //显示图像
if(argc != 2) //判断如果只有一张图片则不进行延时
sleep(1);
}
munmap(fbp, screensize);
close(fbfd);
return 0;
}
/******************************************************************************
*name : put_to_framebuffers
*参数介绍 : line_x,line_y是坐标偏移量;
start_x,start_y是数据写入计数器;
addr_x,addr_y,是写入数据的地址;
功能 : 将一个24位的图片显示在显示屏上
返回值 : 无
time : 2010.7.21
******************************************************************************/
int put_to_framebuf( char *bmpfile )
{
FILE *fp;
int rc;
int ciBitCount, ciWidth, ciHeight,cfoffBits;
int line_x, line_y,start_x,start_y,addr_x,addr_y;
long int location = 0 ;
/* 打开位图文件 */
fp = fopen( bmpfile, "rb" );
if (fp == NULL){
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("it's 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 );
}
/*将数组中的数连接成32位的数*移位实现*/
ciWidth = InfoHead.ciWidth[3]<<24 |InfoHead.ciWidth[2]<<16 | \
InfoHead.ciWidth[1]<<8 |InfoHead.ciWidth[0];
ciHeight = InfoHead.ciHeight[3]<<24|InfoHead.ciHeight[2]<<16| \
InfoHead.ciHeight[1]<<8|InfoHead.ciHeight[0];
ciBitCount = InfoHead.ciBitCount[3]<<24|InfoHead.ciBitCount[2]<<16| \
InfoHead.ciBitCount[1]<<8|InfoHead.ciBitCount[0];
cfoffBits = FileHead.cfoffBits[3]<<24|FileHead.cfoffBits[2]<<16| \
FileHead.cfoffBits[1]<<8|FileHead.cfoffBits[0];
/*也可使用内存复制实现数据的转换***************//*
ciWidth = (int) chartolong( InfoHead.ciWidth, 4 );
ciHeight = (int) chartolong( InfoHead.ciHeight, 4 );
ciBitCount = (int) chartolong( InfoHead.ciBitCount, 4 );*/
fseek(fp, cfoffBits, SEEK_SET); /*设置偏移量*/
printf("width=%d, height=%d, bitCount=%d, offset=%d\n", ciWidth, ciHeight, ciBitCount, (int)chartolong(FileHead.cfoffBits, 4));
if(ciWidth>240&&ciHeight>320){printf("图片过大!无法预览!\n"); return 0;}
if(ciWidth<240||ciHeight<320){ //如果是小图片,则按其尺寸大小在屏幕的中间显示
line_y = (ciHeight - 320)/2;
if(ciWidth<=ciHeight)
line_x = (240 - ciWidth)/2;
else
line_x = 0;
}
else{
line_x =0;
line_y =0;
}
start_x= start_y = 0;
while(!feof(fp))
{
;PIXEL pix;
unsigned short int color;
char rgb[2];
addr_x = line_x + start_x;
addr_y = line_y + start_y;
location = addr_x * bits_per_pixel / 8 + (ciHeight - addr_y - 1) * xres * bits_per_pixel / 8;
if(chartolong(InfoHead.ciBitCount,2) == 24){
rc = fread( (char *)&pix, 1, 3, fp );
if (rc != 3 )
{ break; }
color=(pix.red >>3)<<11 | (pix.green>>2)<<5 | pix.blue>>3; //将24位的数据转换成十六位565格式
}
else if(chartolong(InfoHead.ciBitCount,2) == 16){
rc = fread( (char *)&rgb,1,2, fp );
if (rc != 2 )
{ break; }
color = rgb[0] | rgb[1]<<8;
}
*((unsigned short int*)(fbp + location)) = color ;
start_x++;
if (start_x == ciWidth ){
start_x = 0;
start_y++;
if(start_y== ciHeight)
{
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 );
}
|