神级接口——popen的使用

标题popen()函数

功能:获取执行的程序输出的内容到缓存区

popen函数

案例:

利用popen加载开发板中的所有图片,并循环显示一次

在这里插入代码片#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>

//__attribute__((packed)) 把一个结构体压实,自己根据数据的大小分配空间,不进行对齐!

// 14个字节文件头
struct BITMAPFILEHEADER
{
    unsigned short bfType;      // 文件的类型,该值必需是0x4D42,也就是字符'BM'。
    unsigned int bfSize;        // 位图文件的大小,用字节为单位
    unsigned short bfReserved1; // 保留,必须设置为0
    unsigned short bfReserved2; // 保留,必须设置为0
    unsigned int bfOffBits;     // 位图数据距离文件开头偏移量,用字节为单位
} __attribute__((packed));

// 40个字节的信息头
struct WINBMPINFOHEADER
{
    unsigned int biSize;          // BITMAPINFOHEADER结构所需要的字数
    unsigned int biWidth;         // 图像宽度,单位为像素
    unsigned int biHeight;        // 图像高度,单位为像素,负数,则说明图像是正向的
    unsigned short biPlanes;      // 为目标设备说明位面数,其值将总是被设为1
    unsigned short biBitCount;    // 一个像素占用的bit位,值位1、4、8、16、24、32
    unsigned int biCompression;   // 压缩类型
    unsigned int biSizeImage;     // 位图数据的大小,以字节为单位
    unsigned int biXPelsPerMeter; // 水平分辨率,单位 像素/米
    unsigned int biYPelsPerMeter; // 垂直分辨率,单位 像素/米
    unsigned int biClrUsed;       //
    unsigned int biClrImportant;  //
};

// 在px 和 py 的位置上显示pic图片
int show_24_bmp(char *pic, int px, int py)
{

    // 1.打开LCD 设备
    int lcd_fd = open("/dev/fb0", O_RDWR);
    if (lcd_fd < 0)
    {
        perror("lcd_fd init fail:");
        return -1;
    }

    // 2.进行内存映射
    char *lcd_p = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);
    if (lcd_p == MAP_FAILED)
    {
        perror("mmap fail:");
        return -1;
    }

    // 解码图片
    //  1.打开bmp图片
    int fd = open(pic, O_RDWR);
    if (fd < 0)
    {
        perror("打开图片失败\n");
        return -1;
    }

    // 2.读取文件头
    struct BITMAPFILEHEADER file_head;
    read(fd, &file_head, sizeof(file_head));

    // 3.读取信息头
    struct WINBMPINFOHEADER msg_head;
    read(fd, &msg_head, sizeof(msg_head));

    // 输出 bmp 图像的信息
    printf("格式%.2s\n", (char *)&file_head.bfType);
    printf("大小%d\n", file_head.bfSize);
    printf("Width=%d\n", msg_head.biWidth);
    printf("Height=%d\n", msg_head.biHeight);
    printf("位深=%d\n", msg_head.biBitCount);

    // 根据图片的宽度和高度和位深,定义一个像素点缓存区
    int w = msg_head.biWidth;
    int h = msg_head.biHeight;
    int bit = msg_head.biBitCount;

    char rgb[w * h * bit / 8]; // bit/8 求出一个像素多少个字节

    // 读取图片的像素数据到缓存区
    read(fd, rgb, sizeof(rgb));
    // 关闭图片
    close(fd);

    // 把24位图转换为32位图
    //  把rgb转换为argb
    char argb[w * h * 4]; // char argb[200*200*4];
    for (int i = 0; i < w * h; i++)
    {
        argb[0 + i * 4] = rgb[0 + i * 3];
        argb[1 + i * 4] = rgb[1 + i * 3];
        argb[2 + i * 4] = rgb[2 + i * 3];
        argb[3 + i * 4] = 0;
    }

    // 翻转放入LCD 设备中
    for (int y = 0; y < h; y++)
    {
        for (int x = 0; x < w * 4; x++) // 赋值一行
        {
            // 提示显示的时候,不要出界
            lcd_p[(y + py) * 800 * 4 + (x + px * 4)] = argb[(h - 1 - y) * w * 4 + x];
        }
    }

    // 解除映射
    munmap(lcd_p, 800 * 480 * 4);
    // 关闭LCD设备
    close(lcd_fd);
}

// 利用popen加载开发板中的所有bmp图片,并循环显示一次
int main(int argc, char *argv[])
{
    FILE *fp = popen("find / -name  \"*.bmp\"", "r");
    if (fp == NULL)
    {
        perror("加载失败");
        return -1;
    }

    while (!feof(fp))
    {
        char buf[1024] = {0};
        char *find = NULL;
        fgets(buf, 1024, fp);
        find = strchr(buf,'\n');
        if (find)
            *find = '\0';
        show_24_bmp(buf, 0, 0);
        sleep(1);
    }

    pclose(fp);
}

1.bmp的解码,一般bmp是24位的,而开发板是32位的,所以我们要把24位图片转换为32位图才能在开发板上显示。
2.用fgets函数会读取换行符,我们要去掉换行符,不然你打不开图片会显示如下错误:
打开图片失败
解决办法是

        char buf[1024] = {0};
        char *find = NULL;
        fgets(buf, 1024, fp);
        find = strchr(buf,'\n');
        if (find)
            *find = '\0';
        show_24_bmp(buf, 0, 0);
        sleep(1);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

obsidianer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值