使用libjpeg库在LCD上显示图片

背景:
网上已经有很多关于利用libjpeg显示图片的文章了,因此本文的技术含量不算高。本文是使用libjpeg的v8版本,在开发板的LCD上显示jpg格式图片,关于libjpeg,可到其官方网站下载源码,源码附有许多文档,包括详细的例子(example.c)。
关于如何使用libjpeg,本文不再说明,因为网上文章已经很多了。本文中的代码有几处是自已经修改过的。
1、将所有操作framebuffer的函数放到单独的文件,名称为fb_utils.c,代码主要是来自一个叫ripple的项目。这个文件也用到其它很多地方。
2、libjpeg指定的图片来源有两种,一是文件,一是内存。后者是新版本支持的,旧版本,例如6b,就没有这个函数。

完整的显示jpg图片函数如下:

/**
 * draw_jpeg - Display a jpeg picture from (0, 0) on framebuffer
 * @name: picture name(foo.jpg)
 */

int draw_jpeg(char *name)
{
        struct jpeg_decompress_struct cinfo;
        struct jpeg_error_mgr jerr;
        FILE *infile;
        unsigned char  *buffer;
        int x, y;

        unsigned char *tmp_buf;
        unsigned long size;
        int ret;

        if ((infile = fopen(name, "rb")) == NULL) {
                fprintf(stderr, "open %s failed\n", name);
                return -1;
        }
        cinfo.err = jpeg_std_error(&jerr);
        jpeg_create_decompress(&cinfo);

        // 获取图片文件大小
        fseek(infile, 0L, SEEK_END);
        size = ftell(infile);
        rewind(infile);
        
        tmp_buf = (unsigned char *)malloc(sizeof(char) * size);
        if (tmp_buf == NULL)
        {
                printf("malloc failed.\n");
                return -1;
        }
        ret = fread(tmp_buf, 1, size, infile);
        if (ret != size)
        {
                printf("read jpeg file error.\n");
                return -1;
        }
        // memory
        jpeg_mem_src(&cinfo, tmp_buf, size);        // 指定图片在内存的地址及大小

        
        //jpeg_stdio_src(&cinfo, infile); // 指定图片文件
        
        jpeg_read_header(&cinfo, TRUE);
        jpeg_start_decompress(&cinfo);

        if ((cinfo.output_width > fb_width) || (cinfo.output_height > fb_height)) {
                printf("too large JPEG file,cannot display\n");
                return -1;
        }
        buffer = (unsigned char *) malloc(cinfo.output_width * cinfo.output_components);
        //printf("%d %d\n", cinfo.output_width, cinfo.output_components); /*eg, 240 3(rgb888)*/
        x = y = 0;
        while (cinfo.output_scanline < cinfo.output_height) {
                jpeg_read_scanlines(&cinfo, &buffer, 1);
                if (fb_depth == 16) {
                        unsigned short  color;
                        for (x=0; x < cinfo.output_width; x++) {
                                // LCD为rgb565格式
                                color = make16color(buffer[x*3], buffer[x*3+1], buffer[x*3+2]);
                                fb_pixel(x, y, color);
                        }
                } else if (fb_depth == 24) {
                        // not test
                        memcpy((unsigned char *) fb_mem + y * fb_width * 3,
                                   buffer, cinfo.output_width * cinfo.output_components);
                }
                y++;        // next scanline
        }

        jpeg_finish_decompress(&cinfo);
        jpeg_destroy_decompress(&cinfo);

        fclose(infile);

        free(tmp_buf);

        free(buffer);
        return 0;
}


几点说明:
1、使用图片文件测试,第一种是用jpeg_stdio_src指定图片来源为文件,第二种是将图片读入内存,再使用jpeg_mem_src来指定图片在内存的位置及大小。
2、本文测试所用的LCD格式为rgb565,即16色,而原来图片为24色,所以需要使用一个函数来转换。当得到适合在LCD显示的颜色值后,就可以调用像素函数在LCD上画点了。
就这么简单。
下面是在LCD上显示的图片,使用fb2png截图。

 

左图是rgb565格式,因为LCD就是这种格式,显示正常,而右图是rgb888格式,不能正常显示出来。

关于fb2png这个工具,我找了好久,现在已经不记得原代码出处了。可以到

http://download.csdn.net/detail/subfate/3345143下载,如果没有CSDN的积分,请到

http://www.latelee.org/yetanothertest/tools/下载。


完整的工程及测试用的图片压缩包下载:

http://www.latelee.org/yetanothertest/program/src/jpeg-test-latelee.org.tar.bz2

注:压缩包中的fb_utils.c文件在不断修改,当修改后,恕不更新此处的工程。

©️2020 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值