画像ファイルから読み込む

SAMPLE https://www.dropbox.com/s/cag7oajy64lt13z/texture_png.exe( png ファイルを読み込んでテクスチャにする ) __LINK__(ファイルダイアログ) __LINK__(nmake)


raw

.raw 形式のファイルを読む raw 形式とはヘッダ情報がないデータだけのファイル
void *readRawTexture( const char *path, int w, int h, int nrElement ) { FILE *fp = fopen( path, "rb" ); // 画像サイズ int sz = w * h * nrElement; // バッファ確保 char *buf = new char [sz]; // ヘッダ(余計な情報)がないため fread() のみで読める fread( buf, sz, 1, fp ); fclose( fp ); return buf; }



ppm

raw 形式と同様に ppm というシンプルなフォーマットも利用できる。 フォーマットは以下のとおり
ファイル形式識別記号 横ピクセル数 縦ピクセル数 最大輝度 画像データ(RGB順,左から右,上から下へ走査した順
POINT ヘッダ部分の改行コードは \n である必要がある。 そのため、必ずバイナリモードでオープンすること。
P6 1024 1024 255 ..........
ppm 形式として 24bit RGB で保存する。 保存した画像は gimp などで開くことができる。
FILE *fp = fopen( "test.ppm", "wb" ); int w = 256, h = 256; int nrElement = 3; // 画像サイズ int sz = w * h * nrElement; // ヘッダ fprintf( fp, "P6\n%d %d\n255\n", w, h ); // バッファ確保 char *buf = new char [sz]; // 画像データ memset( buf, 0, sz ); fwrite( buf, sz, 1, fp ); fclose( fp );



bmp

ウィンドウズの標準画像フォーマットなので、ペイントでもつくれる。 フォーマットは先頭にヘッダがあり、その後にピクセルデータ列がある。
------------------- ヘッダ INFOヘッダ ------------------- ピクセルデータ -------------------
ピクセルデータ列は 青、緑, 赤 の順番。 左下から右上の順番にピクセルデータが格納されている。 ( ファイルの末尾は右上のピクセルデータ ) バイナリのテキストエディタで開くとわかる。 OpenGL のテクスチャの順番と同じため、 glTexImage2D() にそのまま渡すことができる。 WARNING png などは順番が異なるため 上下反転などの処理が必要になる。
[B][G][R][B][G][R] ... --------------> エンド | | | | | | | | | | | | スタート ----------->
アルファがある時( 32bit )は BGRA の順番になる。
[B][G][R][A][B][G][R][A] ...
WARNING 横のバイト数は 4バイトアラインメントされている必要がある。 4 で割り切れない時は, padding を考慮して読み書きする必要がある。 次の場合は 4 の倍数になるので padding は考えなくてもいい。
[.] 横のサイズが 4 の倍数 ( 100 pixel とか ) [.] ピクセルあたりのサイズが 4byte( 32bit )



png

画像サイズを小さくしたい場合は png 形式を使う。 可逆圧縮なので、画像も劣化しない。 次の順番で画素データがつまっている。 先頭が左上で 最後が右下
------------------- START ---------> / / / / / / ---------> END -------------------
ライブラリ libpng と zlib に依存するためネットから取得する。
wget http://jaist.dl.sourceforge.net/project/libpng/libpng15/1.5.10/lpng1510.zip wget http://jaist.dl.sourceforge.net/project/libpng/zlib/1.2.7/zlib127.zip
解凍する。
unzip lpng1510.zip unzip zlib127.zip
ビルドする時の makefile の記述にあわせてディレクトリ名を変更する。
mv lpng1510 png mv zlib-1.2.7 zlib
たとえば次のディレクトリの状態になる
d:/png /scripts d:/zlib /win32
VisualStudio 2008 のコマンドプロンプトを起動して namke を使ってビルドすれば完了。
cd zlib nmake -f win32/Makefile.msc cd png nmake -f scripts/makefile.vcwin32
とりえあえず RGB 8bit を読む簡単なサンプル
# include "png/png.h" # include "zlib/zlib.h" # include "zlib/zconf.h" # pragma comment(lib,"png/libpng.lib") # pragma comment(lib,"zlib/zlib.lib") // PNG構造体の取得 png_structp pPtr = NULL; pPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); // PNG情報構造体の取得 png_infop info_ptr = NULL; info_ptr = png_create_info_struct(pPtr); png_bytep pData = 0; //PNGからピクセルデータを受け取るバッファ png_bytepp row_pointers = 0; //PNGから受け取った画像行の先頭ポインタ // fread を利用したデフォルトの読み方にまかせる。 png_init_io( pPtr, fp ); // 情報ヘッダの読み込み png_read_info( pPtr, info_ptr ); png_uint_32 W, H; // 横, 縦ピクセル数 int bit_depth; //ビット深度 int color_type; //PNG画像の形式 png_get_IHDR(pPtr,info_ptr,&W,&H,&bit_depth,&color_type,NULL,NULL,NULL); //すべての設定を登録 png_read_update_info( pPtr, info_ptr ); //イメージを格納するメモリーを割り当てる為の情報を取得 png_size_t rowbytes = png_get_rowbytes(pPtr,info_ptr);//行データのバイト数 int channels = (int)png_get_channels(pPtr, info_ptr); //チャンネル数 // 画像データをうけとるバッファ pData = new BYTE[ rowbytes * H ]; row_pointers = new png_bytep[H]; // 行配列にフラット領域のそれぞれの位置を設定します for (UINT i=0;i<H;i++) { row_pointers[i] = pData + i*rowbytes; } // イメージを読む png_read_image( pPtr, row_pointers ); // 後始末 delete[]row_pointers; png_read_end(pPtr,NULL); printf( "img W %d H %d channels %d rowbytes %d\n", W, H, channels, rowbytes ); // raw データとして出力して確認 { FILE *fp = fopen( "d:/test_png_out.raw", "wb" ); fwrite( pData, H*rowbytes, 1, fp ); fclose(fp); }
読み込み方法をカスタマイズするには png_set_read_fn() にコールバックとして渡す。 例えば、アーカイブ, リソースなどのメモリ上に読み込み済みの png ファイルから png イメージを取得するには次のようにする。
struct ReadContext { // 読み込み元のデータの場所 const char *ptr; // 現在の位置 int i; ReadContext( const char *p, int _i) : ptr((char *)p), i(_i) {} };
png_init_io() の代わりにコールバックを指定する。
void readPng( char *pSrc ) { # if 0 png_init_io( pPtr, fp ); # else ReadContext ctx( pSrc, 0 ); png_set_read_fn( pPtr, &ctx, pngReadProc ); # endif }
コールバックされるので好きなように実装する。 ライブラリが指定する data という場所に length byte を読み込んであげる。
void pngReadProc( png_structp png, png_bytep data, png_size_t length ) { // png 構造体から png_set_read_fn() で渡したポインタを取得する。 ReadContext *p = (ReadContext *)png_get_io_ptr(png); // png file を読みこみ済みなので memcpy をする。 memcpy // 書き込み先はシステムからもらう data, // 読み込み元はこちらの指定 p->ptr + p->i, length ); p->i += length; }
先にpngファイルを読んでから、読み込み処理をする。
FILE *fp = fopen("d:/test.png","rb"); char *pSrc = new char[ filesz ]; fread( pSrc, filesz, 1, fp ); fclose( fp ); readPng( pSrc );



nconvert

nconvert を利用すると、任意の形式に変換できる。
nconvert -out bmp test.ppm nconvert -out png test.ppm nconvert -out jpg test.ppm nconvert -out tga test.jpg
raw 形式には変換できないらしい。
nconvert -out raw test.ppm
一覧をみるには help をつかう。
nconvert -help
windows icon も変換できる。 __LINK__(リソーススクリプトのかきかた)
nconvert -out ico test.ico
上書きをする
nconvert -overwrite -out ico test.ico
出力ファイル名を指定する
nconvert -out png -o d:/out.bmp d:/src.cmp
サイズを変更する
nconvert -out bmp -resize 64px 64px d:/src.bmp
比率を保持する
nconvert -out png -ratio -resize 1000px 0px d:/test.bmp
ログをOFFにする
nconvert -quiet -out png d:/src.bmp