SAMPLE
png ファイルを読み込んでテクスチャにする
REFERENCE ファイルダイアログ
REFERENCE 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 は考えなくてもいい。
■ 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 をつかう。
windows icon も変換できる。
REFERENCE リソーススクリプトのかきかた
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