在帧缓冲上显示jpg格式的图片

ice00 2011-05-26

编译出现错误/opt/CodeSourcery/Sourcery_G++_Lite/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/../../../../arm-none-linux-gnueabi/bin/ld: cannot find –ljpeg

原因是用的是主机上的库,用交叉编译器的话需要把库进行交叉编译。

交叉编译jpeg-6b,交叉编译器为arm-none-linux-gnueabi-

步骤1:下载jpeg-6b.tar.gz

http://code.google.com/p/google-desktop-for-linux-mirror/downloads/detail?name=jpeg-6b.tar.gz&can=2&q=

步骤2:解压缩 tar –xvzf 。。。 

步骤3:./configure

步骤4:修改Makefile

prefix = /opt/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/usr

exec_prefix = /opt/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/usr

# The name of your C compiler:

CC= arm-none-linux-gnueabi-gcc

# library (.a) file creation command

AR= /opt/CodeSourcery/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi-ar rc

# second step in .a creation (use "touch" if not needed)

AR2=/opt/CodeSourcery/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi-ranlib

步骤5:make & make install

安装好以后就在这2个目录下增加了如下文件:
/opt/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/usr/include
jerror.h
jmorecfg.h
jconfig.h
jpeglib.h
/opt/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/usr /lib
libjpeg.a
libjpeg.la
libjpeg.so
libjpeg.so.62
libjpeg.so.62.0.0
编译程序的时候记得加上 -ljpeg
不然大概就有下面这些
/tmp/cc4aJtAS.o: In function `write_JPEG_file':
/tmp/cc4aJtAS.o(.text+0x20): undefined reference to `jpeg_std_error'
/tmp/cc4aJtAS.o(.text+0x3c): undefined reference to `jpeg_CreateCompress'
/tmp/cc4aJtAS.o(.text+0x88): undefined reference to `jpeg_stdio_dest'
/tmp/cc4aJtAS.o(.text+0xbc): undefined reference to `jpeg_set_defaults'
/tmp/cc4aJtAS.o(.text+0xd0): undefined reference to `jpeg_set_quality'
/tmp/cc4aJtAS.o(.text+0xe0): undefined reference to `jpeg_start_compress'
/tmp/cc4aJtAS.o(.text+0x140): undefined reference to `jpeg_write_scanlines'
/tmp/cc4aJtAS.o(.text+0x168): undefined reference to `jpeg_finish_compress'
/tmp/cc4aJtAS.o(.text+0x17c): undefined reference to `jpeg_destroy_compress'

libjpeg函数库介绍

JPEG是CCITT和ISO定义的一种连续色调图像压缩标准[2]。JPEG是一种有损图像压缩标准,其基础是DCT变换(离散余弦变换)。JPEG图像的压缩过程分为三步:DCT计算,量化,变长编码分配。尽管CCITT定义了JPEG图像压缩标准,但是却并没有为JPEG定义标准的文件格式。这导致了现实世界中出现了各种各样的JPEG文件格式,而一种被称为JFIF的JPEG文件格式逐渐成为JPEG文件格式的主流。

libjpeg是一个被广泛使用的JPEG压缩/解压缩函数库(至少在Unix类系统下是广泛使用的),它能够读写JFIF格式的JPEG图像文件,通常这类文件是以.jpg或者.jpeg为后缀名的。通过libjpeg库,应用程序可以每次从JPEG压缩图像中读取一个或多个扫描线(scanline,所谓扫描线,是指由一行像素点构成的一条图像线条),而诸如颜色空间转换、降采样/增采样、颜色量化之类的工作则都由libjpeg去完成了。

要使用libjpeg,需要读者对数字图像的基本知识有初步的了解。对于libjpeg而言,图像数据是一个二维的像素矩阵。对于彩色图像,每个像素通常用三个分量表示,即R(Red)、G(Green)、B(Blue)三个分量,每个分量用一个字节表示,因此每个分量的取值范围从0到255;对于灰度图像,每个像素通常用一个分量表示,一个分量同样由一个字节表示,取值范围从0到255。由于本文不会涉及到索引图像,因此这里略去对索引图像的说明。

在libjpeg中,图像数据是以扫描线的形式存放的。每一条扫描线由一行像素点构成,像素点沿着扫描线从左到右依次排列。对于彩色图像,每个分量由三个字节组成,因此这三个字节以R、G、B的顺序构成扫描线上的一个像素点。一个典型的扫描线形式如下:

      R,G,B,R,G,B,R,G,B,…

通过libjpeg解压出来的图像数据也是以扫描线的形式存放的。

在本文中,只涉及到JPEG的解压缩,因此只对libjpeg的解压过程进行说明,有关libjpeg的压缩过程和其它高级用法,请参考[3]。一般地,libjpeg的解压过程如下:

1、分配并初始化一个JPEG解压对象(本文中将JPEG解压对象命名为cinfo):

    struct jpeg_decompress_struct cinfo;

    struct jpeg_error_mgr jerr;

    ...

    cinfo.err = jpeg_std_error(&jerr);

    jpeg_create_decompress(&cinfo);

2、指定要解压缩的图像文件:

    FILE * infile;

    ...

    if ((infile = fopen(filename, "rb")) == NULL) {

        fprintf(stderr, "can't open %s\n", filename);

        exit(1);

    }

    jpeg_stdio_src(&cinfo, infile);

3、调用jpeg_read_header()获取图像信息:

    jpeg_read_header(&cinfo, TRUE);

4、这是一个可选步骤,用于设置JPEG解压缩对象cinfo的一些参数,本文可忽略;

5、调用jpeg_start_decompress()开始解压过程:

    jpeg_start_decompress(&cinfo);

调用jpeg_start_decompress()函数之后,JPEG解压缩对象cinfo中的下面这几个字段将会比较有用:

l output_width               这是图像输出的宽度

l output_height                     这是图像输出的高度

l output_components            每个像素的分量数,也即字节数

这是因为在调用jpeg_start_decompress()之后往往需要为解压后的扫描线上的所有像素点分配存储空间,这个空间的大小可以通过output_width * output_componets确定,而要读取的扫描线的总数为output_height行。

6、读取一行或者多行扫描线数据并处理,通常的代码是这样的:

      while (cinfo.output_scanline < cinfo.ouput_height) {

             jpeg_read_scanlines();

             /* deal with scanlines */

      }

对扫描线的读取是按照从上到下的顺序进行的,也就是说图像最上方的扫描线最先被jpeg_read_scanlines()读入存储空间中,紧接着是第二个扫描线,最后是图像底边的扫描线被读入存储空间中。

7、调用jpeg_finish_decompress()完成解压过程:

    jpeg_finish_decompress(&cinfo);

8、调用jpeg_destroy_decompress()释放JPEG解压对象cinfo:

    jpeg_destroy_decompress(&cinfo);

以上就是通过libjpeg函数解压JPEG压缩图像的基本过程,由于本文不涉及libjpeg的高级特性和用法,因此,上面的介绍对于说明本文中要用到的libjpeg的功能已经足够了。

另外一个需要说明地方是:由于作者所用的Framebuffer设备的颜色深度为16位,颜色格式为5-6-5格式——即R(红色)在16bit中占据高5位,G(绿色)在16bit中占据中间6位,B(蓝色)在16bit中占据低5位;而libjpeg解压出来的图像数据为24位RGB格式,因此必须进行转换。对于24位的RGB,每个字节表示一个颜色分量,因此转换的方式为:对于R字节,右移3位,对于G字节,右移2位,对于B字节,右移3位,然后将右移得到的值拼接起来,就得到了16位的颜色值。在后面的程序中,将把24位的颜色称为RGB888,而把16位颜色值称为RGB565,这种命名方式可能不太规范,不过无论如何,在本文中就这样称呼了。另外,读者可能会想到,上面这种直接将颜色分量的低位丢弃的方式不是会导致图像细节的丢失吗?比如,对于24位颜色的R字节,假如原来低3位的值在0~7之间均匀分布,转换之后,所有这低3位的值全部都变成了0,这就是颜色细节的丢失。为了处理这个问题,可以采用误差扩散算法或者抖动算法来完成颜色转换。为了保持程序的简单,本文中仍然只采用上面提到的最简单的转换方式——而且事实表明,这样做得到的结果并不差。

相关推荐

超算小站 / 0评论 2019-10-24

TimelessFaith / 0评论 2017-06-29