程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 解決使用 libjpeg 保存圖片時因磁盤寫入失敗導致程序退出的問題

解決使用 libjpeg 保存圖片時因磁盤寫入失敗導致程序退出的問題

編輯:C++入門知識

0. libjpeg 介紹

參考:http://zh.wikipedia.org/wiki/Libjpeg

1.使用 libjpeg 保存圖片的方法。

  不多說,直接上代碼:

 rgb_to_jpeg(LPRgbImage img,  **
    *                            error_flag = = jpeg_std_error(&&= fopen(filename,  (f == -
&= img->width;        
    jcs.image_height = img->height;        
    jcs.input_components = ;            
    jcs.in_color_space = JCS_RGB;        
    jpeg_set_defaults(&&jcs, , );        
    jpeg_start_compress(& (jcs.next_scanline <= img->rgb + jcs.image_width * jcs.next_scanline * &jcs, &pData, &&

 

  

 **= fopen(filename,  (f ==
    cinfo.err                 = jpeg_std_error(&&&&= (LPRgbImage) malloc( (pRgbImage ==->width    =->height    =->linesize    = libcfc_align_size(cinfo.image_width * ->rgb        = (unsigned *) malloc(pRgbImage->linesize * (pRgbImage->rgb ==&] = pRgbImage-> (cinfo.output_scanline <] = pRgbImage->+ (cinfo.image_height - cinfo.output_scanline - ) * pRgbImage->&cinfo, row_pointer, &&

 

2. 問題描述

  使用以上方法保存 rgb 數據到 jpeg 文件時,如果磁盤空間滿或其他原因導致不能寫文件失敗,整個進程會被結束。但我們的期望往往是磁盤空間滿時給出友好提示,而不是程序直接掛掉。

3. 問題分析

  1)在開發環境上重現此問題,程序會在控制台上打印“Output file write error --- out of disk space?”,然後退出。

  2)在 libjpeg 的源代碼中搜索 “Output file write error --- out of disk space?”,找到 jerror.h 文件,內容對應

      JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")。

  3)可以看出,JERR_FILE_WRITE 是 libjpeg 給這個問題描述信息定義的一個編號。

  4)查找 JERR_FILE_WRITE 這個編號被引用過的地方,發現有六個文件使用過這個符號(我使用的是 libjpeg9,其他版本應該也不會影響本文的分析過程)。

  5)JERR_FILE_WRITE 被引用的形式為:

      ERREXIT(cinfo, JERR_FILE_WRITE);

    ERREXIT 是一個宏,轉到這個宏的定義,這個宏同樣的被定義在 jerror.h 中,其定義如下:

 ERREXIT(cinfo,code)  \->err->msg_code =*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))

    可以看出來,ERREXIT 宏做了兩件事:

      a)將編號(本文中討論的問題編號對應 JERR_FILE_WRITE)賦值給 (cinfo)->err->msg_code

      b)調用 (cinfo)->err->error_exit) 回調。

    cinfo 就是 初始化 libjpeg 時指定的 struct jpeg_decompress_struct。

    (cinfo)->err->msg_code 是 libjpeg 處理錯誤的錯誤代碼。

     (cinfo)->err->error_exit 是 libjpeg 在出現錯誤時,用來退出的回調函數。我們的程序就是這樣被退出的。 

4. 解決辦法

  通過分析,知道了程序退出是(cinfo)->err->error_exit 實現的,因此我們可以讓這個回調函數指針指向我們自己的函數。

  並且,因為 libjpeg 會在出錯的時候給 (cinfo)->err->msg_code 一個值,之個值就是 libjpeg 定義的錯誤描述編號,非零的,所以可以在調用 libjpeg 的函數之前將這個值設置為 0,調用完成後在檢查這個時是否為 0,這樣來判斷 libjpeg 的函數調用是否成功。

5. 在 android 下的問題

  遇到這個問題是因為要做一個 android 的播放器,其中解碼使用了 ffmpeg,截圖保存使用 libjpeg。本文上面描述的方法並不能完全奏效。

  在 android 下保存截圖,如果使用的 sd 卡滿,導致保存圖片失敗,並不會回調我們使用  (cinfo)->err->error_exit 指定的函數。每次都會生成一個大小為 0 的文件。

  通過分析,認為這事 android 寫文件時緩存機制的問題:sd  卡滿了,但寫文件是是先寫到緩存的,因此每次寫入文件都會先寫到緩存中,不會返回失敗。並且每次調用 fwrite 返回已經寫入的數據數是正確的,等到關閉文件或刷新緩存的時候,才會出錯。

  為了解決這個問題,在打開文件時,將文件的緩存關閉,這樣,就能使用本文提到的方法來解決問題了。

setbuf(f, NULL);

 

6. 結束語

  下面提供本文源代碼的完整版,代碼中使用的位圖必須是 24 位位圖,且掃描順序是自下而上的。

 

View Code

 

   源代碼下載鏈接:http://files.cnblogs.com/baiynui1983/jpeg_sample.rar

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved