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のアプリの存在を考えれば認められていると考える方が自然だ。
まぁ、やってみるさ。
コメント
コメントを投稿