实现从内存中解压JPEG

一、简介 

   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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容使用说明 YOLO高分设计资源源码,详情请查看资源内容使用说明 YOLO高分设计资源源码,详情请查看资源内容使用说明 YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明
根据提供的引用内容,JPEG算法是一种有损压缩算法,而且实现起来比较复杂。Python有一些第三方库可以实现JPEG压缩和解压缩,比如Pillow和OpenCV。下面是使用Pillow库实现JPEG压缩和解压缩的示例代码: 压缩文件: ```python from PIL import Image # 打开原始图像 img = Image.open('original.jpg') # 将图像转换为YCbCr颜色空间 img_ycbcr = img.convert('YCbCr') # 对每个颜色通道进行离散余弦变换(DCT) img_dct = img_ycbcr.copy() img_dct = img_dct.transform((img.width // 8, img.height // 8), Image.EXTENT, (8, 8), Image.DCT) # 量化DCT系数 quantization_table = [ [16, 11, 10, 16, 24, 40, 51, 61], [12, 12, 14, 19, 26, 58, 60, 55], [14, 13, 16, 24, 40, 57, 69, 56], [14, 17, 22, 29, 51, 87, 80, 62], [18, 22, 37, 56, 68, 109, 103, 77], [24, 35, 55, 64, 81, 104, 113, 92], [49, 64, 78, 87, 103, 121, 120, 101], [72, 92, 95, 98, 112, 100, 103, 99] ] img_quantized = img_dct.copy() for x in range(img_dct.width): for y in range(img_dct.height): img_quantized.putpixel((x, y), tuple([round(img_dct.getpixel((x, y))[i] / quantization_table[y % 8][x % 8]) for i in range(3)])) # 将量化后的DCT系数写入文件 with open('compressed.jpg', 'wb') as f: for y in range(img_quantized.height): for x in range(img_quantized.width): for i in range(3): f.write(bytes([img_quantized.getpixel((x, y))[i]])) ``` 解压文件: ```python from PIL import Image # 从文件读取量化后的DCT系数 with open('compressed.jpg', 'rb') as f: img_quantized = Image.new('YCbCr', (512, 512)) for y in range(img_quantized.height): for x in range(img_quantized.width): img_quantized.putpixel((x, y), tuple([int.from_bytes(f.read(1), byteorder='big') for i in range(3)])) # 反量化DCT系数 quantization_table = [ [16, 11, 10, 16, 24, 40, 51, 61], [12, 12, 14, 19, 26, 58, 60, 55], [14, 13, 16, 24, 40, 57, 69, 56], [14, 17, 22, 29, 51, 87, 80, 62], [18, 22, 37, 56, 68, 109, 103, 77], [24, 35, 55, 64, 81, 104, 113, 92], [49, 64, 78, 87, 103, 121, 120, 101], [72, 92, 95, 98, 112, 100, 103, 99] ] img_dct = img_quantized.copy() for x in range(img_quantized.width): for y in range(img_quantized.height): img_dct.putpixel((x, y), tuple([img_quantized.getpixel((x, y))[i] * quantization_table[y % 8][x % 8] for i in range(3)])) # 对每个颜色通道进行反离散余弦变换(IDCT) img_ycbcr = img_dct.copy() img_ycbcr = img_ycbcr.transform((img_dct.width * 8, img_dct.height * 8), Image.EXTENT, (8, 8), Image.IDCT) # 将图像转换回RGB颜色空间 img_rgb = img_ycbcr.convert('RGB') # 保存解压后的图像 img_rgb.save('uncompressed.jpg') ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值