注意:学习资料可在ElfBoard官方网站“资料”专区获取。
本节用到的源码路径:ELF 1开发板资料包\03-例程源码\03-1 命令行例程源码\07_elf1_cmd_bmp
bmp.c
- #include "bmp.h"
- /*
- * @description : 图片显示函数
- * [url=home.php?mod=space&uid=3142012]@param[/url] - *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
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define BIT16 0
- #define BIT32 1
- //文件头结构体
- typedef struct
- {
- unsigned char bfType[2]; //文件类型
- 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[20] = {"ver01.001"};
- int dev_fd;
- char dev[20];
- char rgb_mode = BIT16; // BIT16-16位屏幕 BIT32-32位屏幕
- char bmpname[50] = {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[i], "-b"))
- {
- i++;
- temp = atoi(param[i]);
- if (16 == temp)
- {
- rgb_mode = BIT16;
- }
- else if (32 == temp)
- {
- rgb_mode = BIT32;
- }
- continue;
- }
- if (!strcmp(param[i], "-n"))
- {
- i++;
- strcpy(bmpname, param[i]);
- printf("%s", bmpname);
- continue;
- }
- if (!strcmp(param[i], "-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[0]);
- exit(1);
- }
- //检测是否有--h或--help
- if ((!strcmp(argv[1], "--h")) || (!strcmp(argv[1], "--help")))
- {
- print_usage(argv[0]);
- exit(1);
- }
- strcpy(dev, "/dev/");
- strcat(dev, argv[1]);
- //从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 设备名 [参数选项]… …
|