2012年6月4日月曜日

iOSで角丸画像の作り方

画像を角丸にして表示したい 時。
いくつか方法があります。

a. 角丸の画像を描画して抜き出す

How to make an image with rounded corners
のようにゴリッと書いて画像を作ってしまうパターン。

Resize a UIImage the right wayにすぐに使えるコードも置いてある。素敵。

b. マスク画像で抜き出す

画像処理に使えるUIImageのTips10個 - (9) マスク処理で角丸画像を作成する
私はまだやったことないのですが、角丸のように単純でない抜き出しは楽そうー。

c. CALayerの cornerRadiusで指定する

#import <QuartzCore/QuartzCore.h>

@implementation FERoundView

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        self.layer.cornerRadius = 4.0f;
    }
    return self;
}
@end

こんな感じで、CALayerのcornerRadiusで指定するのはとっても簡単。
1つこんな感じのViewをつくっておけば、角丸にしたいラベルの背景がある時に InterfaceBuilderのクラスに作ったクラスを指定するだけで完了します。

調子に乗って、角丸画像が一覧になっている画面にCALayer#cornerRadiusで指定したものを並べてみたのですが、 これが遅い! スクロールするとガクガク...
そんなに重い処理だったんですね、コレ。

このLayerの機能をつかって a.のような角丸画像作成メソッドとして使っちゃう手もあります。
シンプルなコードでかけるのが魅力的。

- (UIImage *)makeCornerRoundImage:(UIImage *) image {
    CALayer *imageLayer = [CALayer layer];
    imageLayer.frame = CGRectMake(0, 0, 200, 200);
    imageLayer.contents = (id) image.CGImage;
    imageLayer.masksToBounds = YES;
    imageLayer.cornerRadius = 4.0f;
    
    UIGraphicsBeginImageContext(imageLayer.frame.size);
    [imageLayer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return roundedImage;
}



当たり前のお話なんですが、画像を一度にたくさん表示するのであれば、
・最適の画像サイズ&角丸などの処理済み の画像を用意しておく
・表示はUIImageViewでなくてdrawRectで書いてメモリ節約
ってのはとても効果が大きいもんですなぁ

テスト的にアプリ作っていると、ついつい手抜きでInterfaceBuilderで画面イメージ想像しながらUI部品貼り付けて、画像も既にある画像を拡大/縮小してとりあえず表示しちゃう。
ま、それはそれでいいですよねぇー。あとで、ちゃんと書きなおすのであればw

UIImagePickerでカメラを起動して写真撮ると、結構メモリを消費する上に、
その際に メモリ警告がでると それまでに作成していたViewが削除されてしまう状態になり...
viewが削除された画面に戻ると、UIViewControllerのloadViewからまたふただびCallされる事になり...
"わはーっ ちゃんと真面目にやろう..."
と、ワタワタした土曜日を過ごした(笑

• • •