在一个项目中需要将一些图像数据保存成文件,出现的问题是数据量非常大,文件高达几百兆以及上G,所以需要对数据进行压缩,Google了一下,发现了LIBJPEG这个开源库,在项目中使用后效果非常好,文件一下子减小了很多。
http://www.ijg.org/是这个库的网站,从上面可以下载最新的源代码以及编译好的库,是一个Independent JPEG Group的组织(简称IJG)开发的一个开源免费库,下一个版本将在2013年发布。
但在使用的时候存在一个问题,LIBJPEG无论压缩还是解压缩操作的时候都是对FILE指针来操作,如果我有一个图像数据,无法直接对图像数据进行压缩。还好有源代码,很多人对源代码进行了改造,使得可以支持对内存数据进行压缩和解压缩,具体过程在这就不详细叙述,后面会给出一些参考网站。
这个库使用起来非常简单,下面给出我写的一个简单的压缩类和解压类:
#pragma once #include <stdio.h> extern "C" { #include "jpeglib.h" }; class CJpegCompress { public: CJpegCompress(void); ~CJpegCompress(void); public: //初始化压缩参数 //buffer:压缩后的数据内存,pSize输出压缩后的数据大小 //nWidth,nHeight,nChannel宽度高度和通道数 void InitCompressVar(char* buffer,int* pSize,int nWidth,int nHeight,int nChannel); //压缩 //buffer:输入原始数据,nStride:图像stride void CompressBuffer(unsigned char* buffer,int nStride); protected: struct jpeg_compress_struct jcs; struct jpeg_error_mgr jem; }; #include "StdAfx.h" #include "JpegCompress.h" #pragma comment(lib,"..\\lib\\MyJpegLib.lib") CJpegCompress::CJpegCompress(void) { jcs.err = jpeg_std_error(&jem); jpeg_create_compress(&jcs); } CJpegCompress::~CJpegCompress(void) { jpeg_destroy_compress(&jcs); } //nChannel = 1 或 3 void CJpegCompress::InitCompressVar(char* buffer,int* pSize,int nWidth,int nHeight,int nChannel) { jpeg_stdio_dest(&jcs, buffer,pSize); jcs.image_width = nWidth; // 为图的宽和高,单位为像素 jcs.image_height = nHeight; jcs.input_components = nChannel; // 在此为1,表示灰度图, 如果是彩色位图,则为3 jcs.in_color_space = nChannel == 1 ? JCS_GRAYSCALE:JCS_RGB; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像 jpeg_set_defaults(&jcs); jpeg_set_quality (&jcs, 80, true); } void CJpegCompress::CompressBuffer(unsigned char* buffer,int nStride) { jpeg_start_compress(&jcs, TRUE); JSAMPROW row_pointer[1]; // 一行位图 int row_stride; // 每一行的字节数 row_stride = nStride; while (jcs.next_scanline < jcs.image_height) { row_pointer[0] = &buffer[(jcs.image_height-1-jcs.next_scanline) * row_stride]; jpeg_write_scanlines(&jcs, row_pointer, 1); } jpeg_finish_compress(&jcs); } #pragma once #include <stdio.h> extern "C" { #include "jpeglib.h" }; class CJpegDecompress { public: CJpegDecompress(void); ~CJpegDecompress(void); public: void GetImageInfo(char* inBuffer,int size,int& nwidth,int& nHeight,int& nChannel); void DeCompressBuffer(unsigned char* Outbuffer); protected: struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jem; }; #include "StdAfx.h" #include "JpegDeCompress.h" #pragma comment(lib,"..\\lib\\MyJpegLib.lib") CJpegDecompress::CJpegDecompress(void) { cinfo.err = jpeg_std_error(&jem); jpeg_create_decompress(&cinfo); } CJpegDecompress::~CJpegDecompress(void) { jpeg_destroy_decompress(&cinfo); } void CJpegDecompress::GetImageInfo(char* inBuffer,int size,int& nwidth,int& nHeight,int& nChannel) { jpeg_stdio_src(&cinfo,inBuffer,size); jpeg_read_header(&cinfo, TRUE); nwidth = cinfo.image_width; nHeight = cinfo.image_height; nChannel = cinfo.num_components; } void CJpegDecompress::DeCompressBuffer(unsigned char* Outbuffer) { jpeg_start_decompress(&cinfo); JSAMPROW row_pointer[1]; while (cinfo.output_scanline < cinfo.output_height) { row_pointer[0] = &Outbuffer[(cinfo.output_height - cinfo.output_scanline-1)*cinfo.image_width*cinfo.num_components]; jpeg_read_scanlines(&cinfo,row_pointer ,1); } jpeg_finish_decompress(&cinfo); }
使用起来都非常方便简单,具体调用示例就不列出了,这里用的库是我经过改造之后的LIBJPEG库,如果有谁需要,本人可以将改造后的LIBJPEG代码无私奉献出去,省去大家改造的麻烦,欢迎大家交流沟通,我的邮箱:[email protected]
参考资料:
http://blog.csdn.net/achellies/article/details/4238056
http://www.ijg.org/
http://blog.chinaunix.net/space.php?uid=16400726&do=blog&id=2746316