怎么设置libjpeg turbo库可用的最大内存

libjpeg是一个完全用C语言编写的库,包含了被广泛使用的JPEG解码、JPEG编码和其他的JPEG功能的实现。这个库由独立JPEG工作组维护。最新版本号是6b,于1998年发布。可以参考维基百科关于libjpeg的介绍。
libjpeg库的数据结构
&&& 用libjpeg库解码jpeg数据的时候,最重要的数据类型为struct jpeg_decompress_struct,一般变量定义成cinfo变量,该变量保存着jpeg数据的详细信息,也保存着解码之后输出数据的详细信息。一般情况下,每次调用libjpeg库API的时候都需要把这个变量作为第一个参数传入。另外用户也可以通过修改该变量来修改libjpeg行为,比如输出数据格式,libjpeg库可用的最大内存等等。
libjpeg库的使用
1、设置出错处理函数
&&& “天有不测风云”,我们使用libjpeg库的时候难免会产生错误,所以我们在使用libjpeg解码之前,首先要做好错误处理。在libjpeg库中,实现了默认错误处理函数,当错误发生时,比如如果内存不足(非常可能发生,后面会介绍)等,则默认错误处理函数将会调用exit函数结束整个进程,详细内容可以参考jerror.c文件。这个对于很多用户来说这样的特性是不合适的,不过libjpeg提供了接口让我们注册自定义错误处理函数。
&&& 在C语言中没有C++的异常处理机制,但是提供了setjmp和longjmp机制来实现类似的功能,如果你对这个机制不熟悉的话,请查阅C语言手册。
&span&style=&font-size:&&&struct&my_error_mgr&{&&&&&&struct&jpeg_error_mgr&&&&&&&&&&&jmp_buf&setjmp_&&&&&&};&&typedef&struct&my_error_mgr&*&my_error_&&cinfo.err&=&jpeg_std_error(&jerr.pub);&&jerr.pub.error_exit&=&my_error_&&if&(setjmp(jerr.setjmp_buffer))&{&&&&&&jpeg_destroy_decompress(&cinfo);&&&&&&fclose(infile);&&&&&&return&-1;&&}&&&/span&&&
&&& 上述代码中的重点在于我们向libjpeg注册了一个my_error_exit回调函数,当发生错误的时候,该回调函数将会被调用。然后我们调用setjmp函数,设置一个返回点。这样我们在my_error_exit回调函数处理完错误信息之后,就可以调用longjmp函数返回到这里,在这个返回点进行资源的释放(非常重要,否则将会内存泄漏)。我们再看看my_error_exit回调函数的实现:
&span&style=&font-size:&&&METHODDEF(void)&my_error_exit&(j_common_ptr&cinfo)&&{&&&&&&my_error_ptr&myerr&=&(my_error_ptr)&cinfo-&&&&&&&(*cinfo-&err-&output_message)&(cinfo);&&&&&&longjmp(myerr-&setjmp_buffer,&1);&&}&&&/span&&&
&&& 可以通过检查cinfo-&err-&msg_code的值来判断错误类型,进行相应的处理。本例中只是简单的打印一个错误信息。最后调用longjmp跳转到setjmp调用的地方。
2、初始化解码对象
&&& 要使用libjpeg解码jpeg数据,这步是必须要做的。
&span&style=&font-size:&&&FILE&*&&&if&((infile&=&fopen(filename,&&rb&))&==&NULL)&{&&&&&&fprintf(stderr,&&can't&open&%s\n&,&filename);&&&&&&return&-1;&&}&&jpeg_create_decompress(&cinfo);&&&/span&&&
&&& 这步之后,如果结束解码或者出错之后,需要调用jpeg_destroy_decompress销毁解码对象,否则将会内存泄漏。
3、初始化源数据
&&& 在libjpeg库中仅仅提供了文件作为输入数据的接口,在example.c中代码如下:
jpeg_stdio_src(&cinfo, infile);
&&& 这个设计我个人觉得非常不合理,我觉得一个友好的库,需要能够接受各式各样的输入(内存数据,网络数据等等)。比较友好的做法是提供几种常用的输入数据支持(在libjpeg中如:文件输入等)。然后还要提供一个用户注册自定义输入函数(回调函数)的接口,这样库就可以适配现实生活中各式各样的输入数据类型了。Simon也在以前的博文中写过怎样修改libjpeg库,使之能够解码内存buffer中的jpeg数据,请参考《LibJpeg解码内存中的Jpeg数据》。当然Simon没有扩展libjpeg库让其支持用户注册自定义输入函数(回调函数),有兴趣的朋友可以自行实现。
4、读取jpeg文件的头信息
&&& 这个和初始化解码对象一样,是必须要调用的,是约定,没什么好说的。
Java代码 &
&span&style=&font-size:&&&jpeg_read_header(&cinfo,&TRUE);&&&/span&&&
5、设置解码参数
&&& 很多情况下,这步非常重要。比如设置输出格式,设置scale(缩放)等等功能都是在这一步设置。参数设置通过修改上步得到cinfo的值来实现。这里简单介绍一下一些常用的字段。out_color_space:输出的颜色格式,libjpeg定义如下:
&span&style=&font-size:&&&typedef&enum&{&&&&&&JCS_UNKNOWN,&&&&&&&&&&&&&&JCS_GRAYSCALE,&&&&&&&&&&&&&&JCS_RGB,&&&&&&&&&&&&&&JCS_YCbCr,&&&&&&&&&&&&&&JCS_CMYK,&&&&&&&&&&&&&&JCS_YCCK,&&&&&&&&&&&&&&#ifdef&ANDROID_RGB&&&&&&&&&&&JCS_RGBA_8888,&&&&&&&&&&&&JCS_RGB_565&&&&&&&&&&&#endif&&&}&J_COLOR_SPACE;&&&/span&&&
我们可以看出谷歌在Android扩展了几种输出格式,那么如果你需要的颜色格式输出格式libjpeg不支持(比如:YUYV等颜色格式),那么请参考Android对libjpeg的扩展自行修改,不用担心复杂性,实现起来比较easy。请重点研究jdcolor.c文件中的jinit_color_deconverter函数。
scale_num,scale_denom:因为实际的显示设备千变万化,我们可能需要根据实际情况对输出数据进行一些缩放才能够显示。libjpeg支持对输出数据进行缩放(scale),这个变量就是用来设置缩放的参数。目前libjpeg支持1/2,1/4,1/8三种缩放。
mem:可以指定内存管理相关的内容,比如分配和释放内存,指定libjpeg可以使用的最大内存。默认情况下不同的平台下面都有一个libjpeg默认最大可用内存值,比如Android平台上面该值为L(10M),请参考jmemxxxx.c文件中的DEFAULT_MAX_MEM,了解不同平台的默认最大内存值。通过修改mem-&pub.max_memory_to_use的值,库的使用者可以自定义libjpeg可以使用的最大内存值。
6、开始解码
&&& 经过前面的参数设置,我们可以开始解码了,没有什么好说的。
jpeg_start_decompress(&cinfo);
7、读取解码数据(我们打印到终端看看)
&span&style=&font-size:&&&&&&&buffer&=&(unsigned&char&*)&malloc(cinfo.output_width&*&cinfo.output_components);&&&&&&while&(cinfo.output_scanline&&&cinfo.output_height)&{&&&&&&&&&&jpeg_read_scanlines(&cinfo,&&buffer,&1);&&&&&&&&&&for&(i=0;&i&cinfo.output_&i++)&{&&&&&&&&&&&&&&printf(&%02X%02X%02X&&,&buffer[i*3],&buffer[i*3+1],&buffer[i*3+2]);&&&&&&&&&&&&&&if&(0&==&((i+1)&%&10)&||&i&==&cinfo.output_width-1)&{&&&&&&&&&&&&&&printf(&\n&);&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&&&&&printf(&least:%d\n\n&,&cinfo.output_height-cinfo.output_scanline);&&&&&&}&/span&&&
&&& 请注意虽然函数jpeg_read_scanlines可以指定一次读多少行,但是目前该函数还是只能支持一次只读1行。
8、结束解码
&span&style=&font-size:&&&jpeg_finish_decompress(&cinfo);&&&/span&&&
9、释放解码对象
&span&style=&font-size:&&&jpeg_destroy_decompress(&cinfo);&&&/span&&&
&& 至此一个jpeg数据已经解析完成了。虽然步骤不少但是对于常规的使用还是比较简单的。
&&& libjpeg对于baseline的jpeg数据解码比较好,但是解码progressive的jpeg数据的时候,对内存的需求比较大(我测试过的progressive的图片曾经发现过消耗70M内存)。如果你的硬件能够有硬件解码jpeg的能力,请尽可能使用硬件解码jpeg数据。
&&& 简单的说baseline&& jpeg要全部下载后才能观看;progressive&& jpeg采用了类似fgs的技术,可以先传个质量粗糙的,然后逐渐精细,直至全部传完。举个例子,浏览有些网页时,看到图片一行行的出现,但都很清晰,一般都是baseline的,而如果开始就是一大块,但就像有好多马赛克似的,看不清楚,然后慢慢就好了,这种一般就是progressive的了
备注:附件里test.rar里面是test.c文件,包含了示例代码,我测试通过了。内存不用设置的时候,也能处理1.68MB的图片,更大的没试过。jpegsrc.v6b.tar.gz是从官网下载的linux上编译通过了的库源码,如果在linux上用,请不要下载官网的.zip文件,那个在linux下面编译会出错。官网下载地址:&打开是个倒计时下载的。
本文已收录于以下专栏:
相关文章推荐
今天使用Gil时候需要读JPEG格式文件,需要IJL库。当按README中所述步骤得到libjpeg.lib后,在程序中使用时得到错误:Wrong JPEG library version: libr...
(1)mini2440开发板libjpeg库的版本为62
(2)Tiny6410和Tiny4412开发板libjpeg库的版本为80
(3)所以如果交叉编译使用的版本和arm板上程...
本文转自:/xiaoxiaoboke/archive//2349763.html 
多媒体应用在现在电子产品中的地位越来越重要,尤...
Android图片压缩处理确实不如Ios,之前完全没听过libjpeg这个东西,工作闲余时间研究了了一天,总结下吧
libjpeg的介绍可以参考文章:http://blog.csdn.ne...
最近使用ffmpeg做个rtsp播放器,需要个抓图功能,听说turbo libjpeg效率比较高,于是乎编译一个来试试:(需要先安装好git和ndk以及它们的环境配置)
clone最新版libjp...
第一步:下载libjpeg
地址:http://www.ijg.org/
选择下载最新的UNIX格式的源码包:
jpegsrc.v9b.tar.gz.
第二步:解压: tar zxvf jpegsrc...
libjpeg这个库主要用于处理jpeg数据,比如将RGB压缩成JPEG,或者将JPEG解压为RGB。其实早在4年前已经接触过,但一直没写过这方面的文章。后来想想还是有必要写出来,至少可以证明自己搞过...
最近安卓开发里面最火的是什么?NDK开发啊,之前面试的时候好几家公司都问我会不会这个,或者直接就出了这样类型的笔试题,当时的我也是一脸懵逼。恰好这段时间研究了图片压缩和视频压缩的NDK开发,话不多说,...
如何压缩图片只改变在硬盘的存储大小
如何改变图片分辨率让其Bitmap对象可以加载到内存中
关于重载版本
开始学习之旅
补充知识的结...
他的最新文章
讲师:王哲涵
讲师:王渊命
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)【转】VS2013编译libjpeg库 - cv_ml_张欣男 - 博客园
随笔 - 182, 文章 - 0, 评论 - 182, 引用 - 0
原文地址:http://blog.csdn.net/weixinhum/article/details/
&现在,很多图像处理工具和开源库都给出了图像解码的函数接口,然而有时这些接口并不能完全满足我们的需求,比如如果我们想直接去解码内存中的JPEG数据就没有这样的接口。
& & 由于之前做的项目刚刚好设备传过来的图像数据就是JPEG格式的,如果将每帧图像数据都保存成文件然后再借助开源库提供的接口去读入文件会显得很掉价,所以做了一些直接解码内存中JPEG数据的研究。经过对比发现libjpeg库对JPEG图像的编解码支持甚好,而且相对于OpenCV库,复杂度小很多,是故就决定动手来实现我自己想要的接口。
& & 所谓&巧妇难为无米之炊&,要用libjpeg库,第一步自然是去下载其源码,下载地址。
& & 下载完解解压后,就要去编译libjpeg库了,这里我主要参考的是和。因为第一篇用的是VS2012,有些路径跟本文设置略有差别,所以如果你用的是VS2012,请毫不犹豫的点开链接,跟着他的步骤做吧。当然还是要说,VS2013实在是好用太多。
& & OK,现在开始做编译的准备工作,其实也就两步:
& & 第一步:找到刚刚解压出来的&jpeg-9a&文件夹下面的&makefile.vc&文件,用记事本或Notepad++等编辑工具打开,然后找到里面的&!include &win32.mak&&,将&win32.mak&改为绝对路径。不难看出这个win32.mak是个文件,其是VS下的一个文件,所以路径就跟你自己装的VS版本有关,本人装的是VS2013版本,默认情况下该版本中这个文件在&C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include&这个目录下。因而我们将刚刚搜索到的那句话改为&!include &C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include\win32.mak&&就OK了。
& & 第二步:打开VS2013的命令行:&VS2013 x86 本机工具命令提示&,这个用开始菜单打开会方便点,直接找到&Visual Studio 2013&这一项,打开里面的&Visual Studio Tools&文件夹就可以看到。如果是Win8的用户则建议去装个开始菜单工具,不然就去VS的安装目录下面找。打开命令行之后CD到解压出来的&jpeg-9a&目录下,输入&nmake /f makefile.vc setup-v10&,回车,待命令行执行完命令后,准备工作就大功告成啦。关于命令行的操作,具体如下图:
& & 下面来做编译,其实已经没什么难点了,上面工作做完之后,&jpeg-9a&文件夹下面会生成一个VS的工程。直接运行里面的&jpeg.sln&,然后VS提示要升级编译器什么的点是,进入编程界面后直接编译就大功告成了。编译完成后在&jpeg-9a&文件夹下的&Release&文件夹中可以看到一个&jpeg.lib&文件,这个就是我们刚刚编译出来的静态链接库。
&要使用这个静态链接库,只要先包含进jconfig.h,jmorecfg.h,jpeglib.h这三个头文件,然后把刚刚编译出来的jpeg.lib加进工程中就可以了。习惯上会把jpeg.lib改名为libjpeg.lib。下面提供一个jpeg转bmp的例子,代码是基本照搬的,只是做了少量修改。
&关于解码内存中JPEG数据的实现方法介绍,文章地址如下:博客访问: 320396
博文数量: 106
博客积分: 2146
博客等级: 大尉
技术积分: 1146
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: 嵌入式
注意下载了JPEG的源码后,先看看源码里面自带的libjpeg.doc文件
先来研究一下JPEG的压缩操作过程:
The rough outline of a JPEG compression operation is:
&&& Allocate and initialize a JPEG compression object
&&& Specify the destination for the compressed data (eg, a
&&& Set parameters for compression, including image size
& colorspace
&&& jpeg_start_compress(...);
&&& while (scan lines remain to be written)
&&&&&&& jpeg_write_scanlines(...);
&&& jpeg_finish_compress(...);
&&& Release the JPEG compression object
结合代码:
&* Sample routine for JPEG
compression.& We assume that the target
&* and a compression quality factor
are passed in.
GLOBAL(void)
write_JPEG_file (char * filename, int quality)
& /* This struct contains the JPEG
compression parameters and pointers to
&& * working space (which is
allocated as needed by the JPEG library).
&& * It is possible to have several
such structures, representing multiple
&& * compression/decompression
processes, in existence at once.& We
&& * to any one struct (and its
associated working data) as a "JPEG object".
&& */& struct
jpeg_compress_
这个结构体是JPEG库需要使用的,它保存了JPEG的压缩参数和JPEG库的工作状态,这个结构可以有多个,多个就表示有多个压缩和解压缩要处理。当需要对一系列的image进行compress操作时,这个结构可以重复使用。
& /* This struct represents a JPEG
error handler.& It is declared separately
&& * because applications often want
to supply a specialized error handler
&& * (see the second half of this
file for an example).& But here we just
&& * take the easy way out and use
the standard error handler, which will
&& * print a message on stderr and
call exit() if compression fails.
&& * Note that this struct must live
as long as the main JPEG parameter
&& * struct, to avoid
dangling-pointer problems.
& struct jpeg_error_
& /* More stuff */
& FILE *&&& /* target file */
& JSAMPROW row_pointer[1];& /* pointer to JSAMPLE row[s] */
& int row_&&& /* physical row width in image buffer */
第一步:分配并初始化一个JPEG的压缩对象
& /* Step 1: allocate and initialize JPEG compression object */
& /* We have to set up the error handler first, in case the initialization
&& * step fails.& (Unlikely, but it could happen if you are out
of memory.)
&& * This routine fills in the contents of struct jerr, and returns
&& * address which we place into the link field in cinfo.
& cinfo.err = jpeg_std_error(&jerr);
& /* Now we can initialize the JPEG compression object. */
& jpeg_create_compress(&cinfo);
第二步:指定转换后数据的目的地
& /* Step 2: specify data destination (eg, a file) */
& /* Note: steps 2 and 3 can be done in either order.第二步和第三步顺序无所谓,可以颠倒 */
& /* Here we use the library-supplied code to send compressed data to a
&& * stdio stream.& You can also write your own code to do
something else.
&& * VERY IMPORTANT: use "b" option to fopen() if you are
on a machine that
&& * requires it in order to write binary files.
& if ((outfile = fopen(filename, "wb")) == NULL) {
&&& fprintf(stderr, "can't open %s\n", filename);
&&& exit(1);
& jpeg_stdio_dest(&cinfo, outfile);关联JPEG的压缩对象跟输入文件
第三步:设置压缩参数
& /* Step 3: set parameters for compression */
& /* First we supply a description of the input image.
&& * Four fields of the cinfo struct must be filled in:
& cinfo.image_width = image_ &&& /* image width and
height, in pixels */
& cinfo.image_height = image_
& cinfo.input_components = 3;&&& &&& /* # of
color components per pixel */
& cinfo.in_color_space = JCS_RGB;
&&& /* colorspace of input image */
& /* Now use the library's routine to set default compression
parameters.
&& * (You must set at least
cinfo.in_color_space before calling this,
&& * since the defaults depend on the source color space.)
& jpeg_set_defaults(&cinfo);使用库函数设置默认的压缩参数
& /* Now you can set any non-default parameters you wish to.
&& * Here we just illustrate the use of quality (quantization table)
& jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG
values */);
第四步:开始压缩
/* Step 4: Start compressor */
& /* TRUE ensures that we will write a complete interchange-JPEG file.
&& * Pass TRUE unless you are very sure of what you're doing.
& jpeg_start_compress(&cinfo, TRUE);
第五步:这里的循环参数是库的一个状态变量cinfo.next_scanline
& /* Step 5: while (scan lines remain to be written) */
& /*&&&&&&&&&&
jpeg_write_scanlines(...); */
& /* Here we use the library's state variable cinfo.next_scanline as the
&& * loop counter, so that we don't have to keep track ourselves.
&& * To keep things simple, we pass o you can
&& * more if you wish, though.
& row_stride = image_width * 3;&&& /* JSAMPLEs per row in
image_buffer */
& 当前扫描的行数小于图片的总行数就继续
& while (cinfo.next_scanline & cinfo.image_height) {
&&& /* jpeg_write_scanlines expects an array of pointers to
scanlines.
&&&& * Here the array is only one element long, but you
could pass
&&&& * more than one scanline at a time if that's more
convenient.
&&& row_pointer[0] = & image_buffer[cinfo.next_scanline *
row_stride];
&&& (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
第六步:完成压缩
& /* Step 6: Finish compression */
& jpeg_finish_compress(&cinfo);
& /* After finish_compress, we can close the output file. */
& fclose(outfile);关闭输出文件
第七步:释放JPEG压缩对象,之后这个cinfo可以用作另外一个image
& /* Step 7: release JPEG compression object */
& /* This is an important step since it will release a good deal of
memory. */
& jpeg_destroy_compress(&cinfo);
& /* And we're done! */
下面研究JPEG的解压缩过程:
the rough outline of a
JPEG decompression operation is:
&&& Allocate and initialize a JPEG decompression object
&&& Specify the source of the compressed data (eg, a file)
&&& Call jpeg_read_header() to obtain image info
&&& Set parameters for decompression
&&& jpeg_start_decompress(...);
&&& while (scan lines remain to be read)
&&&&&&& jpeg_read_scanlines(...);
&&& jpeg_finish_decompress(...);
&&& Release the JPEG decompression object
这个过程与压缩过程差不多,就是多了读数据流头这一步。这个头很有用,包含了image的大小,颜色空间,当咱们自己的应用程序选择解压缩参数时候要用到这些信息。例如,应用程序可以选择一个比例因子生成一个适合大小的图片。
结合代码:
&* Sample routine for JPEG
decompression.& We assume that the source
&* is passed in.& We want to return 1 on success, 0 on error.
GLOBAL(int)
read_JPEG_file (char * filename)
& /* This struct contains the JPEG
decompression parameters and pointers to
&& * working space (which is
allocated as needed by the JPEG library).
& struct jpeg_decompress_struct
& /* We use our private extension
JPEG error handler.
&& * Note that this struct must live
as long as the main JPEG parameter
&& * struct, to avoid
dangling-pointer problems.
& struct my_error_
& /* More stuff */
& FILE *&&&& /* source file */
& JSAMPARRAY&&&& /* Output row buffer */
& int row_&&& /* physical row width in output buffer */
& /* In this example we want to open
the input file before doing anything else,
&& * so that the setjmp() error
recovery below can assume the file is open.
&& * VERY IMPORTANT: use
"b" option to fopen() if you are on a machine that
&& * requires it in order to read
binary files.
& if ((infile = fopen(filename,
"rb")) == NULL) {
&&& fprintf(stderr, "can't open
%s\n", filename);
&&& return 0;
& /* Step 1: allocate and initialize
JPEG decompression object */
& /* We set up the normal JPEG error
routines, then override error_exit. */
& cinfo.err =
jpeg_std_error(&jerr.pub);
& jerr.pub.error_exit =
& /* Establish the setjmp return context
for my_error_exit to use. */
& if (setjmp(jerr.setjmp_buffer)) {
&&& /* If we get here, the JPEG code
has signaled an error.
&&&& * We need to clean up the JPEG
object, close the input file, and return.
jpeg_destroy_decompress(&cinfo);
&&& fclose(infile);
&&& return 0;
& /* Now we can initialize the JPEG
decompression object. */
jpeg_create_decompress(&cinfo);
& /* Step 2: specify data source
(eg, a file) */
& jpeg_stdio_src(&cinfo,
& /* Step 3: read file parameters
with jpeg_read_header() */
jpeg_read_header(&cinfo, TRUE);
& /* We can ignore the return value
from jpeg_read_header since
&& *&& (a) suspension is not possible with the
stdio data source, and
&& *&& (b) we passed TRUE to reject a tables-only
JPEG file as an error.
&& * See libjpeg.doc for more info.
& /* Step 4: set parameters for
decompression */
& /* In this example, we don't need
to change any of the defaults set by
&& * jpeg_read_header(), so we do
nothing here.
& /* Step 5: Start decompressor */
jpeg_start_decompress(&cinfo);
& /* We can ignore the return value
since suspension is not possible
&& * with the stdio data source.
& /* We may need to do some setup of
our own at this point before reading
&& * the data. &After jpeg_start_decompress() we have the
correct scaled
&& * output image dimensions
available, as well as the output colormap
&& * if we asked for color
quantization.
&& * In this example, we need to
make an output work buffer of the right size.
& /* JSAMPLEs per row in output
& row_stride = cinfo.output_width *
cinfo.output_
& /* Make a one-row-high sample
array that will go away when done with image */
& buffer =
(*cinfo.mem-&alloc_sarray)
&&&&&& ((j_common_ptr) &cinfo,
JPOOL_IMAGE, row_stride, 1);
& /* Step 6: while (scan lines
remain to be read) */
& /*&&&&&&&&&& jpeg_read_scanlines(...); */
& /* Here we use the library's state
variable cinfo.output_scanline as the
&& * loop counter, so that we don't
have to keep track ourselves.
& while (cinfo.output_scanline &
cinfo.output_height) {
&&& /* jpeg_read_scanlines expects
an array of pointers to scanlines.
&&&& * Here the array is only one
element long, but you could ask for
&&&& * more than one scanline at a
time if that's more convenient.
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
jpeg_read_scanlines函数用来把解压缩的数据传递到内存Buffer中
&&& /* Assume put_scanline_someplace
wants a pointer and sample count. */
put_scanline_someplace(buffer[0], row_stride);
& /* Step 7: Finish decompression */
jpeg_finish_decompress(&cinfo);
& /* We can ignore the return value
since suspension is not possible
&& * with the stdio data source.
& /* Step 8: Release JPEG
decompression object */
& /* This is an important step since
it will release a good deal of memory. */
jpeg_destroy_decompress(&cinfo);
& /* After finish_decompress, we can
close the input file.
&& * Here we postpone it until after
no more JPEG errors are possible,
&& * so as to simplify the setjmp
error logic above.& (Actually, I don't
&& * think that jpeg_destroy can do
an error exit, but why assume anything...)
& fclose(infile);
& /* At this point you may want to
check to see whether any corrupt-data
&& * warnings occurred (test whether
jerr.pub.num_warnings is nonzero).
& /* And we're done! */
& return 1;
}下面开始分析源码,以djpeg.c中的main.c为入口开始分析:(以★开头的是代码,其余的是分析)★struct jpeg_decompress_ 这个结构体对象包含了JPEG解压缩参数和一些工作函数的指针,咱们的JPEG库的API需要它★jpeg_create_decompress(&cinfo);初始化这个结构体对象,这里的jpeg_create_decompress是一个宏替换:★#define jpeg_create_decompress(cinfo) \&&& jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \&&& &&& &&& & (size_t) sizeof(struct jpeg_decompress_struct))这里的JPEG_LIB_VERSION在jpeglib.h头文件中定义,其目的是为了同步JPEG库和调用者的版本一致,如果调用者用的JPEG_LIB_VERSION和库里面的JPEG_LIB_VERSION不一样,程序会退出运行。下面看看函数jpeg_CreateDecompress的实现(在jdapimin.c中):★GLOBAL(void)jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize){&& /* Guard against version mismatches between library and caller. */& cinfo-&mem = NULL;&&& &&& /* so jpeg_destroy knows mem mgr not called */& if (version != JPEG_LIB_VERSION)& //这里判断使用者的版本和库版本是否一致&&& ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);&// 同样调用者的结构体对象jpeg_decompress_struct的大小也要同库一致& if (structsize != SIZEOF(struct jpeg_decompress_struct)) &&& ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, &&& &&&& (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);& /* For debugging purposes, zero the whole master structure.&& * But error manager pointer is already there, so save and restore it.&& */& { // 关于错误处理这里先不看,先当咱们程序不会出错^oo^&&& struct jpeg_error_mgr * err = cinfo-&&&& 将cinfo这个结构体对象清0&&& MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));&&& cinfo-&err =& }& // is_decompressor是值,TRUE表示要解压缩& cinfo-&is_decompressor = TRUE; & /* Initialize a memory manager instance for this object */& // 为这个对象初始化一个内存管理实例,下面会分析这个接口& jinit_memory_mgr((j_common_ptr) cinfo);& /* Zero out pointers to permanent structures. */& cinfo-&progress = NULL;& cinfo-&src = NULL;& // cinfo-&src是被压缩的数据源地址& // NUM_QUANT_TBLS指定量化表个数,默认为4,最好不要改动& // NUM_HUFF_TBLS指定量化表个数,默认为4,最好不要改动& for (i = 0; i & NUM_QUANT_TBLS; i++)&&& cinfo-&quant_tbl_ptrs[i] = NULL; // 表指针先置空& for (i = 0; i & NUM_HUFF_TBLS; i++) {&&& cinfo-&dc_huff_tbl_ptrs[i] = NULL; // 表指针先置空&&& cinfo-&ac_huff_tbl_ptrs[i] = NULL; // 表指针先置空& }& /* Initialize marker processor so application can override methods&& * for COM, APPn markers before calling jpeg_read_header.&& */& jinit_marker_reader(cinfo);& /* And initialize the overall input controller. */& jinit_input_controller(cinfo); // 初始化输入控制& /* OK, I'm ready */& // global_state验证所有任务队列的有效性,即目前程序到了一个什么状态,这里&&& DSTATE_START为200,表示完成了create_decompress& cinfo-&global_state = DSTATE_START; }jinit_memory_mgr实现(在jmemmgr.c中)★jinit_memory_mgr((j_common_ptr) cinfo);/*&* Memory manager initialization.&* When this is called, only the error manager pointer is valid in cinfo!&*/这个函数调用完毕后,cinfo结构里的错误管理指针就有效了这里函数参数j_common_ptr cinfo把cinfo强制转换成j_common_ptr类型,j_common_ptr类型结构如下:struct jpeg_common_struct {& jpeg_common_&&& &&& /* Fields common to both master struct types };而jpeg_common_fields是个宏替换:#define jpeg_common_fields \& struct jpeg_error_mgr *&&& /* Error handler module */\& struct jpeg_memory_mgr *&&& /* Memory manager module */\& struct jpeg_progress_mgr * /* Progress monitor, or NULL if none */\& void * client_&&& &&& /* Available for use by application */\& boolean is_&&& /* So common code can tell which is which */\& int global_state&&& &&& /* For checking call sequence validity */GLOBAL(void)jinit_memory_mgr (j_common_ptr cinfo){& my_mem_& long max_to_&& size_t test_& cinfo-&mem = NULL;&&& &&& /* for safety if init fails */& /* Check for configuration errors.&& * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably&& * doesn't reflect any real hardware alignment requirement.&& * The test is a little tricky: for X&0, X and X-1 have no one-bits&& * in common if and only if X is a power of 2, ie has only one one-bit.&& * Some compilers may give an "unreachable code" ignore it.&& */& if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)&&& ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);& /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be&& * a multiple of SIZEOF(ALIGN_TYPE).&& * Again, an "unreachable code" warning may be ignored here.&& * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK.&& */& test_mac = (size_t) MAX_ALLOC_CHUNK;& if ((long) test_mac != MAX_ALLOC_CHUNK ||&&&&& (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)&&& ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);& 我们返回的max_to_use的值是1000000& max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */& /* Attempt to allocate memory manager's control block */& 分配内存管理控制块的内存& mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));& 如果失败就释放并返回& if (mem == NULL) {&&& jpeg_mem_term(cinfo);&&& /* system-dependent cleanup */这里面没啥东西,可以自己写一些处理之类的&&& ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);& }& /* OK, fill in the method pointers */& // 填充函数指针& mem-&pub.alloc_small = alloc_& mem-&pub.alloc_large = alloc_& mem-&pub.alloc_sarray = alloc_& mem-&pub.alloc_barray = alloc_& mem-&pub.request_virt_sarray = request_virt_& mem-&pub.request_virt_barray = request_virt_& mem-&pub.realize_virt_arrays = realize_virt_& mem-&pub.access_virt_sarray = access_virt_& mem-&pub.access_virt_barray = access_virt_& mem-&pub.free_pool = free_& mem-&pub.self_destruct = self_& /* Make MAX_ALLOC_CHUNK accessible to other modules */& mem-&pub.max_alloc_chunk = MAX_ALLOC_CHUNK;& /* Initialize working state */& max_memory_to_use是为JPEG对象分配的内存极限大小& mem-&pub.max_memory_to_use = max_to_& // JPOOL_NUMPOOLS == 2, JPOOL_PERMANENT == 0& for (pool = JPOOL_NUMPOOLS-1; pool &= JPOOL_PERMANENT; pool--) {&&& mem-&small_list[pool] = NULL;&&& mem-&large_list[pool] = NULL;& }& mem-&virt_sarray_list = NULL;& mem-&virt_barray_list = NULL;& mem-&total_space_allocated = SIZEOF(my_memory_mgr);& /* Declare ourselves open for business */& cinfo-&mem = & mem-&& /* Check for an environment variable JPEGMEM; if found, override the&& * default max_memory setting from jpeg_mem_init.& Note that the&& * surrounding application may again override this value.&& * If your system doesn't support getenv(), define NO_GETENV to disable&& * this feature.&& */#ifndef NO_GETENV& { char *&&& if ((memenv = getenv("JPEGMEM")) != NULL) {&&&&& char ch = 'x';&&&&& if (sscanf(memenv, "%ld%c", &max_to_use, &ch) & 0) {&&& if (ch == 'm' || ch == 'M')&&& & max_to_use *= 1000L;&&& mem-&pub.max_memory_to_use = max_to_use * 1000L;&&&&& }&&& }& }#endif}★jinit_marker_reader(cinfo);★jinit_input_controller(cinfo);★jpeg_mem_init(cinfo)& 返回一个值,简单不多解释GLOBAL(long)jpeg_mem_init (j_common_ptr cinfo){& return DEFAULT_MAX_MEM;&&& /* default for max_memory_to_use */}★mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));GLOBAL(void *)jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject){& return (void *) malloc(sizeofobject);}★jpeg_mem_term(cinfo);
阅读(11298) | 评论(1) | 转发(5) |
相关热门文章
给主人留下些什么吧!~~
超级忍者龟 您好!
我们公司目前正在做IT培训,形式是在线视频形式,我们很想邀请您当我们的讲师。不知您是否有兴趣?
这是我们课程的一个分页面:http://www./3500428
我的联系方式如下,如果您有兴趣,可以随时联系我。
请登录后评论。

我要回帖

更多关于 libjpeg.so.8 的文章

 

随机推荐