利用libjpeg8解压内存中的jpeg图片详解

最近在用zc301摄像头做视频,因为zc301是硬件压缩jpg的,所以从摄像头获取的图片是一张张的jpg文件,得转化成bmp才好处理。也知道libjpeg是linux中常用的jpg图片编解码器,但是在网上一查却发现很多人说libjpeg不支持解压内存中的数据,只能解压已经存在的jpeg文件!!!

如果想要解压内存中的数据,必须修改libjpeg源代码!!!

what a fucking thing!!!

后来想想,应该不至于吧,写这个库的人也不会那么无聊,这么实用的功能没道理不支持,于是下载最新的libjpeg8c原代码研究了一下,惊奇的发现这个库支持解压内存中的数据!

费话不多说,下面详细讲解怎么利用libjpeg8解压内存中的jpeg图片

配置安装libjpeg8c是应该不用说了吧

./configure --prefix=你希望安装的目录

make

make install



首先,我写了一个很方便调用的函数,大家愿意可以拿去尽管用

#include <stdio.h>
#include <stdlib.h>
#include "setjmp.h"
#include "jpeglib.h"

//这些头文件前2个是c必须的,后2个是libjpeg必须的,切忌要把libjpeg8的头文件放进你编写的程序所在的文件夹内,并且用#include “”这种形式调用,不然后面一定会出错,因为大多linux系统自带了libjpeg6的库,不这么做编译器会给你找到libjpeg6的库





下面这个函数可以直接调用就能出解压后的数据,如该函数示意,第一个参数为内存中jpeg文件所在的第一个字节,第二个参数为希望输出的bmp文件所存储的缓存的最后一个字节,为什么是最后一个字节?后面再说。第3个参数是jpeg文件的大小,怎么知道jpeg文件的大小呢?所有的jpeg文件都是以oxffd9结束,你可以用任何方式知道jpeg文件的大小,当然,最简单的是顺序遍历直到oxffd9,走过的字节个数+2就是大小了。

int jpeg_decompress(unsigned char *inbuf,unsigned char *outbuf,unsigned int size)
{
  struct jpeg_decompress_struct cinfo;
  struct my_error_mgr jerr;
  JSAMPARRAY buffer;

  int row_stride;  

  cinfo.err = jpeg_std_error(&jerr.pub);
  jerr.pub.error_exit = my_error_exit;

  if (setjmp(jerr.setjmp_buffer)) {
    jpeg_destroy_decompress(&cinfo);
    return 0;
  }

  jpeg_create_decompress(&cinfo);
  jpeg_mem_src(&cinfo,inbuf,size);
  jpeg_read_header(&cinfo, TRUE);

  jpeg_start_decompress(&cinfo);

  row_stride =cinfo.output_width * cinfo.output_components;//计算图片每行需要的内存大小,单位字节
  BMP_W = cinfo.output_width;
  BMP_H = cinfo.output_height;
  printf("output_width:%d\noutput_height:%d\noutput_components:%d\nrow_stride:%d\n",cinfo.output_width,cinfo.output_height,cinfo.output_components,row_stride);

  buffer = (*cinfo.mem->alloc_sarray)
  ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

//以上这些都是固定的调用步骤,不知道每句的意思的话千万别改动



/*

解压时,libjpeg是以图片的一行为单位解压的,也就是图片水平的一条线,jpeg存储时左上角是坐标原点,bmp存储时左下角是原点,因此转化时要把上下顺序颠倒一下才是正确的,所以outbuf传入的是最后一个字节的地址,从最后一个字节往前顺序拷贝jpg解压缩出来的数据才能得到正确的图片。

解压出来的bmp文件是24位图片,每个像素占用8位,因此如果图片大小为640*480,则outbuf大小应该为921654 = 640*480*3+54,其中54位为bmp文件头,则传入的outbuf应该是开辟的内存空间起始地址+921654,至于bmp头的制作我就不讲了,大家自己看吧,就那么点东西

*/

  while (cinfo.output_scanline < cinfo.output_height)

{
    outbuf -= row_stride;//指针前移一行
    jpeg_read_scanlines(&cinfo,buffer,1);解压出一行数据
    memcpy(outbuf,buffer[0],row_stride);将解压出的数据拷贝至outbuf
  }



//以上这些都是固定的调用步骤,不知道每句的意思的话千万别改动

  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);
  return 1;
}


这是一个完整的函数,可以直接调用就能解压内存中的jpeg图片,

编译时千万别以为加入了-ljpeg参数就可以了,老问题,编译器会给你链接libjpeg6的库,要指定库-l:libjpeg.so.8,如果找不到,前面再指定库目录 -L/你libjpeg的安装目录/lib,这样就一切完美了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值