[iOS開発TIPS] UIViewを劣化なしPNG形式で画像化する方法

2011/09/26
CATEGORY : iPhone app , objective-c
このエントリーをはてなブックマークに追加


みなさまどうもです。シブタニエイジです。

前回のエントリーで紹介しました「iOkonomiyaki」をアップデートしたこともあり、私のobjective-cのスキルがどっか〜〜んと上がりまして。

なので、特に「!!」ってなったテクを、自分忘備録も含めたTIPSとして紹介していきます。

というわけで今回は、UIViewをRetinaサイズでさらに劣化なしPNG形式で取得する方法をご紹介します。

 

とりあえず今までの方法

まずは、iOkonomiyaki ver1.0で採用してた以下の方法。

- (IBAction)saveAction:(id)sender {
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    //保存サイズを指定
    CGSize  size = { 480, 320 };
    UIGraphicsBeginImageContext(size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor blackColor] set];
    CGContextFillRect(ctx, screenRect);
    // 保存するビューを指定
    [self.view.layer renderInContext:ctx];
    // 指定したビューの画像を取得する
    UIImage *screenImage = UIGraphicsGetImageFromCurrentImageContext();
    // 取得した画像をカメラロールに保存する
    UIImageWriteToSavedPhotosAlbum(screenImage, nil, nil, nil);
    UIGraphicsEndImageContext();
}

あ、ちなみに画面は横向きです。なので4行目のところで横位置でサイズ指定してます。縦画面の人は{ 320, 480 }にしてくださいね。

とまぁ、これが一般的に使われてるっぽいのですが、これだとRetinaディスプレイに対応できてません。320x480で、しかもJPEGの70〜80くらいの画質。

で、今回バージョンアップするに当たり、当然各ステージ(お店)の背景を細部まで作り込んでるのでもったいないなぁと。なんとかならんもんかと試行錯誤してましたら、Retinaディスプレイ用のメソッドがありましたよ。

 

[Retina用] UIViewを高画質で画像化、取得してみる

んで今回はこんな感じ。

-(IBAction)retinaSaveAction:(id)sender {
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGSize size = { 480, 320 };
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor blackColor] set];
    CGContextFillRect(ctx, screenRect);
    // 保存するビューを指定
    [self.view.layer renderInContext:ctx];
    // 指定したビューをPNGで取得
    NSData *pngData = UIImagePNGRepresentation(UIGraphicsGetImageFromCurrentImageContext());
    UIImage *screenImage = [[UIImage imageWithData:pngData] retain];
    // 取得したPNG画像をカメラロールに保存する
    UIImageWriteToSavedPhotosAlbum(screenImage, nil, nil, nil);
    UIGraphicsEndImageContext();
}

ポイントは4行目の"UIGraphicsBeginImageContextWithOptions(size, NO, 0);"のところ。

変わってるでしょ?"WithOptions"って。

で、"0"ってなってるところで、指定したサイズを何倍で取得するか設定するんですね。
"0"ならデバイスを自動で判定します。"1.5"なら720*480pxで取得します。中央のBOOL値は何だったっけ??忘れました。気になった人は調べてください。

ちなみに、マヨネーズの描画にもこれを使ってます。ただ、"0" だと高画質すぎて処理落ちハンパなかったので"1.5"にしてますケド。

んで14行目!
なんと劣化なしのPNGデータ!キャッホ〜〜ッ!
これで、お好み焼きがますますウマそうだぜッ!!

 

というわけで以上です。参考になれば幸いです。

 

そしてiOkonomiyakiをダウンロードして課金してくれたらもっと幸いです。

 

今回の一言

あ、UIImageWriteToSavedPhotosAlbumのところでセレクター指定して、保存が完了した後のアクションを指定できます。

こんな感じ。

-(IBAction)retinaSaveAction:(id)sender {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // 描画した画像をカメラロールに保存する
    UIImageWriteToSavedPhotosAlbum(screenImage,
                                   self,
                                   @selector(onCompleteCapture:didFinishSavingWithError:contextInfo:),
                                   NULL);
    UIGraphicsEndImageContext();
}
//保存完了のアラート
- (void)onCompleteCapture:(UIImage *)screenImage didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
    NSString *message = @"カメラロールに保存しました\nSaved to the Photo Library.";
    if(error) message = @"保存に失敗しました\nError.";
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@""
                                                    message:message
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    [alert show];
}

 

 

コメント
コメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2013 THE AGE