2009-02-03 47 views
2

我在Ubuntu Intrepid上,我正在使用jpeglib62 6b-14。我正在研究一些代碼,當我嘗試運行它時,它只會在頂部顯示出一些亂碼輸出的黑屏。經過幾個小時的調試,我把它歸結爲JPEG基礎,所以我拿出了示例代碼,在它周圍寫了一段代碼,輸出結果完全一樣。Jpeglib代碼給出亂碼輸出,甚至捆綁的示例代碼?

我確信jpeglib被用在這個系統的很多地方,它只是版本庫中的版本,所以我很猶豫地說這是jpeglib或Ubuntu包裝中的錯誤。

我把下面的例子代碼(大多數評論剝離)。 輸入的JPEG文件是一個帶有3個通道的未壓縮的640x480文件,因此它應該是921600字節(而且是)。輸出圖像是JFIF和大約9000字節。

如果你能幫助我甚至提示,我會非常感激。

謝謝!

#include <stdio.h> 
#include <stdlib.h> 
#include "jpeglib.h" 
#include <setjmp.h> 

int main() 
{ 
    // read data 
    FILE *input = fopen("input.jpg", "rb"); 
    JSAMPLE *image_buffer = (JSAMPLE*) malloc(sizeof(JSAMPLE) * 640 * 480 * 3); 
    if(input == NULL or image_buffer == NULL) 
    exit(1); 
    fread(image_buffer, 640 * 3, 480, input); 

    // initialise jpeg library 
    struct jpeg_compress_struct cinfo; 
    struct jpeg_error_mgr jerr; 
    cinfo.err = jpeg_std_error(&jerr); 
    jpeg_create_compress(&cinfo); 

    // write to foo.jpg 
    FILE *outfile = fopen("foo.jpg", "wb"); 
    if (outfile == NULL) 
    exit(1); 
    jpeg_stdio_dest(&cinfo, outfile); 

    // setup library 
    cinfo.image_width = 640; 
    cinfo.image_height = 480; 
    cinfo.input_components = 3; // 3 components (R, G, B) 
    cinfo.in_color_space = JCS_RGB; // RGB 
    jpeg_set_defaults(&cinfo); // set defaults 

    // start compressing 
    int row_stride = 640 * 3; // number of characters in a row 
    JSAMPROW row_pointer[1]; // pointer to the current row data 
    jpeg_start_compress(&cinfo, TRUE); // start compressing to jpeg 

    while (cinfo.next_scanline < cinfo.image_height) { 
    row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; 
    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 
    } 

    jpeg_finish_compress(&cinfo); 

    // clean up 
    fclose(outfile); 
    jpeg_destroy_compress(&cinfo); 
} 

回答

2

您正在閱讀的JPEG文件到內存中(不解壓它),並寫出該緩衝區就好像它是未壓縮的,這就是爲什麼你得到的垃圾。您需要先解壓縮圖像,然後才能將其送入JPEG壓縮器。

換句話說,JPEG壓縮器假定其輸入是原始像素。

你可以使用ImageMagick你輸入的圖像轉換成原始RGB:

convert input.jpg rgb:input.raw 

它應該是大小正好921600字節。

編輯:當你的國家,你的問題是誤導你的輸入JPEG文件在解壓縮。無論如何,我編譯了你的代碼,它工作正常,正確壓縮圖像。如果您可以上傳您用作輸入的文件,則可能需要進一步調試。如果沒有,我建議你使用從使用ImageMagick已知JPEG創建的圖像測試程序:

convert some_image_that_is_really_a_jpg.jpg -resize 640x480! rgb:input.jpg 
+0

感謝您的回答,但是: 「輸入的JPEG文件是一個包含3個通道的未壓縮的640x480文件,因此它應該是921600字節(而且是)。」 它是未壓縮的,它*的大小是921600字節! – sgielen 2009-02-04 08:55:21

+0

什麼...?當我在原始圖像上運行壓縮,然後對結果運行jpeginfo(也是621600字節),我得到「不是JPEG文件:以0x80 0x78開頭」,然後當我運行該程序時,我得到一個有效的結果圖像!這裏發生了什麼?! :S – sgielen 2009-02-04 16:36:05

+0

(呃,921600字節,對不起) – sgielen 2009-02-04 16:36:36

1

您正在閱讀的輸入文件到memmory壓縮,然後你扶正文件之前重新壓縮它。在再次壓縮之前,您需要解壓縮image_buffer。或者替代地讀取JPEG文件而不是讀取.raw圖像

1

您的意思是「輸入的JPEG文件是未壓縮的」? Jpegs全部壓縮。

在你的代碼中,似乎在循環中給了一行像素到libjpeg並要求它壓縮它。它不這樣工作。 libjpeg必須至少有8行才能開始壓縮(有時甚至更多,這取決於參數)。所以最好是讓libjpeg控制輸入緩衝區,不要爲它做任何工作。

我建議你閱讀cjpeg.c如何完成它的工作。我認爲最簡單的方法是將數據放入由libjpeg(例如BMP)知道的原始類型中,並使用libjpeg將BMP圖像讀入其內部表示並從那裏壓縮。