使用libjpeg处理图像(libjpeg的使用压缩与解压缩jpg格式)

来源:互联网 发布:雷军是金山软件的 编辑:程序博客网 时间:2024/05/18 02:19

From: http://hi.baidu.com/d_south/blog/item/621285d494e41c09a08bb706.html

 

标题:利用libjpeg处理图像
作者:赵新国
Email:zhao3728@sina.com

关键字: jpeg, 图像压缩

 

前一段时间做了一个项目,项目中有一部分是关于图像采集的,相关硬件有:高速数字相机(我们采用Basler A312f),工控机,服务器。其中相机通过1394视频线连接到工控机的1394视频卡上,工控机与服务器通过百兆网连接。具体工作流程为:工控机控制相机采集图像,帧率一般为40HZ左右,采集的图像为位图数据,需要自己在程序中封装为bmp格式,然后压缩成jpg格式,压缩后的图像一方面保存到本地硬盘,同时要传输到服务器上。

  本文只介绍jpeg压缩的相关内容,刚开始我贪图省事,采用微软 的GDI Plus提供的功能,很是方便,先获取jpg图像的编码,然后根据图像的位图数据创建一个Bitmap类的对象,再保存图像为jpg格式就行了。但是我对GDI+还是很信任,总感觉不踏实(没有理由的),我们的系统一旦安装就要长期运行,我就是担心长期运行一段时间后GDI+会出问题,结果也证实了我的担心,我们实际使用的10套系统中有一套,连续运行3-5天后,GDI+就会崩溃,于是我决心采用IJG JPEG Library。您可以到www.ijg.org网站下载libjpeg的源码, IJG JPEG Library就是jpeg压缩库,是以源码的形式提供给软件开发人员的,当然在软件包里也有编译好的库文件,我们这里就只用到其中的libjpeg.lib,jconfig.h,jmorecfg.h,jpeglib.h这几个文件,下面我就介绍一下怎样在自己的程序里嵌入图像压缩功能。

  一、建立编译环境

  所谓建立编译环境,其实非常简单,就是把上面提到的4个文件拷贝到你的项目文件夹下,把libjpeg.lib添加到你的项目中,然后在你完成压缩功能的那个文件里加入#include "jpeglib.h",需要注意的是,libjpeg.lib是用c语言开发的,如果要用在你的C++程序里,需要用到extern "C",如下:

// TestLibjpeg.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "memory.h"
extern "C" {
#include "jpeglib.h"
}

  二、压缩步骤

  1、申请并初始化jpeg压缩对象,同时要指定错误处理器

struct jpeg_compress_struct jcs;

// 声明错误处理器,并赋值给jcs.err域
   struct jpeg_error_mgr jem;
   jcs.err = jpeg_std_error(&jem);

   jpeg_create_compress(&jcs);

  2、指定压缩后的图像所存放的目标文件,注意,目标文件应以二进制模式打开

f=fopen("03.jpg","wb");
   if (f==NULL)
   {
   delete [] data;
   delete [] pDataConv;
   return 0;
   }
   jpeg_stdio_dest(&jcs, f);

  3、设置压缩参数,主要参数有图像宽、高、色彩通道数(1:索引图像,3:其他),色彩空间(JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像),压缩质量等,如下:

   jcs.image_width = nWidth;    // 为图的宽和高,单位为像素
   jcs.image_height = nHeight;
   jcs.input_components = 1;   // 在此为1,表示灰度图, 如果是彩色位图,则为3
   jcs.in_color_space = JCS_GRAYSCALE; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像

   jpeg_set_defaults(&jcs);
jpeg_set_quality (&jcs, 80, true);

需要注意的是,jpeg_set_defaults函数一定要等设置好图像宽、高、色彩通道数计色彩空间四个参数后才能调用,因为这个函数要用到这四个值,调用jpeg_set_defaults函数后,jpeglib库采用默认的设置对图像进行压缩,如果需要改变设置,如压缩质量,调用这个函数后,可以调用其它设置函数,如jpeg_set_quality函数。其实图像压缩时有好多参数可以设置,但大部分我们都用不着设置,只需调用jpeg_set_defaults函数值为默认值即可。

  4、上面的工作准备完成后,就可以压缩了,压缩过程非常简单,首先调用jpeg_start_compress,然后可以对每一行进行压缩,也可以对若干行进行压缩,甚至可以对整个的图像进行一次压缩,压缩完成后,记得要调用jpeg_finish_compress函数,如下:

   jpeg_start_compress(&jcs, TRUE);

   JSAMPROW row_pointer[1];   // 一行位图
   int row_stride;      // 每一行的字节数

row_stride = jcs.image_width; // 如果不是索引图,此处需要乘以3

   // 对每一行进行压缩
   while (jcs.next_scanline < jcs.image_height) {
        row_pointer[0] = & pDataConv[jcs.next_scanline * row_stride];
        jpeg_write_scanlines(&jcs, row_pointer, 1);
   }

   jpeg_finish_compress(&jcs);

  5、最后就是释放压缩工作过程中所申请的资源了,主要就是jpeg压缩对象,由于在本例中我是直接用的局部变量,所以只需调用jpeg_destroy_compress这个函数即可,如下:

jpeg_destroy_compress(&jcs);

  三、解压缩步骤
  解压缩步骤与压缩步骤非常相似,只是解压缩对象为jpeg_decompress_struct类型,步骤如下:
  1、声明并初始化解压缩对象,同时制定错误信息管理器
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;

cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
  2、打开jpg图像文件,并指定为解压缩对象的源文件
FILE *f = fopen(strSourceFileName,"rb");
if (f==NULL)
{
   printf("Open file error!/n");
   return;
}
//
jpeg_stdio_src(&cinfo, f);
  3、读取图像信息
jpeg_read_header(&cinfo, TRUE);
  4、根据图像信息申请一个图像缓冲区
data = new BYTE cinfo.image_width*cinfo.image_height*cinfo.num_components];
  5、开始解压缩
jpeg_start_decompress(&cinfo);

JSAMPROW row_pointer[1];
while (cinfo.output_scanline < cinfo.output_height)
{
   row_pointer[0] = &data[(cinfo.output_height - cinfo.output_scanline-1)*cinfo.image_width*cinfo.num_components];
   jpeg_read_scanlines(&cinfo,row_pointer ,
      1);
}
jpeg_finish_decompress(&cinfo);
  6、释放资源
jpeg_destroy_decompress(&cinfo);

fclose(f);

  好了,利用IJG JPEG Library进行图像压缩就介绍到这里,希望对大家有所帮助,实例代码已经实现了图像的压缩和解压缩的全部功能,命令格式为:“TestLibjpeg.exe j|j24|b 源文件名 目标文件名”,其中,j选项将源文件压缩为jpg格式,不改变色彩模式,j24选项将源文件压缩为24为jpg格式,b选项将源文件解压缩为bmp格式,该实例并没有提供文件有效性的验证,如果要引入自己的代码,请自己实现文件有效性的验证。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 华为手机不停的自动重启怎么办 华为荣耀4x卡在开机界面怎么办 华为荣耀8青春版密码忘了怎么办 华为手机内存满了开不起来怎么办 华为荣耀畅玩平板2比较卡怎么办 红米4x太卡了怎么办 魅蓝e移动卡只有2g网络怎么办 联通关闭2g网络双卡手机怎么办 小米6x手机插耳机音量大怎么办 音量键和亮度键盘拆了怎么办 荣耀v10锁屏密码忘了怎么办 荣耀9锁屏密码忘记了怎么办 华为荣耀v9锁屏密码忘记了怎么办 荣耀手机密码忘了怎么办数字锁 华为畅享5忘了开机密码怎么办 华为p9连接热点忘了密码怎么办 苹果手机用联通卡信号不好怎么办 魅族手机充电口松了怎么办 华为手机刷机失败开不了机怎么办 华为刷机失败开不了机怎么办 银行卡信息被盗密码被改该怎么办 全民k歌手机话筒有杂音怎么办 手机刷机清除数据需要密码怎么办 oppo手机屏锁密码忘了怎么办 华为手机摔了一下开不了机怎么办 华为v9手机删除隐私空间了怎么办 华为荣耀畅玩5x卡顿怎么办 淘宝买家收到货后恶意退款怎么办 手机淘宝申请退款后不想退了怎么办 买房交首付时的收据发票掉了怎么办 苹果商城消费提示问题忘记了怎么办 psd文件超过2g不能存储怎么办 手机拍的照片做微信头像太大怎么办 上传的照片在等待中传不上去怎么办 淘宝购物车里的图片模糊怎么办 天猫超市一箱饮料少两瓶怎么办 网上卖一件代发顾客要退货怎么办 京东买东西卖家拒绝发货怎么办 淘宝不小心退款给买家了怎么办 不小心智能清理了淘宝物流怎么办 移动卡绑定了太多东西换联通怎么办