libjpeg库的简单使用使用----jpeg图片解压

libjpeg库其实已经可以满足我们日常处理日常简单图片之间的转换了。下面就来介绍一下jpeg库的解压和压缩过程。

首先来讲解压操作过程:

1、分配jpeg对象结构体空间,并初始化。

2、指定解压数据源。

3、获取解压文件信息。

4、为解压设定参数,包括图像大小和颜色空间。

5、开始解压缩。

6、取数据。

7、解压完毕。

8、释放资源和退出程序。


1、分配jpeg对象结构体空间、并初始化。

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

[html] view plain copy
  1. struct jpeg_decompress_struct cinfo;  
  2. struct jpeg_error_mgr jerr;  
        绑定jerr错误结构体至jpeg对象结构体。

[html] view plain copy
  1. cinfo.err = jpeg_std_error(&jerr);  

        这个标准的错误处理结构将使程序在出现错误时调用exit()退出程序,如果不希望使用标准的错误处理方式,则可以通过自定义退出函数的方法自定义错误处理结构。

        初始化cinfo结构体。

[html] view plain copy
  1. jpeg_create_decompress(&cinfo);  

2、指定解压数据源。

        利用标准C库的文件指针打开相关jpg文件。

[html] view plain copy
  1.      FILE * infile;  
  2.      if ((infile = fopen("test.jpg", "rb")) == NULL)  
  3.      {  
  4.           perror("fopen fail");  
  5.           return 0;  
  6.      }  
  7.      jpeg_stdio_src(&cinfo, infile);  

3、获取解压文件信息。

        将图像的缺省信息填充到cinfo结构中以便程序使用。

[html] view plain copy
  1. (void) jpeg_read_header(&cinfo, TRUE);  
        此时,常见的可用信息包括图像的宽cinfo.image_width,高cinfo.image_height,色彩空间cinfo.jpeg_color_space,颜色通道数cinfo.num_components等。

4、为解压设定参数,包括图像大小和颜色空间。

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

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

[html] view plain copy
  1. cinfo.scale_num=1;  
  2. cinfo.scale_denom=2;  

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

[html] view plain copy
  1. cinfo.out_color_space=JCS_GRAYSCALE;  

5、开始解压缩。 

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

[html] view plain copy
  1. (void) jpeg_start_decompress(&cinfo);  
        在完成解压缩操作后,会将解压后的图像信息填充至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-bit RGB真彩色的图像中,一个scanline中的数据存储模式是R,G,B,R,G,B,R,G,B,...,每条scanline是一个JSAMPLE类型的数组,一般来说就是unsigned char,定义于jmorecfg.h中。除了JSAMPLE,图像还定义了JSAMPROW和JSAMPARRAY,分别表示一行JSAMPLE和一个2D的JSAMPLE数组。

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

[html] view plain copy
  1. JSAMPARRAY buffer;  
        然后是计算每行需要的空间大小,比如RGB图像就是宽度×3,灰度图就是宽度×1
[html] view plain copy
  1. row_stride = cinfo.output_width * cinfo.output_components;  

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

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

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

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

[html] view plain copy
  1. buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);  
        output_scanline表示当前已经读取的行数,如此即可依次读出图像的所有数据,并填充到缓冲区中,参数1表示的是每次读取的行数。

[html] view plain copy
  1. while(cinfo.output_scanline < cinfo.output_height)  
  2. {  
  3.     (void) jpeg_read_scanlines(&cinfo, buffer, 1);  
  4.      //do something  
  5. }  


7、解压完毕。

[html] view plain copy
  1. (void) jpeg_finish_decompress(&cinfo);  

8、释放资源和退出程序。
[html] view plain copy
  1. jpeg_destroy_decompress(&cinfo);  
  2. fclose(infile);  
如果不再需要JPEG对象,则使用
[html] view plain copy
  1. jpeg_destroy_decompress(&cinfo);  
  2.   
  3. jpeg_destroy(&cinfo);  
而如果还希望继续使用JPEG对象,则可使用

[html] view plain copy
  1. jpeg_abort_decompress(&cinfo);  
  2.   
  3. jpeg_abort(&cinfo);  
完整例程:

[html] view plain copy
  1. //变量定义  
  2.      struct jpeg_decompress_struct cinfo;  
  3.      struct jpeg_error_mgr jerr;  
  4.      FILE * infile;  
  5.      JSAMPARRAY buffer;  
  6.      int row_stride;          
  7.   
  8.      //绑定标准错误处理结构  
  9.      cinfo.err = jpeg_std_error(&jerr);    
  10.   
  11.      //初始化JPEG对象  
  12.      jpeg_create_decompress(&cinfo);  
  13.   
  14.      //指定图像文件  
  15.      if ((infile = fopen("sample.jpg", "rb")) == NULL)  
  16.      {  
  17.            perror("fopen fail");  
  18.            return;  
  19.      }  
  20.      jpeg_stdio_src(&cinfo, infile);  
  21.   
  22.      //读取图像信息  
  23.      (void) jpeg_read_header(&cinfo, TRUE);  
  24.   
  25.      //设定解压缩参数,此处我们将图像长宽缩小为原图的1/2  
  26.      cinfo.scale_num=1;  
  27.      cinfo.scale_denom=2;  
  28.   
  29.      //开始解压缩图像  
  30.      (void) jpeg_start_decompress(&cinfo);  
  31.   
  32.      //本程序功能是应用GDI+在客户区绘制图像  
  33.      CClientDC dc(this);  
  34.      Bitmap bm( cinfo.output_width , cinfo.output_height);   
  35.      Graphics graphics(dc.GetSafeHdc());  
  36.      Graphics gdc(&bm);  
  37.   
  38.      //分配缓冲区空间  
  39.      row_stride = cinfo.output_width * cinfo.output_components;  
  40.      buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);  
  41.   
  42.      //读取数据  
  43.      while (cinfo.output_scanline < cinfo.output_height)  
  44.      {  
  45.          (void) jpeg_read_scanlines(&cinfo, buffer, 1);  
  46.          //output_scanline是从1开始,所以需要减1  
  47.          int line=cinfo.output_scanline-1;  
  48.          for(int i=0;i<cinfo.output_width;i++)  
  49.          {  
  50.               //绘制位图,本例中假设读取的sample.jpg图像为RGB真彩色图像  
  51.               //因此,实际上cinfo.output_components就等于3,灰度图则需另作处理  
  52.               bm.SetPixel(i,line,Color(255,(BYTE)buffer[0][i*3],(BYTE)buffer[0][i*3+1],(BYTE)buffer[0][i*3+2]));  
  53.          }  
  54.      }  
  55.      //结束解压缩操作  
  56.      (void) jpeg_finish_decompress(&cinfo);  
  57.   
  58.      //释放资源  
  59.      jpeg_destroy_decompress(&cinfo);  
  60.      fclose(infile);  
  61.   
  62.      //在客户区绘制位图  
  63.      graphics.DrawImage(&bm,0,0);  
阅读更多
个人分类: libjpeg
想对作者说点什么? 我来说一句

libjpeg.lib

2010年06月15日 230KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭