フィルタ処理された画像を取り出すのにハマる
よーしまずは画像をセピア色にしよう!と思って、チュートリアル的なサイトを探して参考にさせていただいた。
「蜷川実花監修カメラアプリcameranのエンジニアが教える高速フィルターカメラアプリの作り方」のレジュメを公開します
その他いくつかのサイトでもここを参考に、類似の実装を行っているようだし、はじめの一歩なのでさすがに簡単そうに見えた。
さくさくと進めるかと思いきや、imageFromCurrentlyProcessedOutput
セレクタが見つからず、???となってしまった。
そこで、githubのページをきちんと読み直したら解決策を見つけた。
UIImage *inputImage = [UIImage imageNamed:@"Lambeau.jpg"];
GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:inputImage];
GPUImageSepiaFilter *stillImageFilter = [[GPUImageSepiaFilter alloc] init];
[stillImageSource addTarget:stillImageFilter];
[stillImageFilter useNextFrameForImageCapture] //imageFromCurrentlyProcessedOutputを使うならその前にこれを呼び出す
[stillImageSource processImage];
UIImage *currentFilteredVideoFrame = [stillImageFilter imageFromCurrentFramebuffer]; //以前はimageFromCurrentlyProcessedOutput
githubのissuesや、本家サイトを確認してみると、
- フレームワークのメモリ利用量の削減
- メモリ関連のクラッシュ回避
などの観点から変更した模様。
この件、日本語の情報はまだ少ないな・・。
GPUImageView は UIImageViewではない?でハマる
次に、githubのサンプルを活用してみようと、SimpleImageFilterを弄ってみることにした。
サンプルはloadViewでGPUImageViewを初期化しているが、自分はstroyboardでUIImageViewを使ってプレースホルダ画像を活用したいと思っている。
しかし、下記の実装だと実行時エラーが出てしまう。
/***
ここで登場するself.imageViewはstoryboardにて接続したUIImageViewのこと。
実装は、UIViewControllerのviewDidLoad内の処理。
***/
//GUIで設定した画像を取得する
UIImage *inputImage = nil;
inputImage = self.imageView.image;
//画像をGPUImageのフォーマットに変換する
GPUImagePicture *sourcePicture;
sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage smoothlyScaleOutput:YES];
//セピアフィルターを作る
GPUImageSepiaFilter *sepiaFilter = [[GPUImageSepiaFilter alloc] init];
GPUImageView *theImageView = (GPUImageView *)self.imageView; //キャストしてるんだけど・・。
[self.sepiaFilter forceProcessingAtSize:theImageView.sizeInPixels];
//ターゲット設定する
[sourcePicture addTarget:sepiaFilter];
[self.sepiaFilter addTarget:theImageView]
//フィルターを実行
[sourcePicture processImage];
エラーログの一部はこのような感じで、キャストしているんだけどGPUImageVIewのアクセサメソッドが認識されないようだ。ログを見れば[UIImageView sizeInPixels]
とあり、確かにこの文字列だけ見たら通らないな、とは思うのだけど・・。
-[UIImageView sizeInPixels]: unrecognized selector sent to instance ...
直接関係ないが、 http://stackoverflow.com/a/23747248 にライブラリ作者様のコメントがある。
GPUImageView is not a subclass of UIImageView.
今回の件は、サブクラスではないけど一応ダウンキャスト(サブクラスへのキャスト)としてコンパイルできるものの、結局は定義していないメソッドの実行箇所で落ちる、ということだろうか。
そもそもダウンキャスト自体が危険なアプローチになることが多いらしいので注意が必要だ。
カメラアプリの開発を進める中で、もう少し深堀できると良い。