今回は、画像ファイルの話です。画像ファイルは、Modelオブジェクトのドキュメントからは分離して別に保存します。登録一覧(UITableView)に画像を表示するためには、画像ファイルから小サイズ画像(UIImage)を作る必要もあります。
iPhoneアプリケーションで画像を取り扱う場合には、Quartz2DフレームワークのCGImageRefやUIKitフレームワークのUIImageクラスを利用します。片方からもう片方への変換は簡単です。UIImageからCGImageRefを得るには、UIImageのCGImageプロパティを参照します。
UIImage *uiimage;
CGImageRef cgimage;
cgimage=uiimage.CGImage // プロパティを参照する
逆に、CGImageRefからUIImageを得るには、UIImageクラスのimageWithCGImage:メソッドを利用します。
uiimage=[UIImage imageWithCGImage:cgimage]; // メソッドを利用する
UIImageクラスには色々と便利なメソッドが用意されていますが、Quartz2Dの強力な機能を利用したいケースも出てきます。そうした場合には、上記に示したオブジェクトの変換が必要ですので注意してください。
さて、次は画像ファイルの読み込みです。XcodeプロジェクトのResourcesグループに登録した画像やサウンドファイル(内部利用)は、各アプリケーションパッケージ内に保存されています。そこに保存されている画像ファイル(ボタンなどのユーザインターフェースなどに使う)については、UIImageクラスのImageNamed:メソッドを利用することで簡単に読み込むことが可能です。以下は、与えたフラグの内容により異なる画像(PNGファイル)を読み込むサンプルルーチンです。
UIImage *getLockImag (BOOL flag )
{
UIImage *image;
NSString *str;
if( flag&LOK_FLAG ) // ロックフラグON/OFF
str=@"Lock.png"; // 画像ファイル名
else
str=@"Unlock.png";
image=[UIImage imageNamed:str]; // 画像(UIImage)を得る
return image;
}
imageNamed:メソッドで読み込まれた画像はシステムでキャッシュされるため、再描画される時には高速に処理されます。つまり、Cocoaのルールとは異なり、このメソッドで得られたUIImageオブジェクトはAutoReleaseされません。このメソッドを使うと画像は例外なくキャッシュに入ってしまいますので、大容量の画像ファイルを読み込むことは厳禁です。間違いなくアプリケーションの使用可能メモリを圧迫します。
以下は、iPhone OSで描画できる画像フォーマットです。ただし、iPhone OSの場合は、描画システムがPNG形式の画像に最適化されているので、頻繁に描画するUIImageには、そのソースとしてPNG形式の画像を使うことが推薦されています。
・PortableNetworkGraphic(PNG) .png
・TaggedImageFileFormat(TIFF) .tiff, .tif
・JointPhotographicExpertsGroup(JPEG) .jpeg, .jpg
・GraphicInterchangeFormat(GIF) .gif
・WindowsBitmapFormat(DIB) .bmp, .BMPf
・Windowsアイコン形式 .ico
・Windowsカーソル .cur
・XWindowビットマップ .xbm
続いて、アプリケーションのDocumentsフォルダに保存されている画像ファイルの読み込みです。アプリケーション内部の作業で入手した(例えばカメラ撮影した画像など)については、もし継続して使うなら、そのままDocumentsフォルダに保存しておくことになります。以下は、拡張子を外したファイル名を与えることで、UIImageをJPEG画像ファイルとして保存するメソッドの一例です。
- (BOOL)saveJPEGImage:(UIImage *)image name: (NSString *)name
{
NSString *name,*path;
BOOL ret=NO;
NSData *data;
if( data=UIImageJPEGRepresentation( image,0.5 ) ) // 圧縮率設定しデータ作成
{
name=[name stringByAppendingString:@".jpg"];
path=getDocumentPath( name ); // 保存ファイルのパスを得る
ret=[[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil];
} // 指定パスにファイルを作成する
return ret;
}
ここで、画像ファイルのパス(保存場所)を得るためにgetDocumentPath()というルーチンを利用していますが、これはDocumentsフォルダ経由のファイルパスを得るための自作ルーチンです。リソースとして保存されている画像ファイルのパスについては、以前作成したsysBeep()ルーチン同様に、NSBundleクラスのpathForResource:メソッドを使えば簡単に得ることができます。
path=[[NSBundle mainBundle] pathForResource:name ofType:@"jpg"];
しかし、アプリケーションのDocumentsフォルダのパスを得るには、以下の様に少し複雑な処理が必要となります。次期バージョンのiPhone OSでは、CarbonのFindFolder()ルーチンのような便利なメソッドを用意してもらいたところですね。
NSString *getDocumentPath( NSString *name )
{
NSString *path=nil;
NSArray *paths;
NSString *dir;
paths=NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,NSUserDomainMask,YES );
// ドキュメントディレクトリーを含むリスト
if( [paths count] > 0 ) // 得られた項目が配列(NSArray)に格納される
{
dir=[paths objectAtIndex:0]; // ドキュメントディレクトリのパス
path=[dir stringByAppendingPathComponent:name];
// 画像ファイルのパスを得る
}
return path;
}
次は、拡張子を外したJPEGファイルの名前を与えることで、Documentsフォルダに保存されている画像ファイルを読み込むメソッドの一例です。
- (UIImage *)loadJPEGImage:(NSString *)name
{
NSString *str,*path;
UIImage *image;
str=[name stringByAppendingString:@".jpg"]; // 拡張子を追加する
path=getDocumentPath( str ); // 保存ファイルのパスを得る
image=[[UIImage alloc] initWithContentsOfFile:path]; // UIImageの読み込み
return image;
}
次回は、こうしてファイルから読み込んだ画像の矩形サイズを変更する処理を考えてみます。 大きなオリジナルサイズの画像をメモリーに常駐させておいては、iPhoneのメモリーがいくらあっても足りません。サムネイルサイズに小さくして活用します。