ユーザ用ツール

サイト用ツール


サイドバー

About

Contents

Materials Link

その他

PR


wiki:opengl:tips:008

008 PNGテクスチャの読み込み

概要

libpng 使ってPNG画像を読み込みOpenGLで扱える形にします。

ソースコード

#include <png.h> 
#include <pnginfo.h> 
 
// データ読込時のコールバック関数 
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; 
} 
wiki/opengl/tips/008.txt · 最終更新: 2014/11/07 03:59 (外部編集)