アラのアラアラしい日記

こっそりかいてます

AVAssetImageGeneratorから取得した動画のサムネイル(UIImage)が撮影時とサイズが違ってしまう問題の解決法

こんばんわ!一昨日の晩御飯が思い出せない系エンジニアです。
objective-cを「おぶしー」って呼んでいたらチャラいって言われました。

そんな感じで、今回ハマったのはAVAssetImageGeneratorから動画のサムネイルを取得したあとに、それをUIImageで画像として表示するところで、
なんだか撮影していた時と表示される画像のサイズが違ったのでその解決法を書きます。

私が遭遇した現象としては、以下のような感じです。
f:id:wknar0311:20150531115654p:plain AVFoundation Frameworkを使用しているのですが、この撮影範囲とiOSカメラの撮影範囲が違う為、
画像に変換した時に撮っていた時と違う表示のされ方をします。
見てくださいよこの可哀想なカーネルサンダース。
( というかAVFoundationで撮影している時点で全体の画像を持っているんですね。)

色々調べていたんですがどれも理想通りにいかなかったので、
以下のようにしました。

// サムネイル作成
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[videoFile toURL] options:nil];
AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
gen.appliesPreferredTrackTransform = YES;
CGImageRef image = [gen copyCGImageAtTime:CMTimeMakeWithSeconds(0.0, 600) actualTime:nil error:nil];
UIImage *thumb = [[UIImage alloc] initWithCGImage:image];
CGImageRelease(image);

NSString *attr = [[NSString alloc] initWithFormat:@"okomeView%d", i];

// ここでサムネイルの余計な部分を切り取る
[[self valueForKey:attr] setContentMode:UIViewContentModeScaleAspectFill];
[[self valueForKey:attr] setClipsToBounds:YES];
[[self valueForKey:attr] setImage:thumb];

取得したサムネイル画像からUIViewContentModeを利用して見た目を変えてしまうという方法です。

UIViewContentModeScaleAspectFillで元の縦横比を維持したまま、指定した範囲内で最大に画像を表示します。
そのあと、setClipsToBoundsYESにすることではみ出した部分を非表示にします。
これで撮影した部分のみのサムネイルが表示されます。

ただ、切り取り済みの画像を表示するのと違い、表示毎に大きい画像を持ってきてから見た目を変えたり非表示にしているので
メモリ使用量を考えると大量のサムネイルを表示したい時等は向いてないかもしれないです!

UIViewContentModeの使い方は以下から見れます。
UIView Class Reference

それではちゃんと歯磨きして寝てくださいね!