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