2009-03-29 22 views
19

私はいくつかの画像処理をしており、JPEGとPNG画像の各ピクセル値を個別に読みたいと思います。LinuxのC++でJPEGおよびPNGピクセルを読み取るにはどうすればよいですか?

私の展開のシナリオでは、サードパーティ製のライブラリを使用するのは難しいでしょう(対象のコンピュータではアクセスが制限されています)。しかし、標準のC/C++ライブラリではJPEG/PNG ...

の方法を知っていれば、ではライブラリを使用していないので、そうでない場合は、答えはまだ歓迎です!

答えて

19

ファイル形式を読むための標準ライブラリはC標準にはありません。

しかし、特にLinuxプラットフォーム上のほとんどのプログラムは、画像フォーマットをデコードするために同じライブラリを使用します。

JPEGの場合、それはlibpngのだpngのために、のlibjpegです。

libがすでにインストールされている可能性は、非常にです。 JPEGの場合

http://www.libpng.org

http://www.ijg.org

5

libjpegと呼ばれるライブラリがすでにあり、およびPNGのためのlibpngがあります。良いニュースは、それらがすぐにコンパイルされるため、ターゲットマシンはdllファイルなどを必要としないということです。悪いニュースは、彼らはあなたが読みやすい形式にしたい場合は、代わりにPPMを使用しています。でもtrying to readthe files自分のこととは思わない、

また:(Cであるである。

+6

Cさんがどのように悪い知らせをしていますか? Perl、Python、Java、またはC#のCライブラリよりも、C++でCライブラリを使用するほうがはるかに簡単です。そして、C++のものを使用しようとするよりはずっと簡単です。 –

+0

私はかつてクラス割り当てのためにJavaでJPEGデコーダを書かなければなりませんでした。それは殺人的な仕事でした(そして、Javaはそれをもっと簡単にはしませんでしたが、それを教えてください)。しかし、それにもかかわらず、私はフォーマットとハフマン自身をコーディングするための多くの洞察を与えました。厳密に制限された組み込みシステムをコーディングする場合など、メモリ/スピードの要求が非常に厳しい場合を除いて、あなた自身のようなことをやろうとするのは確かに過度のことです。 –

4

残念ながら、JPEG形式があります圧縮されているので、個々のピクセルを読み取る前に解凍する必要があります。これは簡単な作業です。ライブラリを使用できない場合は、画像を解凍する方法を参照してください。 sourceforgeのソースライブラリ:CImg on sourceforge.

19

これは10年前のソースコード(libjpegを使用)から掘り出した小さなルーチンです:

#include <jpeglib.h> 

int loadJpg(const char* Name) { 
    unsigned char a, r, g, b; 
    int width, height; 
    struct jpeg_decompress_struct cinfo; 
    struct jpeg_error_mgr jerr; 

    FILE * infile;  /* source file */ 
    JSAMPARRAY pJpegBuffer;  /* Output row buffer */ 
    int row_stride;  /* physical row width in output buffer */ 
    if ((infile = fopen(Name, "rb")) == NULL) { 
    fprintf(stderr, "can't open %s\n", Name); 
    return 0; 
    } 
    cinfo.err = jpeg_std_error(&jerr); 
    jpeg_create_decompress(&cinfo); 
    jpeg_stdio_src(&cinfo, infile); 
    (void) jpeg_read_header(&cinfo, TRUE); 
    (void) jpeg_start_decompress(&cinfo); 
    width = cinfo.output_width; 
    height = cinfo.output_height; 

    unsigned char * pDummy = new unsigned char [width*height*4]; 
    unsigned char * pTest = pDummy; 
    if (!pDummy) { 
    printf("NO MEM FOR JPEG CONVERT!\n"); 
    return 0; 
    } 
    row_stride = width * cinfo.output_components; 
    pJpegBuffer = (*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, pJpegBuffer, 1); 
    for (int x = 0; x < width; x++) { 
     a = 0; // alpha value is not supported on jpg 
     r = pJpegBuffer[0][cinfo.output_components * x]; 
     if (cinfo.output_components > 2) { 
     g = pJpegBuffer[0][cinfo.output_components * x + 1]; 
     b = pJpegBuffer[0][cinfo.output_components * x + 2]; 
     } else { 
     g = r; 
     b = r; 
     } 
     *(pDummy++) = b; 
     *(pDummy++) = g; 
     *(pDummy++) = r; 
     *(pDummy++) = a; 
    } 
    } 
    fclose(infile); 
    (void) jpeg_finish_decompress(&cinfo); 
    jpeg_destroy_decompress(&cinfo); 

    BMap = (int*)pTest; 
    Height = height; 
    Width = width; 
    Depth = 32; 
} 
+0

hi wat r libjpeg関連機能を使用するために追加するヘッダファイルはありますか? – suresh

+0

#include

+0

ヘッダーを追加しました。 –

1

私はDevILライブラリで良い経験をしています。これは、広範囲の画像形式をサポートし、OpenGLと非常によく似た関数形式に従います。

許可されていますが、それはライブラリですが、試してみる価値があります。

2

公開されている可能性があるため、SourceforgeでホストされているThe IM Toolkitという別のライブラリを調査します。これはクロスプラットフォームであり、ユーザーから完全に離れたファイル形式を抽象化するため、ほとんどの詳細を心配することなくイメージをロードして処理することができます。 PNGとJPEGの両方をサポートしており、必要に応じて他のインポートフィルタで拡張することができます。

それはまたLuaに結合する良い品質を持って

...だけでなく、画像処理演算子の大規模なコレクションが付属しています。

1

その他の回答には、既にライブラリを使用する必要があると言われているので、ImageMagickをご覧になり、必要な処理を実行できるかどうかを確認してください。これはImageMagickのコア機能とインタフェースするためのさまざまな方法が用意されています。

ホームページ:ImageMagick

2

ニルスが指摘したように、JPEG圧縮および画像操作のためのCまたはC++標準ライブラリのようなものはありません。

サードパーティライブラリを使用できる場合は、GDALにJPEG、PNGなどの他のフォーマット、圧縮、およびメディアをサポートすることをおすすめします。利用可能GDAL API tutorialより完全であり

#include <gdal_priv.h> 
#include <cassert> 
#include <iostream> 
#include <string> 
#include <vector> 

int main() 
{ 
    GDALAllRegister(); // once per application 

    // Assume 3-band image with 8-bit per pixel per channel (24-bit depth) 
    std::string const file("/home/mloskot/test.jpg"); 

    // Open file with image data 
    GDALDataset* ds = static_cast<GDALDataset*>(GDALOpen(file.c_str(), GA_ReadOnly)); 
    assert(0 != ds); 

    // Example 1 - Read multiple bands at once, assume 8-bit depth per band 
    { 
     int const ncols = ds->GetRasterXSize(); 
     int const nrows = ds->GetRasterYSize(); 
     int const nbands = ds->GetRasterCount(); 
     int const nbpp = GDALGetDataTypeSize(GDT_Byte)/8; 
     std::vector<unsigned char> data(ncols * nrows * nbands * nbpp); 

     CPLErr err = ds->RasterIO(GF_Read, 0, 0, ncols, nrows, &data[0], ncols, nrows, GDT_Byte, nbands, 0, 0, 0, 0); 
     assert(CE_None == err); 

     // ... use data 
    } 

    // Example 2 - Read first scanline by scanline of 1 band only, assume 8-bit depth per band 
    { 
     GDALRasterBand* band1 = ds->GetRasterBand(1); 
     assert(0 != band1); 

     int const ncols = band1->GetXSize(); 
     int const nrows = band1->GetYSize(); 
     int const nbpp = GDALGetDataTypeSize(GDT_Byte)/8; 
     std::vector<unsigned char> scanline(ncols * nbpp); 

     for (int i = 0; i < nrows; ++i) 
     { 
      CPLErr err = band1->RasterIO(GF_Read, 0, 0, ncols, 1, &scanline[0], ncols, 1, GDT_Byte, 0, 0); 
      assert(CE_None == err); 

      // ... use scanline 
     } 
    } 

    return 0; 
} 

:ここ

はGDAL C++ APIを使用してJPEGファイルからピクセルデータを読み取る方法を提供する簡単な例です。

1

速度が問題でない場合LodePNGは、PNGの読み込みと保存に非常に単純なアプローチをとることができます。

また、関数内の自己完結型のpngローダーである同じ作者のpicoPNGを使用することもできます。

関連する問題