飞凌嵌入式ElfBoard ELF1板卡-显示bmp图片代码
注意:学习资料可在ElfBoard官方网站“资料”专区获取。本节用到的源码路径:ELF 1开发板资料包\03-例程源码\03-1 命令行例程源码\07_elf1_cmd_bmp
bmp.c
#include "bmp.h"
/*
* @description : 图片显示函数
* @param - *fbp : 映射内存起始地址
* @param - *scrinfo: 屏幕信息结构体
* @param - *bmpname: .bmp位图文件名
* @return : 执行结果
*/
int show_photo(const char *fbp, struct fb_var_screeninfo *scrinfo, const char *bmpname, char mode)
{
if (NULL == fbp || NULL == scrinfo || NULL == bmpname)
return -1;
int line_x = 0, line_y = 0;
unsigned long tmp32 = 0;
unsigned int tmp = 0;
int xres = scrinfo->xres_virtual; //屏幕宽(虚拟)
int bits_per_pixel = scrinfo->bits_per_pixel; //屏幕位数
BitMapFileHeader FileHead;
BitMapInfoHeader InfoHead;
RgbQuad rgb;
unsigned long location = 0;
//打开.bmp文件
FILE *fb = fopen(bmpname, "rb");
if (fb == NULL)
{
printf("fopen bmp error\r\n");
return -1;
}
//读文件信息
if (1 != fread(&FileHead, sizeof(BitMapFileHeader), 1, fb))
{
printf("read BitMapFileHeader error!\n");
fclose(fb);
return -1;
}
if (memcmp(FileHead.bfType, "BM", 2) != 0)
{
printf("it's not a BMP file\n");
fclose(fb);
return -1;
}
//读位图信息
if (1 != fread((char *)&InfoHead, sizeof(BitMapInfoHeader), 1, fb))
{
printf("read BitMapInfoHeader error!\n");
fclose(fb);
return -1;
}
//跳转至数据区
fseek(fb, FileHead.bfOffBits, SEEK_SET);
int len = InfoHead.biBitCount / 8; //原图一个像素占几字节
int bits_len = bits_per_pixel / 8; //屏幕一个像素占几字节//循环显示
while (!feof(fb))
{
tmp = 0;
tmp32 = 0;
rgb.Reserved = 0xFF;
if (len != fread((char *)&rgb, 1, len, fb))
break;
//计算该像素在映射内存起始地址的偏移量
location = line_x * bits_len + (InfoHead.biHeight - line_y - 1) * xres * bits_len;
if (BIT32 == mode)
{
tmp32 |= rgb.Reserved << 24 | rgb.Red << 16 | rgb.Green << 8 | rgb.Blue; // RGB888
*((unsigned long *)(fbp + location)) = tmp32;
}
else if (BIT16 == mode)
{
tmp |= (rgb.Red >> 3) << 11 | (rgb.Green >> 2) << 5 | rgb.Blue >> 3; // RGB565
*((unsigned short *)(fbp + location)) = tmp;
}
else
break;
line_x++;
if (line_x == InfoHead.biWidth)
{
line_x = 0;
line_y++;
if (line_y == InfoHead.biHeight)
break;
}
}
fclose(fb);
return 0;
}
bmp.h
#ifndef __BMP_H__
#define __BMP_H__
#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>
#define BIT16 0
#define BIT32 1
//文件头结构体
typedef struct
{
unsigned char bfType; //文件类型
unsigned long bfSize; //位图大小
unsigned short bfReserved1; //位0
unsigned short bfReserved2; //位0
unsigned long bfOffBits; //到数据偏移量
} __attribute__((packed)) BitMapFileHeader; //使编译器不优化,其大小为14字节
//信息头结构体
typedef struct
{
unsigned long biSize; // BitMapFileHeader 字节数
long biWidth; //位图宽度
long biHeight; //位图高度,正位正向,反之为倒图
unsigned short biPlanes; //为目标设备说明位面数,其值将总是被设为1
unsigned short biBitCount; //说明比特数/象素,为1、4、8、16、24、或32。
unsigned long biCompression;//图象数据压缩的类型没有压缩的类型:BI_RGB
unsigned long biSizeImage; //说明图象的大小,以字节为单位
long biXPelsPerMeter; //说明水平分辨率
long biYPelsPerMeter; //说明垂直分辨率
unsigned long biClrUsed; //说明位图实际使用的彩色表中的颜色索引数
unsigned long biClrImportant; //对图象显示有重要影响的索引数,0都重要。
} __attribute__((packed)) BitMapInfoHeader;
//像素点结构体
typedef struct
{
unsigned char Blue; //该颜色的蓝色分量
unsigned char Green; //该颜色的绿色分量
unsigned char Red; //该颜色的红色分量
unsigned char Reserved; //保留值(亮度)
} __attribute__((packed)) RgbQuad;
int show_photo(const char *fbp, struct fb_var_screeninfo *scrinfo, const char *bmpname, char mode);
#endif //__BMP_H__main.c
#include "bmp.h"
char ver = {"ver01.001"};
int dev_fd;
char dev;
char rgb_mode = BIT16; // BIT16-16位屏幕BIT32-32位屏幕
char bmpname = {0};
/*
* @description: 打印参数设置格式
* @param - pname: 函数名
* @return : 无
*/
static void print_usage(const char *pname)
{
printf("Usage: %s device [-b bits] [-n bmpname] [-v]"
"\n\t'-b bits' for 16 bits_per_pixel or 32 bits_per_pixel"
"\n\t'-n bmpname' for the bmp file name containing the path "
"\n\t'-v' show version"
"\n\texample :--> ./elf1_cmd_lcd_bmp fb0 -b 16 -n /home/root/test1.bmp\n ",
pname);
}
/*
* @description : 解析函数带入参数
* @param - numb: 参数个数
* @param - *param: 带入参数数组指针
* @return : 无
*/
void get_param(int numb, char *param[])
{
int i = 0;
int temp = 0;
if (numb <= 2)
return;
for (i = 2; i < numb; i++)
{
if (!strcmp(param, "-b"))
{
i++;
temp = atoi(param);
if (16 == temp)
{
rgb_mode = BIT16;
}
else if (32 == temp)
{
rgb_mode = BIT32;
}
continue;
}
if (!strcmp(param, "-n"))
{
i++;
strcpy(bmpname, param);
printf("%s", bmpname);
continue;
}
if (!strcmp(param, "-v"))
{
printf("tty_demo ver:%s\n", ver);
continue;
}
}
}
/*
* @description: 主函数
* @param - argc : 参数个数
* @param - *argv: 带入参数数组指针
* @return : 执行结果
*/
int main(int argc, char *argv[])
{
struct fb_var_screeninfo scrinfo;
unsigned long screensize;
char *fbp;
//检测是否有参数
if (argc < 2)
{
print_usage(argv);
exit(1);
}
//检测是否有--h或--help
if ((!strcmp(argv, "--h")) || (!strcmp(argv, "--help")))
{
print_usage(argv);
exit(1);
}
strcpy(dev, "/dev/");
strcat(dev, argv);
//从main函数带入的参数解析
get_param(argc, argv);
//当知道设备名称时可以直接赋值dev,例strcpy(dev, "/dev/fb0");
//打开屏幕外设
dev_fd = open(dev, O_RDWR);
if (!dev_fd)
{
printf("dev_fd open error!\r\n");
return -1;
}
// printf("dev_fd open OK! %d\r\n", dev_fd);
//获取屏幕信息
//若屏幕显示区域大小不合适,可用ioctl(dev_fd, FBIOPUT_VSCREENINFO, &scrinfo)设置
if (ioctl(dev_fd, FBIOGET_VSCREENINFO, &scrinfo))
{
printf("get screen infomation error!\r\n");
return -1;
}
//打印屏幕信息
printf(".xres=%d, .yres=%d, .bit=%d\r\n", scrinfo.xres, scrinfo.yres, scrinfo.bits_per_pixel);
printf(".xres_virtual=%d, .yres_virtual=%d\r\n", scrinfo.xres_virtual, scrinfo.yres_virtual);
if (((16 != scrinfo.bits_per_pixel) && (BIT16 == rgb_mode)) ||
((32 != scrinfo.bits_per_pixel) && (BIT32 == rgb_mode)))
{
printf("screen infomation.bits error!\r\n");
return -1;
}
//计算需要的映射内存大小
screensize = scrinfo.xres_virtual * scrinfo.yres_virtual * scrinfo.bits_per_pixel / 8;
// printf("screensize=%lu!\r\n", screensize);
//内存映射
fbp = (char *)mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0);
if (-1 == (int)fbp)
{
printf("mmap error!\r\n");
return -1;
}
//显示图片
show_photo(fbp, &scrinfo, bmpname, rgb_mode);
//取消映射,关闭文件
munmap(fbp, screensize);
close(dev_fd);
return 0;
}
进程名:elf1_cmd_lcd_bmp
使用方法:./elf1_cmd_lcd_bmp 设备名 [参数选项]… …
页:
[1]