LittlevGL图形框架扩展 - JPEG图片的支持

简介: 在轻量级RTOS GUI图形库中,LittlevGL是一个使用C语言开发,开源免费的GUI,支持触摸屏,鼠标,键盘多种操作,移植简单方便,在丰富的控件基础上还可以自定义控件,开发者一直在不断完善更新,相对于其他GUI,LittlevGL在硬件资源不足(RAM < 100kbytes)的情况下存在较大的优势,在240*240的显示屏上显示一张图片,RAM缓冲区设置为2Kbytes即可。AliOS Things 目前最新版本已经集成LittlevGL,并且在智能穿戴设备项目上已商用。
转自HaaS技术社区

在轻量级RTOS GUI图形库中,LittlevGL是一个使用C语言开发,开源免费的GUI,支持触摸屏,鼠标,键盘多种操作,移植简单方便,在丰富的控件基础上还可以自定义控件,开发者一直在不断完善更新,相对于其他GUI,LittlevGL在硬件资源不足(RAM < 100kbytes)的情况下存在较大的优势,在240*240的显示屏上显示一张图片,RAM缓冲区设置为2Kbytes即可。

AliOS Things 目前最新版本已经集成LittlevGL,并且在智能穿戴设备项目上已商用。

image.png

LittlevGL对于图片跟字体的使用是预先要使用外部工具,对图片跟字体转成二进制文件,然后直接使用,在一些简单固定显示的应用场景是可以满足的,而且对内存消耗会比较少。但是在一些复杂的应用场景就无法满足了,比如相机应用中拍照生成的图片格式大多为JPEG的,相册中显示图片就无法提前进行转换,或者遇到服务端下发JEPG图片情况,因此需要对LittlevGL进行扩展。

开源libJPEG库是用于编码数据为JPEG格式或者解码JPEG格式图片的常用库,而libJPEG-turbo则效率更高。考虑到未来除了需要解码JPEG可能还会遇到需要压缩JPEG图片的场景,因此最终使用libJPEG-turbo来丰富LittlevGL对图片支持。

JPEG图像的解压缩操作过程

1.为JPEG对象分配空间并初始化

2.指定解压缩数据源

3.获取文件信息

4.为解压缩设定参数,包括图像大小,颜色空间

5.开始解压缩

6.取出数据

7.解压缩完毕

8.释放资源

为JPEG对象分配空间并初始化

解压缩过程中使用的JPEG对象是一个jpeg_decompress_struct的结构体。同时还需要定义一个用于错误处理的结构体对象,标准的错误结构体是jpeg_error_mgr。

#if !USE_LV_DRAW_IMG_JPEG_DECODER_HW_MODE
 
static struct jpeg_decompress_struct jpeg_info;
 
static struct jpeg_error_mgr jpeg_error_mgr;
 
#endif

初始化jpeg_info结构,并将错误处理结构对象绑定在JPEG对象上,这个标准的错误处理结构将使程序在出现error时调用exit退出程序,如果不希望使用标准的错误处理方式,则可以通过自定义退出函数的方法自定义错误处理结构。

    jpeg_create_decompress(&jpeg_info);
 
    jpeg_info.err = jpeg_std_error(&jpeg_error_mgr);
 
    jpeg_error_mgr.error_exit = jpeg_error_exit;

对jpeg_info分配内存并将图片的缺省信息填充到jpeg_info。

    jpeg_mem_src(&jpeg_info, data_buf, img_dsc->data_size);
 
 
    if(jpeg_read_header(&jpeg_info, TRUE) == -1) {
 
        LOGE("lv_img_decoder_open_jpeg: read header err !!\n");
 
        if(from_file == 1) {
 
            jpeg_free(data_buf);
 
            data_buf = NULL;
 
        }
 
        return LV_IMG_DECODER_OPEN_FAIL;
 
    }

此时,常见的可用信息包括图像的宽jpeg_info.image_width,高jpeg_info.image_height,色彩空间jpeg_info.jpeg_color_space,颜色通道数jpeg_info.num_components等。在完成jpeg_read_header调用后,开始解压缩之前就可以进行解压缩参数的设定,也就是为jpeg_info结构的成员赋值。

可以设定解出来的图像与原图的比例,也可以设定输出图像的色彩空间,即cinfo.out_color_space。原图比例是使用scale_num和scale_denom两个参数,解出来的图像大小就是scale_num/scale_denom,当前仅支持1/1, 1/2, 1/4,和1/8这几种缩小比例,如果没有额外要求,以上参数使用默认即可。

比如要取得1/2原图的图像,把一个原本彩色的图像由真彩色JCS_RGB变为灰度JCS_GRAYSCALE。需要如下设定:

    jpeg_info.scale_num=1;
 
    jpeg_info.scale_denom=2;
 
    jpeg_info.out_color_space=JCS_GRAYSCALE;

根据设定的解压缩参数进行图像解压缩操作。

    if((jpeg_start_decompress(&jpeg_info) == false) || (jpeg_err == 1)) {
 
        LOGE("lv_img_decoder_open_jpeg: decompress failed !!\n");
 
        if(from_file == 1) {
 
            jpeg_free(data_buf);
 
            data_buf = NULL;
 
        }
 
        return LV_IMG_DECODER_OPEN_FAIL;
 
    }

在完成解压缩操作后,要开始为取走数据做准备,将解压后的图像信息填充至jpeg_info结构中。比如,输出图像宽度jpeg_info.output_width,输出图像高度jpeg_info.output_height,每个像素中的颜色通道数jpeg_info.output_components(比如灰度为1,全彩色为3)等。一般情况下,这些参数是在jpeg_start_decompress执行后才被填充到jpeg_info中的,如果希望在调用jpeg_start_decompress之前就获得这些参数,可以通过调用jpeg_calc_output_dimensions()的方法来实现。

    uint8_t *rgb888_buf = NULL;
 
    uint32_t out_buffer_size = jpeg_info.image_width*jpeg_info.image_height*jpeg_info.num_components;
 
    rgb888_buf = jpeg_malloc(out_buffer_size, 0);
 
    if(rgb888_buf == NULL) {
 
        LOGI("lv_img_decoder_open_jpeg: no enough memory!!\n");
 
        goto err;
 
    }

解压缩的数据是按照行取出的,数据像素按照scanline来存储,scanline是从左到右,从上到下的顺序,每个像素对应的各颜色或灰度通道数据是依次存储,比如一个24-bitRGB真彩色的图像中,一个scanline中的数据存储模式是R,G,B,R,G,B,R,G,B,...,每条scanline是一个JSAMPLE类型的数组,一般来说就是unsigned char,定义于jmorecfg.h中。除了JSAMPLE,IJG还定义了JSAMPROW和JSAMPARRAY,分别表示一行JSAMPLE和一个2D的JSAMPLE数组。

jpeg_info.output_scanline表示当前已经读取的行数,如此即可依次读出图像的所有数据,并填充到缓冲区中。

    while (jpeg_info.output_scanline<jpeg_info.output_height)
 
    {
 
        JSAMPROW out_str  = (JSAMPROW)(rgb888_buf +
 
                     jpeg_info.output_scanline*jpeg_info.image_width*jpeg_info.num_components);
 
        if((jpeg_read_scanlines(&jpeg_info, &out_str, 1) != 1) || (jpeg_err == 1)) {
 
            LOGE("lv_img_decoder_open_jpeg: scan line failed!!\n");
 
            jpeg_free((void *)rgb888_buf);
 
            goto err;
 
        }
 
    }

解压缩完毕调用jpeg_finish_decompress,然后释放jpeg_destroy_decompress

        jpeg_finish_decompress(&jpeg_info);
 
        jpeg_destroy_decompress(&jpeg_info);

开发者支持

如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号。

image.png

更多技术与解决方案介绍,请访问HaaS官方网站https://haas.iot.aliyun.com

相关文章
|
存储 缓存 算法
内存分配不再神秘:深入剖析malloc函数实现原理与机制
内存分配不再神秘:深入剖析malloc函数实现原理与机制
|
存储 C语言
C语言顺序结构:基础与实践
C语言,作为一种广泛使用的编程语言,其程序结构可以分为三种基本类型:顺序结构、选择结构和循环结构。在这篇文章中,我们将重点讨论顺序结构的概念、特点以及如何在C语言中实现顺序结构的程序设计。
861 1
|
Python
python pip设置代理
python pip设置代理
3695 0
|
6月前
|
人工智能 API
多模型时代的 AI API 架构设计方法论 ——从单一调用到可演进系统的工程实践
本文探讨多模型AI应用中API接入层的演进,指出其正从简单调用接口升级为关键基础设施。针对模型耦合、策略分散、稳定性不足等工程挑战,提出统一接口方案,实现模型抽象、业务解耦、策略集中与弹性扩展,提升系统长期可维护性与生产稳定性。
|
8月前
|
自然语言处理 搜索推荐 机器人
阿里云中国智能客服市场份额蝉联第一
国际数据公司IDC发布《中国智能客服市场份额,2024》,阿里云 2024 年在中国智能客服市场份额占比 11.4%,持续位居第一。累计服务互联网、零售、金融、保险、医疗、教育、政务、交通物流、汽车等行业超 5000 家企业客户。
|
10月前
|
机器学习/深度学习 算法 数据挖掘
足球比赛的镜头如何变成数据:从视频分析到实时数据应用
足球视频分析利用计算机视觉与深度学习技术,将比赛镜头转化为球员位置、动作及赛事事件等结构化数据,助力战术制定、表现评估与观赛体验升级,推动体育智能化发展。
|
自然语言处理 搜索推荐 机器人
只需几个演示就能对齐大模型,杨笛一团队提出的DITTO竟如此高效
【6月更文挑战第22天】斯坦福团队推出DITTO,一种只需少量演示即可高效对齐大型语言模型的新技术。DITTO借助用户演示生成在线比较数据,实现模型对齐,无需大规模数据集。在用户研究中,DITTO表现优于传统方法,平均胜出19%,开创了LLMs对齐的简洁途径,适用于个性化助手和聊天机器人等场景。然而,它可能不适用于需要大量数据的任务,训练速度较慢,且可能无法完全匹配用户意图。[论文链接](https://arxiv.org/pdf/2406.00888)
492 10
|
JSON 数据挖掘 API
抖音电商新篇章:douyin.item_get API接口的介绍
抖音商品详情API接口助力电商与数据分析!在电商短视频融合趋势下,抖音成为商品交易的重要平台。该API可合法高效获取商品详情(如名称、价格、评价等),帮助电商优化策略、分析人员挖掘市场趋势、开发者构建应用,推动业务增长。请求方式为HTTP(GET/POST),通过商品ID查询,返回JSON格式数据,灵活易用。
Qt6.5打包(QT windeployqt不是内部或外部命令、QT错误:缺少libgcc_s_seh-1.dll ,无法正常启动(0xc000007b) 问题解决方法)
Qt6.5打包(QT windeployqt不是内部或外部命令、QT错误:缺少libgcc_s_seh-1.dll ,无法正常启动(0xc000007b) 问题解决方法)
2134 1
|
Ubuntu 安全 Unix
在Linux中,有哪几种linux/unix发行版本?
在Linux中,有哪几种linux/unix发行版本?

热门文章

最新文章