jpg毀損檢測思路

基於libjpeg保存jpg圖像或者讀取圖像時,特別是再存儲大尺寸圖像時,一個問題特別突出。即圖像存儲明明毀損了,可是調用存儲的函數直接再控制檯輸出警告信息,可是沒有返回值或者異常可供捕獲。形成毀損的緣由不明。只能推測是libjpeg多線程存儲問題。其中圖像存在 JWRN_JPEG_EOF 問題時特別緻命。由於圖像從某一個節點以後信息所有無效。如下是最終算法可以捕獲的毀損。算法

JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")多線程

JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")ide

JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")函數

JWRN_JPEG_EOF是核心要解決的問題。 後倆者是最後優化代碼時剩餘部分比較複雜,時間有限,保留代碼順帶檢測。優化

動手解決以前思路:基於libjpeg庫,屏蔽掉無關代碼,將警告改成異常拋出。捕獲併產生相應記錄信息。由於是提早終止,所以期待直接從文件頭獲取文件長度和實際文件長度比較,直接獲得斷定。spa

實際解決思路:線程

1.借鑑opencv的庫進行libjpeg從新改寫。指針

2.將libjpeg裏面一些C代碼更改成C++代碼,並消除一些與檢測無關代碼,提升檢測效率。code

3.跟蹤JWRN_JPEG_EOF 出現位置,梳理先後代碼。發現動手前的思路存在缺失。並不能直接獲取文件長度進行比較。實際jpg判斷該問題是基於段,每次循環前斷定當前讀取字節數 < 該段字節總數。是的話一次讀取固定長度(jpg代碼有具體數值)。當讀取到字節數目<固定長度,就會進行斷定 拋出倆種異常其中一種 就是「JWRN_JPEG_EOF」。 原始libjpg代碼以下:blog

 1 METHODDEF(boolean)  2  fill_input_buffer (j_decompress_ptr cinfo)  3 {  4     my_src_ptr src = (my_src_ptr) cinfo->src;  5  size_t nbytes;  6 
 7     nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);  8 
 9     if (nbytes <= 0) { 10         if (src->start_of_file)    /* Treat empty input file as fatal error */
11  ERREXIT(cinfo, JERR_INPUT_EMPTY); 12  WARNMS(cinfo, JWRN_JPEG_EOF); 13         /* Insert a fake EOI marker */
14         src->buffer[0] = (JOCTET) 0xFF; 15         src->buffer[1] = (JOCTET) JPEG_EOI; 16         nbytes = 2; 17  } 18 
19     src->pub.next_input_byte = src->buffer; 20     src->pub.bytes_in_buffer = nbytes; 21     src->start_of_file = FALSE; 22 
23     return TRUE; 24 }
 1 METHODDEF(boolean)  2  fill_mem_input_buffer (j_decompress_ptr cinfo)  3 {  4   static const JOCTET mybuffer[4] = {  5     (JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0
 6  };  7 
 8   /* The whole JPEG data is expected to reside in the supplied memory  9  * buffer, so any request for more data beyond the given buffer size 10  * is treated as an error. 11    */
12  WARNMS(cinfo, JWRN_JPEG_EOF); 13 
14   /* Insert a fake EOI marker */
15 
16   cinfo->src->next_input_byte = mybuffer; 17   cinfo->src->bytes_in_buffer = 2; 18 
19   return TRUE; 20 }

4.找到查錯代碼後更改自定義代碼。我理解不夠沒有從新書寫代碼,而是經過剝離出來的opencv的jpeg庫調用。而後跟蹤執行路徑,把執行路徑中的函數標記出來,從新寫成本身的函數,而後調用。

5.最終效果:使用opencv讀取圖片會報 JWRN_JPEG_EOF,我這邊也會報。執行時間:16000*8192彩色圖像,用imread執行時間3~5s,用我更改後的libjpeg庫只須要0.2~0.3s(這邊耗時主要霍夫編解碼上面。由於指針遍歷有部分再霍夫編解碼上,趕時間沒有細究。若是消除的話就是 10ms之內級別操做)。

 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2019-05-10這樣直接改某些狀況下會觸發野指針。暫不清楚引發得緣由。由於此時有問題的圖片能打開,能看。不肯定是真的文件存在問題,仍是寫的算法有問題。因此最好加異常捕獲代碼。

相關文章
相關標籤/搜索