本篇文章讲的是jpeg库的使用,至于jpeg库的编译方法,在之前的文章中已经介绍过了。首先我们看看用jpeg库进行编程我们需要哪些资源:在jpeg库编译完成后我们需要其中的jconfig.h,jmorecfg.h,jpeglib.h这三个头文件,还需要libjpeg.a这个库文件(在这里我们使用静态链接库)。

        我用Qt+jpeg库写了一个在Linux操作系统下使用的jpeg图片格式转换的小工具,主要的功能就是实现jpeg图片的尺寸压缩,色阶的变化,质量系数的改变,以供参考,下载的地址是:http://download.csdn.net/detail/yanchen0314/7491995

 

        jpeg库的使用分为压缩和解压缩两个部分,首先各自介绍一下这两个部分的操作流程。

压缩流程:

                        <1>分配和初始化一个jpeg压缩对象。

                        <2>指定压缩数据保存的位置。

                        <3>设置压缩参数。

                        <4>开启一个压缩循环。

                        <5>逐行扫描,压缩图像。

                        <6>结束压缩循环

                        <7>释放jpeg压缩对象

1.      如何分配和初始化一个jpeg压缩对象:在libjpeg中jpeg压缩对象被定义为struct jpeg_compresss_struct这样一个结构体(在这个结构体中有一些子结构体,而这些子结构体是通过malloc来分配的);另外我们还需要定义一个错误处理器struct jpeg_error_mgr结构体(错误处理器的作用是将jpeg库中的错误流输出到stderr,如果出现致命的错误就退出程序)。

例1:

         structjpeg_compress_struct  cinfo;

         strcut jpeg_error_mgrjerr;

         cinfo.err  = jpeg_std_error(&jerr);

        jpeg_create_compress(&cinfo);

2.      指定压缩数据保存的位置:

例2:

         FILE *pOutfile =NULL;

         if(pOutfile =fopen(strFileName,”wb”))

         {

               return;

}

jpeg_stdio_dest(&cinfo,pOutfile);

不能在jpeg_start_compress与jpeg_finish_compress之间更改数据保存的位置。

 

3.       设置压缩对象参数,这里主要需要设置的参数有:

     cinfo.image_width;(图像的宽度,以像素为单位);

     cinfo.image_height;(图像的高度,以像素为单位);

     cinfo.input_components;(图像的索引,1代表灰阶图,2代表彩色图);

     cinfo.in_color_space;(输入图像的色阶,JCS_GRAYSCALE代表灰阶,JCS_RGB代表彩色图像);

     质量参数(0~100);

     例3:

           jpeg_set_default(&cinfo)//设置压缩参数;

           jpeg_set_quality(&cinfo,100,TRUE)//设置质量参数;

 

4.       开始压缩循环,逐行进行压缩:使用jpeg_start_compress开始一个压缩循环。

     例4:

          jpeg_start_compress(&cinfo,TRUE);

           JSAMPROW pRow[1];

           int iWidth = cinfo.image_width *cinfo. input_components;//一行数据所占的字节数

           while(cinfo.next_scanline <cinfo.image_height)

           {

               pRow[0] =pData[cinfo.next_scanline*iWidth];//需要压缩成jpeg图片的位  图数据缓冲区

              jpeg_write_scanlines(&cinfo,pRow,1);//参数:1表示写入一行

           }

5.      结束压缩循环:

例5:

       jpeg_finish_compress(&cinfo);

 

6.      释放jpeg压缩对象

           jpeg_destorycompress(&cinfo);

           fclose(pOutfile);

 

解压缩流程:

<1>JPEG对象分配空间并初始化

<2> 指定解压缩数据源

 <3> 获取文件信息

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

<5>开始解压缩

<6>取出数据

<7> 解压缩完毕

<8>  释放资源

 

1.  JPEG对象分配空间并初始化,解压缩过程中使用的JPEG对象是一个jpeg_decompress_struct的结构体。同时还需要定义一个用于错误处理的结构体对象,IJG中标准的错误结构体是jpeg_error_mgr

     struct jpeg_decompress_structcinfo;

     struct jpeg_error_mgrjerr;

       然后是将错误处理结构对象绑定在JPEG对象上。

       cinfo.err = jpeg_std_error(&jerr);

    初始化cinfo结构。

     jpeg_create_decompress(&cinfo);

2.指定解压缩数据源,利用标准C中的文件指针传递要打开的jpg文件。

     FILE *infile;

     if ((infile= fopen("sample.jpg", "rb")) == NULL)

     {

         return 0;

     }

     jpeg_stdio_src(&cinfo, infile);

 

3.  获取文件信息,IJG将图像的缺省信息填充到cinfo结构中以便程序使用。

     (void)jpeg_read_header(&cinfo, TRUE);

此时,常见的可用信息包括图像的宽cinfo.image_width,高cinfo.image_height,色彩空间cinfo.jpeg_color_space,颜色通道数cinfo.num_components等。

 

4.  为解压缩设定参数在完成jpeg_read_header调用后,开始解压缩之前就可以进行解压缩参数的设定,也就是为cinfo结构的成员赋值。

比如可以设定解出来的图像的大小,也就是与原图的比例。使用scale_numscale_denom两个参数,解出来的图像大小就是scale_num/scale_denom,但是IJG当前仅支持1/1, 1/2, 1/4,1/8这几种缩小比例。

比如要取得1/2原图的图像,需要如下设定:

           cinfo.scale_num=1;

           cinfo.scale_denom=2;

也可以设定输出图像的色彩空间,即cinfo.out_color_space,可以把一个原本彩色的图像由真彩色JCS_RGB变为灰度JCS_GRAYSCALE。如:

           cinfo.out_color_space=JCS_GRAYSCALE;

 

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

          (void)jpeg_start_decompress(&cinfo);

在完成解压缩操作后,IJG就会将解压后的图像信息填充至cinfo结构中。比如,输出图像宽度cinfo.output_width,输出图像高度cinfo.output_height,每个像素中的颜色通道数cinfo.output_components(比如灰度为1,全彩色为3)等。

一般情况下,这些参数是在jpeg_start_decompress后才被填充到cinfo中的,如果希望在调用jpeg_start_decompress之前就获得这些参数,可以通过调用jpeg_calc_output_dimensions()的方法来实现。

 

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

除了JSAMPLEIJG还定义了JSAMPROWJSAMPARRAY,分别表示一行JSAMPLE和一个2DJSAMPLE数组。

在此,我们定义一个JSAMPARRAY类型的缓冲区变量来存放图像数据。

           JSAMPARRAY buffer;

然后是计算每行需要的空间大小,比如RGB图像就是宽度×3,灰度图就是宽度×1

           row_stride = cinfo.output_width *cinfo.output_components;

为缓冲区分配空间,这里使用了IJG的内存管理器来完成分配。

JPOOL_IMAGE表示分配的内存空间将在调用jpeg_finish_compressjpeg_finish_decompressjpeg_abort后被释放,而如果此参数改为JPOOL_PERMANENT则表示内存将一直到JPEG对象被销毁时才被释放。

row_stride如上所说,是每行数据的实际大小。

最后一个参数是要分配多少行数据。此处只分配了一行。

          buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);

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

          while (cinfo.output_scanline< cinfo.output_height)

          {

                (void)jpeg_read_scanlines(&cinfo, buffer, 1);

                //do something

          }

7. 解压缩完毕,释放资源

     (void)jpeg_finish_decompress(&cinfo);

     jpeg_destroy_decompress(&cinfo);

     fclose(infile);

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐