強火で進め

このブログではプログラム関連の記事を中心に書いてます。

iPhoneのOpenGL ESのテクスチャ読み込み処理を修正した



現在、iPhoneOpenGL ESでテクスチャ使用時の読み込みの関数はAppleのサンプルを一部抜き出して使っています。

元々はクラスになっていたものから一部のメソッドを抽出したものを使っているためイマイチ使い勝手が悪いので今回リニューアルを計画しました。

BMPファイルだけ対応なら昔作った事もあるし、シンプルな構造なので自前で1から作っても良いのですがiPhoneはなにやらPNGファイルに最適化してあるらしく、なるべくPNGファイルを使う様にした方が良いとのことを聞いたので今回はPNGも読みたいなと思っています。

さすがにPNGファイル読み込みまで自前で作るのは時間がかかりすぎるので以下の条件のあてはまるライブラリは無いかなぁと調査してみました。

  • 自由にいじってOK
  • 構造がシンプル(あまりたくさんのファイルをインクルードしていない)
  • PNGファイルが読み込める

色々と調査した結果、こちらのライブラリがマッチしました。

lonesock.net: SOIL
http://lonesock.net/soil.html

読み書き可能なファイルは以下の様にさまざま有り、しかもライセンスは Public Domain です。

読み込み

書き込み

そこで早速、実際に使ってみました。

「Simple OpenGL Image Library」というライブラリ名から少し、気にはなっていたんですがOpenGLに最適化してあるみたいで内部でジャンジャンOpenGLのコマンド呼んでいたりしてました。

ちょっとOpenGLにべったりすぎたので他の用途や環境でも動作できる様にちょっと加工することにしました。
加工方法としては以下の様にしました。これでは途中に画像加工を入れたり、他の用途でも使いやすくできます。

  • ファイルの読み込みは「ファイル→メモリ」とする
  • ファイルの書き込みは「メモリ→ファイル」とする

そこでいろいろとプログラムを追って行くとなにやらこのライブラリも別のライブラリを利用されている様でした。

こちらのサイトの

the Nothing itself nothings
http://www.nothings.org/

こちらのファイルを組み込まれているようです。

public domain JPEG decompression, public domain PNG decompression, public domain ZLIB decompression
http://www.nothings.org/stb_image.c

こっちのファイルはまさに自分が希望していた状態のライブラリでした。
元ファイルはヘッダファイルが定義されてなかった(ヘッダ定義も.cファイル内に記載だった)ので Public Domain だし、自分でこの様に分割してみました。

  • stb_image_custom.h
  • stb_image_custom.c

このファイルを使うとこんな感じで画像の読み書きができます。

#include <stdio.h>
#include <stdlib.h>
#include "stb_image_custom.h"

int main (int argc, const char * argv[]) {
	const int IMAGE_WIDTH	= 128;
	const int IMAGE_HEIGHT	= 128;
	const int PIXEL_SIZE	= 3;	// ピクセルサイズを BYTE で指定
	
	// グラデーションデータを保存する配列
	unsigned char grad[IMAGE_WIDTH*IMAGE_HEIGHT*PIXEL_SIZE];
	// 読み込んだ画像ファイルのデータを格納
	unsigned char *pImg = NULL;
	unsigned char gray;
	int x, y;
	int width, height, comp;
	
	//----------------------------------------
	// グラデーションの画像データをファイルに出力する
	//----------------------------------------
	for (y=0; y<IMAGE_HEIGHT; y++) {
		for (x=0; x<IMAGE_WIDTH; x++) {
			gray = (unsigned char)((x/(IMAGE_WIDTH-1.0)) * 255.0);
			grad[(y*IMAGE_WIDTH+x)*PIXEL_SIZE] = gray;
			grad[(y*IMAGE_WIDTH+x)*PIXEL_SIZE+1] = gray;
			grad[(y*IMAGE_WIDTH+x)*PIXEL_SIZE+2] = gray;
		}
	}
	// BMPファイルとTGAファイルで保存
	stbi_write_bmp("test.bmp", IMAGE_WIDTH, IMAGE_HEIGHT, 3, grad);
	stbi_write_tga("test.tga", IMAGE_WIDTH, IMAGE_HEIGHT, 3, grad);
	
	//--------------------------------
	// ファイルを読み込み、Redの値のみ残す
	//--------------------------------
	pImg = stbi_load("sample.png", &width, &height, &comp, 3);
	if (!pImg) {
		printf("sample.png read error.\n");
		return -1;
	}
	printf("image info : %dx%d %d\n", width, height, comp);
	for (y=0; y<height; y++) {
		for (x=0; x<width; x++) {
			// RGBのうちRのみ残し、GとBの値は0にする
			*(pImg+(y*width+x)*comp+1) = 0;
			*(pImg+(y*width+x)*comp+2) = 0;
		}
	}
	stbi_write_bmp("sample_red.bmp", width, height, comp, pImg);
	
	// メモリは malloc() で確保されているので free() で解放する
	if (pImg) free(pImg);

    return 0;
}

ソースコードこちら
※画像読み込み用のサンプルとして以下のパスにPSDファイルを置いています。 Releaseビルドするときはファイルをコピーするなど適宜対応して下さい。

build/Debug/sample.png

(2008/12/28 追記)
結局、このライブラリを使用した場合はファイルパスに日本語が含まれている場合、エラーとなる事が判明したので使用しませんでした。通常問題無い様に思ったのですがiPhoneアプリ名を日本語にして、そのResourceフォルダにテクスチャファイルを入れていた場合に問題になりました。