2009年

[iPhone] UIImage #imageWithContentsOfData: などは描画が激遅 このエントリーを含むはてなブックマーク

iPhone/iPod touch Add comments

現在制作中の iPhone アプリで描画が遅くて困っていました。その原因はまさにこのエントリにある通りのことでした。

UIImage#imageNamed:は読み込みも描画もUIImage#imageWithContentsOfFile:やそれ以外のメソッドより5〜6倍速い – 24/7 twenty-four seven

imageNamed:は圧倒的にロードが速いし、何故か描画も速い。


私の感じでは、UIImage#imageNamed: が早いというよりも、UIImage#imageWithContentsOfFile: や UIImage#imageWithData: などが遅い感じです。UIImage#imageNamed: 以外で作成した UIImage の描画も UIImage#imageWithContentsOfFile: とかよりも劇的に早いからです。(UIImage#imageNamed: も早いが、imageWithContentsOfFile: とか以外で作成したのも早いから)
なんかややこしくなってきたので実際にやっていること見て下さい。

UIImagePicker から取得した UIImage をアプリが終了するときに NSData として NSUserDefaults で保存していました。

NSData *data = UIImagePNGRepresentation(image);
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"image_data"];

で、次の起動時に UIImage#imageWithData: を使用して UIImage に戻します。

NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:@"image_data"];
UIImage* image = [UIImage imageWithData:data];

しかし、この UIImage を描画すると、UIImagePicker から取得した UIImage を描画するよりも数段遅く、処理落ちしてしまいました。それほど処理速度を要求しなければ問題にならないと思いますが、今回はかなり重い処理+スピードを要求しているため全体の動きがカクカクしてしまいました。

そこで、下記のようにすることにより回避しました。

NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:@"image_data"];
UIImage* image = [UIImage imageWithData:data];

CGImageRef imageRef = [image CGImage];
UIGraphicsBeginImageContext(CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)));
[image drawAtPoint:CGPointMake(0,0)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

NSData から UIImage#imageWithData で UIImage にして、さらに UIImage に書き出し描画するようにしました。これで速度低下は見られずに動作するようになりました。

なんか UIImage から UIImage を作り直していて無駄なようなことをしている気がします。何か他に良い方法があるのでしょうか?

途中で試しに、NSUserDefaults に保存しないで、DOCUMENT フォルダに PNG 画像として保存して、

NSData *data = UIImagePNGRepresentation(image);
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"ui_image_data"];
NSString *filePath = [NSString stringWithFormat:@"%@/hoge.png" ,[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]];
[data writeToFile:filePath atomically:YES];

次の起動時に保存した PNG 画像を読み込んで UIImage#imageWithContentOfFile: で UIImage に戻してもやっぱり遅かったです。

NSString *filePath = [NSString stringWithFormat:@"%@/hoge.png" ,[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]];
UIImage* image = [UIImage imageWithContentsOfFile:filePath];

関連する投稿

3 Responses to “[iPhone] UIImage #imageWithContentsOfData: などは描画が激遅”

  1. takuma104 Says:

    どうも今年のTechTalkで、

    http://www.travisdunn.com/iphone-tech-talk-world-tour-2009-hamburg

    > UIImageNamed (immediate decompression, cached by OS, purgeable by OS) vs.
    > ImageWithContentsOfFile (decompression on demand, not cached, purgeable by OS)

    という差があって、imageWithContentsOfFile とかだと表示時にデコードされるようです。なので、もう1つUIImageを作ってそこに強制的にデコードしてしまうという手が有効なんですね。コード参考にさせていただいて、UIImageのカテゴリでの拡張で書いてみました。

    http://gist.github.com/259357

  2. matsuura Says:

    iPhone Tech Talks は私も参加しました。imageNamed:とimageWithContentsOfFileの違いは聞きました。あれを聞いてやっとこのなぞが解けました。

    github の方、参考にさせてもらいます。こうしておけば、色々使いやすいですよね。さすがです!

  3. 画像処理に使えるUIImageのTips10個 Says:

    [...] Sun Limited Mt. UIImage#ImageWithContentsOfData: などは描画が激遅 [...]

Leave a Reply

Additional comments powered by BackType

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS ログイン