现在的位置: 首页 > 综合 > 正文

使用libjpeg对图像进行压缩

2013年08月12日 ⁄ 综合 ⁄ 共 2035字 ⁄ 字号 评论关闭

  libjpeg 是一个完全用C语言编写的库,包含了被广泛使用的JPEG解码、JPEG编码和其他的JPEG功能的实现。Libjpeg不仅可以把bmp格式转化成jpg格式,还支持其他格式的转化成jpg格式(例如ppm,gif,targa,rle等)。

转化流程如下:

(1) 分配和初始化一个JPEG压缩对象

libjpeg中,JPEG压缩对象被定义为“struct  jpeg_compress_struct(这个结构体内部有一些子结构体,这些子结构体时通过“malloc”来分配空间的,我们的程序不会直接使用这些结构体)

我们还需要定于错误处理器。这里我们仅使用默认的错误处理器,默认的错误处理器会把警告/错误信息输出到stderr,如果出现致命错误,将会调用exit()退出程序。

绑定错误处理器的代码如下:

       struct jpeg_compress_struct cinfo;

       struct jpeg_error_mgr jerr;

       ...

       cinfo.err = jpeg_std_error(&jerr);

       jpeg_create_compress(&cinfo);

jpeg_create_compress会分配一小段内存,如果我们机器内存过少则会分配失败。在这种情况下error handler会处理错误并退出程序。这就是为什么error handler为什么需要首先进行初始化的原因。

 

(2) 指定压缩数据保存的位置

Libjpeg库把压缩后的数据传输到“数据目的”模块。在本库中包含把数据写入到标准流的“数据目的”模块。如果想把数据写入到其他地方(比如内存),可以自定义“数据目的”模块。以下是示例代码:

 

     FILE * outfile;

       ...

       if ((outfile = fopen(filename, "wb")) == NULL) {

       writeLog(…);

       }

jpeg_stdio_dest(&cinfo, outfile);

最后一个函数调用了标准“数据目的”模块。

可以选择在设置参数(步骤3)后再数据目的,但不能在jpeg_start_compress()jpeg_finish_compress()之间更改数据目的。

(3) 设置压缩对象的参数

我们必须在JPEG压缩对象中设置源图片的以下信息:

       image_width             图片的宽度,以像素为单位

       image_height             图片的高度,以像素为单位

      input_components     色彩通道数(每像素采样)

       in_color_space    源文件的色彩空间

      input_components1代表灰度图,在等于3时代表彩色位图图像

      in_color_spaceJCS_GRAYSCALE表示灰度图,在等于JCS_RGB时代表彩色位图图像

        JPEG需要提供大量的参数来决定我们如何对参数进行编码。大多数情况下我们不需要知道所有的参数,我们可以使用jpeg_set_defaults()把参数设置成合理的默认值。然后,再设置我们需要更改的参数。

        jpeg_set_defaults()依赖于源图像的色彩空间,我们需要在调用jpeg_set_defaults()之前正确设置in_color_space。以下是设置压缩对象的参数的参考代码:

    cinfo.image_width = Width;     
    cinfo.image_height = Height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;
    jpeg_set_defaults(&cinfo);

//设置压缩参  数

(4)jpeg_start_compress(...)

在设置完数据目的和源图像的所有信息和参数后,我们就可以通过调用jpeg_start_compress()来启动一个压缩循环。jpeg_start_compress()会初始化内部的状态,分配工作空间。并且产生JPEG文件头的数据流。示例代码:

       jpeg_start_compress(&cinfo, TRUE);

在这里”TRUE”代表我们需要写入一个完整的数据流

(5) 逐行压缩图像

现在我们可以通过调用jpeg_write_scanlines()写入图象数据了。图象数据应该按照自底向上的顺序进行扫描。

(6jpeg_finish_compress

当所有的图像数据都被写入后,我们调用jpeg_finish_compress来结束压缩循环。这是为了确保所有的数据都被写入数据目的。jpeg_finish_compress同时也承担着释放JPEG对象开辟的内存的工作。一般代码如下:

jpeg_finish_compress(&cinfo);

(7 释放JPEG压缩对象

当对一个JPEG对象完成压缩后,调用jpeg_destroy_compress来释放内存。

抱歉!评论已关闭.