====== 008 PNGテクスチャの読み込み ====== ===== 概要 ===== [[http://www.libpng.org/pub/png/libpng.html|libpng]] 使ってPNG画像を読み込みOpenGLで扱える形にします。 ==== ソースコード ==== #include #include // データ読込時のコールバック関数 int offset = 0; void ReadEndProcess( png_structp _pPng, png_bytep _buf, png_size_t _size ) { uint8* p = (uint8*)png_get_io_ptr( _pPng ); memcpy( _buf, p+offset, _size ); offset += _size; } bool IsPNG( const uint8* _pData ) { if( png_sig_cmp( _pData, 0, 8 ) != 0 ) { return false; } return true; } // テクスチャの読み込み。 bool Load( const uint8* _pData, GLuint* _textureID, sint32* _width, sint32* _height ) { GLuint textureName; glGenTextures( 1, &textureName ); glBindTexture( GL_TEXTURE_2D, textureName ); // PNGファイルであるか? if( png_sig_cmp( _pData, 0, 8 ) != 0 ) { return false; } png_structp png_ptr; png_infop info_ptr; sint32 depth; sint32 color_type; // 読み込み用メモリを生成 png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); // メモリが生成できなければ終了 if( png_ptr == NULL ) { return false; } // 画像情報用メモリを生成(必須) info_ptr = png_create_info_struct( png_ptr ); if( info_ptr == NULL ) { png_destroy_read_struct( &png_ptr, NULL, NULL ); return false; } // データ読み込み時に呼ばれるコールバック関数を定義する png_set_read_fn( png_ptr, (png_voidp)_pData, ReadEndProcess ); offset = 8; // 内部でエラーが発生したら、ここに飛んでくる if( setjmp( png_jmpbuf( png_ptr ) ) ) { // 確保したメモリーを解放する png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); return false; } // PNGファイルの識別エリア(8バイト)をスキップ png_set_sig_bytes( png_ptr, 8 ); // PNGファイルを読み込む png_read_png( png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL ); // PNG画像情報を取得 *_width = info_ptr->width; *_height = info_ptr->height; color_type = info_ptr->color_type; depth = info_ptr->bit_depth; // 色のタイプからテクスチャの画像情報を設定 GLint gl_type; switch( color_type ) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb( png_ptr ); gl_type = GL_RGB; break; case PNG_COLOR_TYPE_RGB: gl_type = GL_RGB; break; case PNG_COLOR_TYPE_RGBA: gl_type = GL_RGBA; break; default: // 対応していないタイプなので処理を終了 png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); return false; } uint8* outData; // 画像1ライン分のメモリ領域を確保. uint32 row_bytes = png_get_rowbytes( png_ptr, info_ptr ); outData = new uint8[ row_bytes * *_height ]; // 画像情報を行単位で取得できるようにする. png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr); #if 1 for ( sint32 i = 0; i < *_height; i++ ) { // 画像が上下反転するように格納する // (OpenGLのテクスチャーは上下反転して表示されるため) // memcpy( outData+(row_bytes * (*_height-1-i)), row_pointers[i], row_bytes ); // 反転しない。 memcpy( outData+(row_bytes * (i)), row_pointers[i], row_bytes ); } #endif // メモリをすべて解放する png_destroy_read_struct(&png_ptr, &info_ptr, NULL); // テクスチャーデータを割り当てる glTexImage2D( GL_TEXTURE_2D, 0, gl_type, *_width, *_height, 0, gl_type, GL_UNSIGNED_BYTE, outData ); SafeDeleteArray( outData ); *_textureID = textureName; return true; }