iPhoneアプリから画面のキャプチャー画像を取得する2つの方法
iPhoneでは、ホームボタンと電源ボタンを同時押しするとスクリーンショットがとれる。しかもこのスクリーンショットはPNG形式で保存されるので高画質だ。
ただこの方法の問題は、間違えてスリープさせてしまったり、アプリを終了させてしまったり、スクリーンショットをとるだけなのに相当集中・気合を必要とすることだ。場合によっては間違ってiPhoneを落としてしまう可能性もある。
そこで、アプリ内からもっと気軽に簡単に画面のキャプチャーを取れないか試してみることにした。
アプリのキャプチャーをとるには、少なくとも2つ方法があるとわかった。スタンダードな方法と、ハックハックな方法だ。
スタンダードな方法
例えば、こんな風にする。
この方法ではUIWindowのコンテンツをキャプチャーするのでステータスバーは写らない。場合によってはこの方が都合がいい場合もあるだろう。
しかし、今回の場合の最大の問題は、UIWindowにカメラ入力を表示している場合でも、カメラ入力のレイヤーが無視されて写らないことだ。
なお、UIImageWriteToSavedPhotosAlbum()を使って保存した画像は、ホームボタンと電源ボタンの同時押しによるキャプチャー画像と違い、JPEG画像として「写真」に保存される。クオリティーコントロールもできないようだ。
ただ、見た目にはそれほど劣化しているようには見えず、ImageMagickのidentifyコマンドで書き出されたJPEGのクオリティーを調べてみたところ93と結構高かった。
ハックハックな方法
こうすると、ステータスバーも写るし、カメラ入力も写る。
これだけだと「Implicit declaration of function 'UIGetScreenImage'」の警告が出るので、ヘッダーファイルに次のコードを入れると警告が出なくなる。
ポイントであるUIGetScreenImage()は、ドキュメントに載っていないAPIだ。つまり、これを使えばAppleの審査に通らない可能性がある。
しかしネット上には、最近はAppleがこのAPIの使用を認めたとの情報がいくつもある。
Saving a view as an image. : SkyBlog
と、将来は正式なAPIとして認められるかもしれないとのご指摘も。
iPhone ARは第2章へ突入 >> akalogue
本当のところは実際に審査に出してみないとわからないが、赤松さんがおっしゃるように、Ustreamのアプリの存在を考えれば認められていると考える方が自然だ。
まぁ、やってみるさ。
ただこの方法の問題は、間違えてスリープさせてしまったり、アプリを終了させてしまったり、スクリーンショットをとるだけなのに相当集中・気合を必要とすることだ。場合によっては間違ってiPhoneを落としてしまう可能性もある。
そこで、アプリ内からもっと気軽に簡単に画面のキャプチャーを取れないか試してみることにした。
アプリのキャプチャーをとるには、少なくとも2つ方法があるとわかった。スタンダードな方法と、ハックハックな方法だ。
スタンダードな方法
例えば、こんな風にする。
/**
*
* 画面キャプチャー開始
*
*/
- (IBAction)onTouchUpInsideBtnCapture {
//画面をキャプチャー
NSLog(@"画面キャプチャー開始");
CGRect rect = [[UIScreen mainScreen] bounds];
UIGraphicsBeginImageContext(rect.size); //コンテクスト開始
UIApplication *app = [UIApplication sharedApplication];
//#import をしておかないとrenderInContextで警告が出る
[app.keyWindow.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); //画像を取得してからコンテクスト終了
//画像を「写真」に保存
//JPEGで保存され、クオリーティーはコントロールできないようだ。
//ImageMagickのidentifyによるとQuality=93らしい。
//UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil); //完了通知が必要ない場合
UIImageWriteToSavedPhotosAlbum(img, self, @selector(onCompleteCapture:didFinishSavingWithError:contextInfo:), nil);
}
/**
*
* 画面キャプチャー完了
*
*/
- (void)onCompleteCapture:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void*)contextInfo {
NSLog(@"画面キャプチャー完了");
}
この方法ではUIWindowのコンテンツをキャプチャーするのでステータスバーは写らない。場合によってはこの方が都合がいい場合もあるだろう。
しかし、今回の場合の最大の問題は、UIWindowにカメラ入力を表示している場合でも、カメラ入力のレイヤーが無視されて写らないことだ。
なお、UIImageWriteToSavedPhotosAlbum()を使って保存した画像は、ホームボタンと電源ボタンの同時押しによるキャプチャー画像と違い、JPEG画像として「写真」に保存される。クオリティーコントロールもできないようだ。
ただ、見た目にはそれほど劣化しているようには見えず、ImageMagickのidentifyコマンドで書き出されたJPEGのクオリティーを調べてみたところ93と結構高かった。
ハックハックな方法
こうすると、ステータスバーも写るし、カメラ入力も写る。
/**
*
* 画面キャプチャー開始
*
*/
- (IBAction)onTouchUpInsideBtnCapture {
//画面キャプチャー開始
NSLog(@"画面キャプチャー開始");
//スクリーンに写っているものすべてを画像化
//ドキュメントにはないAPIコール(ひょっとするとREJECTの可能性もあるが、許されているという話も)
CGImageRef imgRef = UIGetScreenImage();
//CGImageRefをUIImageに変換
UIImage *img = [UIImage imageWithCGImage:imgRef];
//キャプチャーしたCGImageRefはUIImageに変換して必要なくなったので解放
CGImageRelease(imgRef);
//画像を「写真」に保存
//JPEGで保存され、クオリーティーはコントロールできないようだ。
//ImageMagickのidentifyによるとQuality=93らしい。
//UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil); //完了通知が必要ない場合
UIImageWriteToSavedPhotosAlbum(img, self, @selector(onCompleteCapture:didFinishSavingWithError:contextInfo:), nil);
}
/**
*
* 画面キャプチャー完了
*
*/
- (void)onCompleteCapture:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void*)contextInfo {
NSLog(@"画面キャプチャー完了");
}
これだけだと「Implicit declaration of function 'UIGetScreenImage'」の警告が出るので、ヘッダーファイルに次のコードを入れると警告が出なくなる。
//「Implicit declaration of function 'UIGetScreenImage'」の警告が出ることへの対処 //頭に「-」がついておらず後ろに「(void)」がついている事に注意。これはタイプミスではない。 CGImageRef UIGetScreenImage(void);
ポイントであるUIGetScreenImage()は、ドキュメントに載っていないAPIだ。つまり、これを使えばAppleの審査に通らない可能性がある。
しかしネット上には、最近はAppleがこのAPIの使用を認めたとの情報がいくつもある。
Saving a view as an image. : SkyBlog
・・・Update: Apple have now allowed the usage of UIGetScreenImage()・・・The announcement hints strongly that Apple will be adding a new public method into future frameworks that will gather a screenshot.・・・
と、将来は正式なAPIとして認められるかもしれないとのご指摘も。
iPhone ARは第2章へ突入 >> akalogue
・・・2009年12月になって、唐突にUstream Live Broadcasterなどのライブ映像系のアプリケーションがApp Storeで公開されるように・・・これらは非公式APIであるUIGetScreenImage()・・・を使っていました・・・デベロッパー・フォーラムではUIGetScreenImage()を使っていいよとのAppleからのメッセージも掲載されちゃいました・・・
本当のところは実際に審査に出してみないとわからないが、赤松さんがおっしゃるように、Ustreamのアプリの存在を考えれば認められていると考える方が自然だ。
まぁ、やってみるさ。
コメント
コメントを投稿