Linux 开发板 lcd显示jpg,gif

一帧帧的静态jpg图片进行延时显示

struct my_error_mgr
{
    struct jpeg_error_mgr pub; /* "public" fields */

    jmp_buf setjmp_buffer; /* for return to caller */
};

typedef struct my_error_mgr *my_error_ptr;

/*
 * Here's the routine that will replace the standard error_exit method:
 */

METHODDEF(void)
my_error_exit(j_common_ptr cinfo)
{
    /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
    my_error_ptr myerr = (my_error_ptr)cinfo->err;

    /* Always display the message. */
    /* We could postpone this until after returning, if we chose. */
    (*cinfo->err->output_message)(cinfo);

    /* Return control to the setjmp point */
    longjmp(myerr->setjmp_buffer, 1);
}

/* lcd_draw_jpeg        : 指定静态/动态图像数据显示
 * int x, int y         : 图像显示起点位置
 * const char *pathname : 指定静态数据源  (例如 图片文件)
 * char *jpeg_buf       : 指定动态数据源  (例如 摄像头获取到的数据)
 * int jpeg_size        : 动态数据的大小
 * int zoom_flag        : 缩放比例     (分子:1/分母:zoom_flag,例如1/2缩小一倍)
 */

int lcd_draw_jpeg(int x, int y, const char *pathname, char *jpeg_buf, int jpeg_size, int zoom_flag)
{
    int img_fd;
    char *img_buf;
    int img_size;
    unsigned char *argb_buf = lcd_buf;
    int x_c = x;

    // jpeg解压缩对象和错误处理对象
    struct jpeg_decompress_struct cinfo;
    struct my_error_mgr jerr;
    struct stat statbuf;

    if (pathname != NULL)
    {
        // 打开图片文件
        img_fd = open(pathname, O_RDWR);

        if (img_fd == -1)
        {
            printf("open jpeg file [ %s ] failed !\n", pathname);
            return -1;
        }

        // 获取文件大小
        fstat(img_fd, &statbuf);

        img_size = statbuf.st_size;

        img_buf = calloc(1, img_size);

        read(img_fd, img_buf, img_size);
    }
    else
    {
        img_size = jpeg_size;
        img_buf = jpeg_buf;
    }

    /* Step 1: 分配并初始化jpeg解压缩对象 */

    // 错误处理
    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;

    if (setjmp(jerr.setjmp_buffer))
    {
        // 释放资源
        jpeg_destroy_decompress(&cinfo);
        if (pathname != NULL)
        {
            close(img_fd);
        }
        return -1;
    }

    // 初始化解压缩对象
    jpeg_create_decompress(&cinfo);

    /* Step 2: 指定解压缩数据源 (eg, a file) */

    jpeg_mem_src(&cinfo, img_buf, img_size);

    /* Step 3: 读取图片文件的详细信息 */
    (void)jpeg_read_header(&cinfo, TRUE);

    /* Step 4: 解压缩的参数设置,一般默认 */
    cinfo.scale_num = 1;           // 1
    cinfo.scale_denom = zoom_flag; //

    /* Step 5: 开始解压 */
    (void)jpeg_start_decompress(&cinfo);

    int i, r, g, b, color;

    /* Step 6: 取出数据 */
    // cinfo.output_scanline:当前行号
    // cinfo.output_height:对应的图片的高
    // cinfo.output_width:对应的图片的宽
    while (cinfo.output_scanline < cinfo.output_height)
    {
        argb_buf = lcd_buf;
        // 每次读取一行的数据
        (void)jpeg_read_scanlines(&cinfo, (JSAMPARRAY)&argb_buf, 1);

        for (i = 0; i < cinfo.output_width; i++)
        {
            b = *(argb_buf + 2);
            g = *(argb_buf + 1);
            r = *(argb_buf + 0);

            // 合并
            color = b;
            color |= (g << 8);
            color |= (r << 16);

            lcd_draw_point(x, y, color);

            argb_buf += 3;
            x++;
        }
        y++;
        x = x_c;
    }

    /* Step 7: 解压完毕 */
    (void)jpeg_finish_decompress(&cinfo);

    /* Step 8: 释放资源 */
    jpeg_destroy_decompress(&cinfo);

    if (pathname != NULL)
    {
        close(img_fd);
    }

    return 0;
}

int dev_init()
{
    lcd_fd = open("/dev/fb0", O_RDWR);

    // 错误处理
    if (lcd_fd == -1)
    {
        printf("open lcd device failed!\n");
        return -1;
    }

    // 2,为lcd设备建立内存映射关系
    lcd_ptr = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);

    if (lcd_ptr == MAP_FAILED)
    {
        printf("mmap failed!\n");
        return -2;
    }

    // 清除屏幕
    memset(lcd_ptr, 0, 800 * 480 * 4);

    return 0;
}

void dev_uninit()
{
    munmap(lcd_ptr, 800 * 480 * 4);
    close(lcd_fd);
}

int main(void)
{
    // 1,设备的初始化
    int rt = dev_init();

    if (rt != 0)
    {
        printf("rt : %d\n", rt);
        return -1;
    }

    char buf[4096];
    

    int i;
    unsigned int *mem_p = (unsigned int *)mmap(NULL, 800 * 480 * 4,
                                 PROT_READ | PROT_WRITE,
                                 MAP_SHARED, lcd_fd, 0);
	for (int i = 0; i < 800 * 480; ++i) // 清空屏幕
	{
		*(mem_p + i) = 0x00FFFFFF;
	}
	
    for (i = 0; i < 70; i++)
    {
        if (i < 10)
        {
            sprintf(buf, "IMG0000%d.jpg", i);
            lcd_draw_jpeg(i*7, i*3, buf, NULL, 0, 1);
        }
        else
        {
            sprintf(buf, "IMG000%d.jpg", i);
            lcd_draw_jpeg(i*7, i*2, buf, NULL, 0, 1);
        }

        /* 延时进行显示 */
        usleep(50000);
    }



    // 3,设备的卸载
    dev_uninit();

    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值