Home People Research Blog Courses Links Search Download
NCHC

Blog

Blog 最新文章

  1. Visual Studio 的遠端偵錯:Windows
    2021/03/24 14:45
  2. Visual Studio 2019 16.9 支援使用 OpenMP LLVM
    2021/03/03 13:52
  3. Valve 推出完全支援 OpenXR 的 SteamVR 1.16.8
    2021/02/25 09:43

Blog 最新回應

  1. 加入斜體文字...
    2021/02/07 21:06
  2. 加入斜體文字...
    2021/02/07 21:06
  3. 加入斜體文字...
    2021/02/07 21:06

Keyword 關鍵字

OpenGL C++20 Valve Index 3d print OpenNI 開放資料 C++11 OpenCL PHP Pandas Docker Docker HTC Vive VR Qt NiTE2 OpenNI2 HTC Vive Focus Oculus Rift S VR Python Boost C++14 Oculus Quest 2 Vulkan CubeX HoloLens 2 Windows MR xml Oculus WebGL OpenXR OpenVR iFlyover HTC Vive Pro Pandas C++ git C++14 ASUS Xtion 資訊地圖 CUDA Java OpenCV MR OpenMP Python 資料視覺化 Kinect C++17 javascript 3D立體 GitLab 開放資料 svn

類別:技術相關 » 技術研究
文章發表|我要回應|RSS訂閱

在記憶體內進行 JPEG 壓縮

一般要將圖片儲存成特定的檔案格式、進行壓縮的話,大部分都是直接寫到磁碟裡。不過,有的時候其實可能只是要進行壓縮,而不想寫到磁碟上(速度比較慢、而且還要再讀回來),這個時候,就必須要特別處理。

而 Independent JPEG Group 的 JPEG 函式庫(官網)目前就有提供 jpeg_mem_dest() 這個函式,可以再壓縮的時候,把資料寫到指定的記憶體空間,而不用寫到磁碟上。

如果要把相關功能包成一個函式的話,寫法大概就會像下面這樣:

std::pair<unsigned char*,unsigned long> CompressJPEG(
unsigned int uWidth, unsigned int uHeight,
unsigned char* pImg, int iQuality = 75 )
{
std::pair<unsigned char*,unsigned long> mRes
= std::make_pair( (unsigned char*)NULL, 0 );
 
// setup JPEG compression structure data
jpeg_compress_struct jcInfo;
jpeg_error_mgr jErr; // JPEG error handler
jcInfo.err = jpeg_std_error ( &jErr );
 
// initialize JPEG compression object
jpeg_create_compress( &jcInfo );
 
// specify data destination is memory
jpeg_mem_dest( &jcInfo, &mRes.first, &mRes.second );
 
// image format
jcInfo.image_width = uWidth;
jcInfo.image_height = uHeight;
jcInfo.input_components = 3;
jcInfo.in_color_space = JCS_RGB;
 
// set default compression parameters
jpeg_set_defaults( &jcInfo );
 
// set image quality
jpeg_set_quality( &jcInfo, iQuality, TRUE );
 
// start compressor
jpeg_start_compress( &jcInfo, TRUE );
int iRowStride = jcInfo.image_width * jcInfo.input_components;
while( jcInfo.next_scanline < jcInfo.image_height )  {
JSAMPROW pData = &( pImg[ jcInfo.next_scanline * iRowStride ] );
jpeg_write_scanlines( &jcInfo, &pData, 1 );
}
 
// finish compression
jpeg_finish_compress( &jcInfo );
 
// release JPEG compression object
jpeg_destroy_compress( &jcInfo );
 
return mRes;
}

這邊要輸入的參數基本上有四個,uWidth 和 uHeight 是圖片的寬和高,pImg 則是圖片的內容(未壓縮的);最後的 iQuality 則是壓縮成 JPEG 時,所要設定的品質(0-100)。至於影像的像素格式,Heresy 這邊是寫死成三個 channel、也就是 RGB 的格式。

回傳的結果有兩種資料,這邊用 std::pair 來做簡單的包裝。裡面第一項的 unsigned char* 指到的記憶體空間,就是壓縮完的資料,而第二項的 unsigned long 數值,則是代表這個資料的長度。

而如果是要使用的話,假設有一個 unsigned char 的陣列 pImg,它的大小是 w x h 的話,那只要執行下方程式碼的第一行,就可以取得壓縮成 JPEG 的資料(pJpeg)了~

std::pair<unsigned char*,unsigned long> pJpeg = CompressJPEG( w, h, pImg, 100 );
ofstream of( "e:\\test.jpg", ios::binary );
of.write( (char*)pJpeg.first, pJpeg.second );
of.close();

而如果要驗證的話,最簡單的方法,還是把他寫出來、變成實際的檔案;這時候,只要透過 ofstrem,用 binary 的形式,整個寫出來就好了。

參考:《Compressing IplImage to JPEG using libjpeg in OpenCV》

張貼者:heresy於2013/07/29 15:53 下午有0則回應,瀏覽次數:1,482次

-- TOP --

我要回應
* 身份  訪客 (暱稱:)
 本篇文章作者 (帳號:密碼:)
* 內容      
很高興 悲傷 震驚 疑惑 大笑 發瘋 傷心
* 留言密碼 (請輸入下方圖片中去除前、後位數的數字,共五碼。)
說明 1. * 表示必填欄位。
2. 不支援HTML Tag。
   

-- TOP --

© Visualization and Interactive Media Laboratory of NCHC, 2007 - 2021, All Rights Reserved. Contact E-mail