版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、libjpeg 实现内存内位图的压缩及解压缩相信使用过的朋友应该会喜欢上 libjpeg,它简单易用、压缩质量可以随意控制、并且稳定给提供的 libjpeg 库,性很好,但是,不论是进行压缩时还是解压缩时,都需要用到 FILE,使得解压缩图像还要自己实现相应的结构,总之,比较麻烦,尤其对初学者,更是不知从何处入手,幸运的是,libjpeg 给提供了源代码,今天我就为大家介绍,怎样修改源代码,使 libjpeg 可以非常容易的直接处理内存中的图像,而无需借助文件操作。立自己的 libjpeg 工程如果想在内存中直接压缩或为了修改后编译方便,也为了以后在 VC 环境下容易使用 libjpeg 库,
2、骤将 libjpeg 转换为 VC 环境下的工程。按以下步1、在 VC 环境下重新建立一个空的 sic library 工程,工程名为 libjpeg,此处注意,新建工程不要包含 mfc,不要预编译头文件;2、然后将 libjpeg 下的 jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.cjcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.cjcphuff.c jcprepct.c jcsle.c jctrans.c jdapimin.c jdapist
3、d.cjdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.cjdinpjdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.cjdtct.c jdsle.c jdtrans.c jerror.c jfdctflt.c jfdctfst.cjfdct.c jidctflt.c jidctfst.c jidct.c jidctred.c jquant1.cjquant2.c jutils.c jmemmgr.cjchuff.h jconfig.hjdhuff.hjdct.hjerr
4、or.hjinclude.hjmemsys.h jmorecfg.hjpeg名为.cpp;.h jpeglib.h jver.h 等文件拷贝到新工程的文件夹下,并将.c 文件改3、将所有的源文件及头文件添加到新建的工程中; 4、编译新工程,此时就可以生成 libjpeg.lib 了。二、分析并修改源代码知道,libjpeg 是利用 FILE 进行存取图像数据的,接下来,libjpeg 是怎样利用 FILE 进行存取图像数据的,就要分析一下然后用内存拷贝的方式替换掉所有的文件操作(I/O),也就实现了内存中进行图像压缩和解压缩的目标。下面,先分析压缩图像时 libjpeg 是怎样利用FILE 进
5、行数据的。先看在进行图像压缩时,所调用的跟文件有关系的函数:jpeg_stdio_dest(pres_ptr cinfo, FILE *outfile);找到这个函数的源代码(jdatadst.cpp 文件第 130 行):GLOBAL(void)1234jpeg_stdio_dest (press_ptr cinfo, FILE * outfile)my_dest_ptr dest;5images 6/* The destination object is made permanent sot multiple JPEG* can be written to the same file wi
6、thout re-executingjpeg_stdio_dest.7destination 8private object* This makes it dangerous to use this manager and a different* manager serially with the same JPEG object, because their910111213* sizes may be different. Caveat programmer.*/if (cinfo-dest = NULL) /*time for this JPEG object? */cinfo-des
7、t = (struct jpeg_destination_mgr *)(*cinfo-mem-alloc_small) (mon_ptr) cinfo,JPOOL_PERMANENT,1415161718192021SIZEOF(my_destination_mgr);dest = (my_dest_ptr) cinfo-dest;dest-pub.init_destination = init_destination;dest-pub.empty_output_buffer = empty_output_buffer; dest-pub.term_destination = term_des
8、tination;dest-outfile = outfile;大家看第 20 行,函数将 FILE 类型的指针赋值给了 dest-outfile,很显然,以后对文件的操作,就转向了对 dest-outfile 的操作,只要找到所有outfile 的函数,就可以知道 libjpeg 是怎样压缩图像到文件的,因此,继续搜 outfile,搜索结果如下:Find all outfile, Subfolders, Find Results 1, Entire SolutionE:VS2005libjpeglibjpegjpeglib.h(910):EXTERN(void)jpeg_stdio_des
9、tJPP(press_ptr cinfo, FILE * outfile);E:VS2005libjpeglibjpegjdatadst.cpp(28): FILE stream */E:VS2005libjpeglibjpegjdatadst.cpp(85): if dest-buffer, OUTPUT_BUF_SIZE) !=E:VS2005libjpeglibjpegjdatadst.cpp(113):*outfile; /*(JFWRITE(dest-outfile,if(JFWRITE(dest-outfile,dest-buffer, dount) != dount)E:VS20
10、05libjpeglibjpegjdatadst.cpp(116):E:VS2005libjpeglibjpegjdatadst.cpp(118):fflush(dest-outfile);if (ferror(dest-outfile)E:VS2005libjpeglibjpegjdatadst.cpp(130):jpeg_stdio_dest press_ptr cinfo, FILE * outfile)E:VS2005libjpeglibjpegjdatadst.cpp(150): dest-outfile = outfile;(Matching lines: 8可以看到,共有 8 处
11、Matching files: 2Total files searched: 57了 outfile 变量,第一处为函数,第二处为变量,第三、四、五、六处为文件操作,第七处和第八处已经见过了,只需要把这八处改了就可以实现的目标了。如下:EXTERN(void) jpeg_stdio_dest JPP(由 EXTERN(void) jpeg_stdio_dest JPP(改写press_ptr cinfo, char* outdata); / press_ptr cinfo, FILE * outfile);char * outdata; /*改写stream */ /由 FILE * outf
12、ile; /*stream */jdatadst.cpp 文件第 87 行 empty_output_buffer (press_ptr cinfo)函数memcpy(dest-outdata,dest-buffer,OUTPUT_BUF_SIZE);/JFWRITE(dest-outfile, dest-buffer, OUTPUT_BUF_SIZE)改写由jdatadst.cpp 文件第 114 行 term_destination (press_ptr cinfo)memcpy(dest-outdata,dest-buffer,dJFWRITE(dest-outfile, dest-bu
13、ffer, dount);ount)改写/由删除 fflush(dest-outfile);和 if (ferror(dest-outfile)及相关的其它语句。peg_stdio_dest (press_ptr cinfo, char* outdata)/ 由 peg_stdio_dest(press_ptr cinfo, FILE * outfile)改写dest-outdata = outdata;改写/ 由dest-outfile = outfile;改到这里,可以编译一下,应该不会有错误产生,但是,你会不会觉得有问题呢?对,位置),发现,没有为内存区域提供偏移量(每次追加图像数据后,
14、偏移量指向当前的另外,由于只有到压缩完才能知道图像压缩完后的数据量大小,据大小的变量。还需要一个指示图像数这两个变量添加到outdata 后面,跟 outdata 一样,作为 dest 的成员变量,如下:typedef struct struct jpeg_destination_mgr pub; /* public fields */char * outdata;/*stream */*pSize;/新加变量,该指针为调用者提供,压缩完后返回图像大小/ 新加变量nOutOffset;JOCTET * buffer; /* start of buffer */ my_destination_m
15、gr;通过 jpeg_stdio_dest 函数提供 pSize 指针,并在 jpeg_stdio_dest 的实现函数里对新添加的变量进行初始化,如下:GLOBAL(void)jpeg_stdio_dest (my_dest_ptr dest;press_ptr cinfo, char * outdata,*pSize)/* The destination object is made permanent sot multiple JPEG imagescan be written to the same file without re-executing jpeg_stdio_dest.T
16、his makes it dangerous to use this manager and a different destinationmanager serially with the same JPEG object, because their private objectsizes may be different. Caveat programmer.*/if (cinfo-dest = NULL) /*time for this JPEG object? */cinfo-dest = (struct jpeg_destination_mgr *)(*cinfo-mem-allo
17、c_small) (SIZEOF(my_destination_mgr);mon_ptr) cinfo, JPOOL_PERMANENT,dest = (my_dest_ptr) cinfo-dest;dest-pub.init_destination = init_destination;dest-pub.empty_output_buffer = empty_output_buffer; dest-pub.term_destination = term_destination;/* 修改过的代码 */dest-outdata = outdata; dest-nOutOffset = 0;
18、dest-pSize = pSize;*(dest-pSize)= 0;改写函数EXTERN(void) jpeg_stdio_dest JPP(*pSize);press_ptr cinfo, char* outdata,jdatadst.cpp 文件第 87 行 empty_output_buffer (press_ptr cinfo)函数memcpy(dest-outdata+dest-nOutOffset,dest-buffer,OUTPUT_BUF_SIZE);/ 由 JFWRITE(dest-outfile, dest-buffer, OUTPUT_BUF_SIZE)改写 dest
19、-nOutOffset+=OUTPUT_BUF_SIZE;*(dest-pSize)=dest-nOutOffset;jdatadst.cpp 文件第 114 行 term_destination (press_ptr cinfo)memcpy(dest-outdata+dest-nOutOffset,dest-buffer,dount);/ 由JFWRITE(dest-outfile, dest-buffer, dount)改写dest-nOutOffset+=dount;*(dest-pSize)=dest-nOutOffset;重新编译工程,这样就实现了压缩 bmp 位图到内存中,当然,
20、调用 jpeg_stdio_dest之前,需要先分配足够的内存,并把内存指针传递给 jpeg_stdio_dest 函数,好了,再分析 libjpeg 在解压缩 jpg 图像时,是怎样从 jpg 文件读入图像数据的。先看在解压缩图像时调用的与文件操作有关的函数,如下:jpeg_stdio_src (press_ptr cinfo, FILE * infile)。在该函数的实现代码中找到了 my_src_ptr 结构,并且,发现与文件操作有关的该结构的成员变量为 infile,参考上面内容,搜索 infile,搜索结果如下:Find all infile, Subfolders, Find Re
21、sults 1, Entire SolutionE:VS2005libjpeglibjpegjpeglib.h(911):EXTERN(void)jpeg_stdio_srcJPP(press_ptr cinfo, FILE * infile);E:VS2005libjpeglibjpegjdatasr*/E:VS2005libjpeglibjpegjdatasr src-buffer, INPUT_BUF_SIZE);E:VS2005libjpeglibjpegjdatasrp(28): FILE * infile; /* sourtreamp(95): nbytes = JFREAD(sr
22、c-infile,p(182):jpeg_stdio_src(press_ptr cinfo, FILE * infile)E:VS2005libjpeglibjpegjdatasrp(209): src-infile = infile;Matching lines: 5Matching files: 2Total files searched: 57根据上面的经验,考虑,除了将 FILE *类型变量改为 char *类型的变量外,还要添加两个变量,图像大小的变量及图像偏移量,这跟图像压缩时差不多,所不同的是,图像压缩时,图像大小是由 libjpeg 库返回,所以在调用是提供给 libjpeg
23、 库的是个指针,而在解压缩时,图像数据大小是由调用者通过变量(不是指针)提供给 libjpeg 库。由于我详细讲解了图像压缩时的所做的工作读者朋友们很容易就能理解解压缩时所做的更改,下面我只列出jpeglib.h 第 911 行所改写的代码,就不再详细讲解了。EXTERN(void) jpeg_stdio_src JPP(nSize);press_ptr cinfo, char* indata,jdatasrp 第 33 行/* Expanded data source object for stdio input */ typedef struct struct jpeg_source_mg
24、r pub; /* public fields */char * indata; /* sour nInOffset;nSize;tream */JOCTET * buffer; /* start of buffer */start_of_file; /* have we gotten any data yet? */ my_source_mgr;jdatasrp 第 183 行GLOBAL(void) jpeg_stdio_src (my_src_ptr src;press_ptr cinfo, char * indata,nSize)/* The source object and inp
25、ut buffer are made permanent sot a series* of JPEG images can be read from the same fiy calling jpeg_stdio_src* only before theone. (If we discarded the buffer atofone image, wed likely lose the start of the next one.)This makes it unsafe to use this manager and a different sourcemanager serially wi
26、th the same JPEG object. Caveat programmer.*/if (cinfo-src = NULL) /*time for this JPEG object? */cinfo-src = (struct jpeg_source_mgr *)(*cinfo-mem-alloc_small) ( SIZEOF(my_source_mgr);src = (my_src_ptr) cinfo-src; src-buffer = (JOCTET *)(*cinfo-mem-alloc_small) (mon_ptr) cinfo, JPOOL_PERMANENT,mon_
27、ptr) cinfo, JPOOL_PERMANENT,INPUT_BUF_SIZE * SIZEOF(JOCTET);src = (my_src_ptr) cinfo-src;src-pub.init_source = init_source;src-pub.fill_input_buffer = fill_input_buffer;src-pub.skip_input_data = skip_input_data;src-pub.resync_to_restart = jpeg_resync_to_restart; /* use default method*/src-pub.term_s
28、ource = term_source;src-indata = indata;/ 新添加行src-nSize = nSize;/ 新添加src-nInOffset = 0;/ 新添加src-pub.bytes_in_buffer = 0; /* forfill_input_buffer onread */src-pub.next_input_byte = NULL; /* until buffer loaded */jdatasrp 第 91 行METHODDEF(fill_input_buffer ()press_ptr cinfo)my_src_ptr src = (my_src_ptr
29、) cinfo-src; size_t nbytes;/nbytes = JFREAD(src-infile, src-buffer, INPUT_BUF_SIZE); nbytes = src-nSize-src-nInOffset;if (nbytesINPUT_BUF_SIZE) nbytes = INPUT_BUF_SIZE;if (nbytes start_of_file) /* Treat empty input file as fatal error */ ERREXIT(cinfo, JERR_INPUT_EMPTY);WARNMS(cinfo, JWRN_JPEG_EOF);
30、/* Insert a fake EOI marker */ src-buffer0 = (JOCTET) 0 xFF;src-buffer1 = (JOCTET) JPEG_EOI; nbytes = 2;memcpy(src-buffer,src-indata+src-nInOffset,nbytes); src-nInOffset+=nbytes;src-pub.next_input_byte = src-buffer; src-pub.bytes_in_buffer = nbytes;src-start_of_file = FALSE;return TRUE;至此,libjpeg 库的源代码中所有要改的东西都已经完成,剩下的事情就是段测试程序测试一下。三、编写测试代码编写一对于 libjpeg 库的详细的调用步骤,请参照式,上面详细介绍了利用 libjpeg 库文章利用 jpeglib 压缩图像为 jpg 格进行图像压缩和解压缩的步骤,在编写本例的测试代码时,础上进行改进,如下:在上次提供的测试代码的基无论压缩还是解压缩, 与原来的 libjpeg 库调用不同的地方都只有一处, 就是jpeg_stdio_dest 和 jpeg_stdio_src 这两个函数的调用,调用原来的 libjpeg 库时,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 胃肠减压的护理新进展
- 肝硬化患者中医护理方法
- 工程建设标准强制性条文检查制度
- 2026年大型机械设备进出场方案范本(2篇)
- 肠胀气婴儿的护理要点
- 数字化转型与内容质量提升-洞察与解读
- 跨媒介叙事比较-洞察与解读
- 2026年建筑工地安全责任合同协议二篇
- 羔羊数字化养殖技术应用
- 短视频用户粘性分析-洞察与解读
- 2026年宝鸡市辛家山林业局、宝鸡市马头滩林业局招聘(12人)考试参考题库及答案解析
- 江西省南昌市2026届高三年级四月第二次模拟语文试卷(含答案)
- 2026广岩国际投资有限责任公司招聘14人备考题库附答案详解(综合卷)
- XJJ013-2012 新疆维吾尔自治区城市规划管理技术规定
- 2026年非遗保护中心招聘考试面试题及参考答案
- 智慧树 创造性思维与创新方法 章节测试答案
- 2025-2026中国市场IP商业化价值研究报告
- 2026年创新药挂网采购随时申报自主定价直接挂网流程
- 2026年商丘职业技术学院单招职业技能测试题库及答案详解(名师系列)
- 机械厂卫生管理制度
- RnB介绍教学课件
评论
0/150
提交评论