本文只介紹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格式,該實例並沒有提供文件有效性的驗證,如果要引入自己的代碼,請自己實現文件有效性的驗證。