标签:libjpeg库 jpeg解码 内存中数据 源码修改 范例提供
在“VS2013编译libjpeg库”这篇文章中本人介绍了如何在VS中编译libjpeg库并提供了一个应用的范例,而这篇文章将在此基础上,介绍如何用libjpeg库来解码内存中的jpeg数据。
其实这个需求已经不新鲜了,网上也能找到别人提供的一些解决方法,之所以要再次写不过是因为本人觉得那些方法或多或少都有些不对的地方,或者说因为版本的迭代,本来是对的,现在有点问题。当然,本人并没有很费心思的自己去一行一行的看源代码,实现的过程基本是参考这篇文章来做的,所以这里只是提供怎么改,而为什么这么改则可参考上文。
OK,言归正传,下面正式进入主题。
要让libjpeg库能直接解码内存中的jpeg数据,首先想到的自然是修改其源码,让其提供一个这样的函数接口给我们调用,本人也正是这么干的。在“VS2013编译libjpeg库”这篇文章中我们是在生成“jpeg.sln”这个VS工程之后就直接双击进去编译生成“jpeg.lib”这个静态链接库,而我们在这里要实现对其源码的修改,所以在之前需要先改好再编译。修改的内容如下:
找到jdatasrc.c这个文件(从命名可以看出其跟输入数据相关),在my_source_mgr这个结构体的上方添加一个结构体(jpeg内存块描述相关)如下:
typedef struct{
	UINT8* img_buffer;
	long buffer_size;
	long pos;
}BUFF_JPG;           然后将my_source_mgr结构的定义修改如下:
typedef struct {
  struct jpeg_source_mgr pub;	/* public fields */
  union{
	  BUFF_JPG jpg;		/* jpeg image buffer */
	  FILE * infile;		/* source stream */
  };
  JOCTET * buffer;		/* start of buffer */
  boolean start_of_file;	/* have we gotten any data yet? */
} my_source_mgr;  
   接着在文件中定义相应的回调函数,可先用“Ctrl+F”查找“METHODDEF(boolean)”,然后添加在其上方,代码如下:/*
* This function will read the jpeg memery block to fill the library buffer.
*/
METHODDEF(boolean)
jpg_fill_input_buffer (j_decompress_ptr cinfo)
{
  my_src_ptr src = (my_src_ptr) cinfo->src;
  size_t nbytes;
  if(src->jpg.img_buffer == NULL || src->jpg.pos >= src->jpg.buffer_size){
    nbytes = -1;
  }
  else {
    nbytes = (src->jpg.pos + INPUT_BUF_SIZE > src->jpg.buffer_size ? 	   	src->jpg.buffer_size - src->jpg.pos : INPUT_BUF_SIZE);
    memcpy(src->buffer, src->jpg.img_buffer + src->jpg.pos, nbytes);
    src->jpg.pos += nbytes;
  }
  if (nbytes <= 0) {
    if (src->start_of_file)	/* Treat empty input file as fatal error */
      ERREXIT(cinfo, JERR_INPUT_EMPTY);
    WARNMS(cinfo, JWRN_JPEG_EOF);
    /* Insert a fake EOI marker */
    src->buffer[0] = (JOCTET) 0xFF;
    src->buffer[1] = (JOCTET) JPEG_EOI;
    nbytes = 2;
  }
  src->pub.next_input_byte = src->buffer;
  src->pub.bytes_in_buffer = nbytes;
  src->start_of_file = FALSE;
  return TRUE;
}      做完上面这些,我们需要实现一个供用户用到解码内存中jpeg数据时初始化source
 manager的接口,添加位置和上面类似,代码如下:/*
* This function improve the library can use the jpeg memory block as source.
*/
GLOBAL(void)
jpeg_stdio_buffer_src (j_decompress_ptr cinfo, UINT8 * buffer, long size)
{
  my_src_ptr src;
  if (cinfo->src == NULL) {	/* first time for this JPEG object? */
    cinfo->src = (struct jpeg_source_mgr *)
      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
				  SIZEOF(my_source_mgr));
    src = (my_src_ptr) cinfo->src;
    src->buffer = (JOCTET *)
      (*cinfo->mem->alloc_small) ((j_common_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 = jpg_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_source = term_source;
  //src->infile = infile;
  src->jpg.img_buffer = buffer;
  src->jpg.buffer_size = size;
  src->jpg.pos = 0;
  src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
  src->pub.next_input_byte = NULL; /* until buffer loaded */
}            
这样我们在jdatasrc.c这个文件所要做的工作就做完了,其实修改的工作也可以说做的八九不离十了,只需要在jpeglib.h文件中将接口暴露出来即可,添加位置也是跟上面很类似的,不再赘述,代码如下:
EXTERN(void) jpeg_stdio_buffer_src JPP((j_decompress_ptr cinfo, UINT8 * buffer, long size));做完上面这些就大功告成了,编译出来的jpeg.lib已经支持解码内存中的jpeg数据了,jpeg_stdio_buffer_src这个函数就是相应的接口。
下面本人还是提供一个范例,如果懒得去改的话也可以直接用这个范例里面本人编好的“lib”和修改过的“.h”头文件。
标签:libjpeg库 jpeg解码 内存中数据 源码修改 范例提供
原文地址:http://blog.csdn.net/weixinhum/article/details/43089047