讀取jpeg圖像數據

jpeg是一個國際圖像壓縮標準,圖像的後綴一般爲jpeg或者jpg。這種圖片格式非常常見,還是有必要知道怎樣將數據讀取出來的。

在我做的zMatrix庫裏,之前一直使用openCV的函數imread()讀取圖像,不是很方便,查過很多資料後發現,如果自己從零寫一個讀取jpeg的程序非常麻煩(可能水平不夠吧,可以查一下都是需要什麼算法),需要用到一些比較複雜的壓縮算法,又因爲讀取圖像不是重點,所以可以使用開源的庫達到同樣的目的,以後有空了可以自己實現。

使用的庫是libjpeg,官網鏈接:http://libjpeg.sourceforge.net/,下載鏈接:http://www.ijg.org/files/,我使用的是9b這個版本。

接下來說一下在windows平臺怎樣使用這個庫。


一、 編譯

1、下載並解壓,放在一個好找的目錄就行:

這裏寫圖片描述

2、進入jpeg-9b,找到jconfig.cv,複製並改名爲jconfig.h,否則會產生無法生成jconfig的警告

這裏寫圖片描述

3、找到makefile.vc這個文件,打開(隨便一個文本編輯器)找到這一行

這裏寫圖片描述
把路徑改爲win32.mk在你電腦上的路徑,每個人的可能不太一樣,路徑差別可能不是很大,我的是C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include\win32.mak,改爲
這裏寫圖片描述

4、準備編譯,我用的是VS2015命令提示符,不要選ARM的

這裏寫圖片描述

5、進入jpeg-9b的目錄,輸入編譯命令開始編譯

這裏寫圖片描述
命令:nmake -f makefile.vc

6、編譯後在目錄下找到庫libjpeg.lib就編譯成功了。


二、使用

具體的使用在目錄下的example.c中有,註釋非常細,看了基本就會用了。這裏我簡單說說用法。

1、使用配置

有兩種方法:
第一種:添加libjpeg的頭文件的路徑和lib的路徑到VS的工程中,項目屬性頁
這裏寫圖片描述,然後在
這裏寫圖片描述
中添加libjpeg.lib
這裏寫圖片描述
第二種:把用到的頭文件和libjpeg.lib拷到你的工程中,只在工程裏做第一種的第三步添加libjpeg.lib就行了。

2、使用

程序裏包含頭文件#include <jpeglib.h>就行了。
大部分照搬,細節可以看裏面的英語註釋,主要的幾個地方修改下就行了,看下面的漢語註釋:

// 這些和錯誤處理有關,不用管
struct my_error_mgr {
    struct jpeg_error_mgr pub;  /* "public" fields */

    jmp_buf setjmp_buffer;  /* for return to caller */
};

typedef struct my_error_mgr * my_error_ptr;

METHODDEF(void) my_error_exit(j_common_ptr cinfo)
{
    my_error_ptr myerr = (my_error_ptr)cinfo->err;
    (*cinfo->err->output_message) (cinfo);
    longjmp(myerr->setjmp_buffer, 1);
}

// 讀取圖像的函數
// 我添加了一個參數,是我庫裏的zMatrix類對象,用於保存讀取的圖片數據
GLOBAL(int) read_JPEG_file(char * filename, z::Matrix8u & img)
{
    struct jpeg_decompress_struct cinfo;
    struct my_error_mgr jerr;
    FILE * infile;      
    JSAMPARRAY buffer;      
    int row_stride; 

    if ((infile = fopen(filename, "rb")) == NULL) {
        fprintf(stderr, "can't open %s\n", filename);
        return 0;
    }
    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;
    if (setjmp(jerr.setjmp_buffer)) {
        jpeg_destroy_decompress(&cinfo);
        fclose(infile);
        return 0;
    }
    jpeg_create_decompress(&cinfo);

    jpeg_stdio_src(&cinfo, infile);

    // 這個函數獲取了讀取圖片的信息,包括圖片的高和寬
    (void)jpeg_read_header(&cinfo, TRUE);
    // 在這裏添加你自己的代碼,獲取或用戶到圖像信息
    img.create(cinfo.image_height, cinfo.image_width, 3);

    (void)jpeg_start_decompress(&cinfo);

    row_stride = cinfo.output_width * cinfo.output_components;
    buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);

    while (cinfo.output_scanline < cinfo.output_height) {
        // 一行一行的讀取
        (void)jpeg_read_scanlines(&cinfo, buffer, 1);

        // 在這裏添加代碼獲取到圖片的像素數據
        // buffer保存了讀取的當前行的數據,保存順序是RGB
        // output_scanline是已經讀取過的行數
        for (int i = 0; i < img.cols; ++i) {
            img[cinfo.output_scanline - 1][i * 3 + 2] = buffer[0][i * 3 + 0];
            img[cinfo.output_scanline - 1][i * 3 + 1] = buffer[0][i * 3 + 1];
            img[cinfo.output_scanline - 1][i * 3 + 0] = buffer[0][i * 3 + 2];
        }
    }

    (void)jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    fclose(infile);
    return 1;
}

代碼:https://github.com/ffiirree/zMatrix/blob/master/zMatrix/zgui/zgui.cpp

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章