实现从内存中解压JPEG

来源:互联网 发布:淘宝优惠券转化器 编辑:程序博客网 时间:2024/06/05 03:19

一、简介 

   Jpeg编解码的程序网络上有很多,也有很多现成的类如著名的CxImage,或者使用OpenCV。但是这些ToolTik基本上都只提供了从硬盘打开JPEG图像进行解码,有的时候如果JPEG的图像数据是从内存载入的,就无法使用这些曾经很方便高效的接口。比如OpenCV提供的接口是:CVAPI(IplImage*) cvLoadImage( const char* filename, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR));

二、解决的办法:

 

  1. 用ramdisk内存虚拟硬盘,把传输过来的jpg文件存在虚拟盘,再用cvLoadImage载入分析.
  2. OpenCV 2.0 提供该功能。(我装的是OpenCV 1.1,还没用过这两个函数)
    imdecode
    Mat imdecode( const Mat& buf, int flags );
    buf The input array of vector of bytes
    flags The same flags as in imread
    The function reads image from the specified buffer in memory. If the buffer is too short or
    contains invalid data, the empty matrix will be returned.
    See imread for the list of supported formats and the flags description.
    imencode
    bool imencode( const string& ext, const Mat& img,
    vector<uchar>& buf,
    const vector<int>& params=vector<int>());
    ext The file extension that defines the output format
    img The image to be written
    buf The output buffer; resized to fit the compressed image
    params The format-specific parameters; see imwrite
    The function compresses the image and stores it in the memory buffer, which is resized to fit
    the result. See imwrite for the list of supported formats and the flags description.
  3. 看了网上的一些代码,我使用JpegLib改了一个接口。opencv中也有JpegLib,如果要使用opencv中的JpegLib注意配置HAVE_JPEG。我把这个接口放到了OpenCV中,这样做是为了一劳永逸,其他工程要用到这个接口时不需要复制粘贴。

          首先在highgui.h中做函数声明

/**********************************************************************/
// by xjf 2009-11-09
// convert a jpeg image to bmp from a buffer
// cause we can use opencv to convert a jpeg image from file by easily 
//  using cvLoadImage()
//  the api in the grfmt_jpeg.cpp

CVAPI(IplImage*) cvJpeg2Ipl(char *jpegData, int jpegSize);

          

 

         函数的实现我放到了grfmt_jpeg.cpp

/**********************************************************************/
void mem_init_source(j_decompress_ptr cinfo)
{
//  cinfo->src->bytes_in_buffer = g_buf_len; 
//     cinfo->src->next_input_byte = (unsigned char*)g_buf;
}
boolean mem_fill_input_buffer(j_decompress_ptr cinfo)
{
 return true;
}
void mem_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
{
 cinfo->src->bytes_in_buffer -= num_bytes;
 cinfo->src->next_input_byte += num_bytes;
}
boolean mem_resync_to_restart(j_decompress_ptr cinfo, int desired)

 return jpeg_resync_to_restart(cinfo, desired);
}
void mem_term_source(j_decompress_ptr cinfo)
{
}

/**********************************************************************/
// @jpegData: 内存中的JPEG图像数据流

// @jpegSize:数据流大小
CV_IMPL IplImage* 
cvJpeg2Ipl(char *jpegData, int jpegSize)
{
 IplImage *_pImg = 0;
 
 jpeg_source_mgr jmgr;
 struct jpeg_error_mgr jerr;
 struct jpeg_decompress_struct cinfo;
 
 cinfo.err = jpeg_std_error(&jerr);
 jpeg_create_decompress(&cinfo);
 
 jmgr.init_source = mem_init_source; 
 jmgr.fill_input_buffer = mem_fill_input_buffer; 
 jmgr.skip_input_data = mem_skip_input_data;
 jmgr.resync_to_restart = mem_resync_to_restart;
 jmgr.term_source = mem_term_source; 
 jmgr.next_input_byte = (unsigned char*)jpegData; 
 jmgr.bytes_in_buffer = jpegSize;  
 
 cinfo.src = &jmgr;
 jpeg_read_header(&cinfo, TRUE);
 jpeg_start_decompress(&cinfo);
 
 int nRowSize = cinfo.output_width * cinfo.output_components;
 int w =cinfo.output_width;
 int h =cinfo.output_height;
 
 char *bmpBuffer=new char[h*w*3]; 
 JSAMPARRAY pBuffer = (*cinfo.mem->alloc_sarray)
  ((j_common_ptr) &cinfo, 1, nRowSize, 1);
 while(cinfo.output_scanline < cinfo.output_height) 
 {
  jpeg_read_scanlines(&cinfo, pBuffer, 1);
  
  int start=nRowSize*(cinfo.output_scanline-1);
  for(int i=0;i<nRowSize;i++)
  {
   bmpBuffer[start+i]=pBuffer[0][i];
  } 
 } 
 jpeg_finish_decompress(&cinfo);
 jpeg_destroy_decompress(&cinfo);
 
 _pImg = cvCreateImage(cvSize(w,h),8,3);
 for (h=0; h<_pImg->height; h++)
 {
  for (w=0; w<_pImg->widthStep; w+=3)
  {
   *(_pImg->imageData+h*_pImg->widthStep+w+0)=*(bmpBuffer+h*_pImg->widthStep+w+2);
   *(_pImg->imageData+h*_pImg->widthStep+w+1)=*(bmpBuffer+h*_pImg->widthStep+w+1);
   *(_pImg->imageData+h*_pImg->widthStep+w+2)=*(bmpBuffer+h*_pImg->widthStep+w+0);
  }
 } 

 

delete bmpBuffer;

bmpBuffer=NULL;
 return _pImg;
}

需重新编译opencv

原创粉丝点击