iOS Tips #4 iOSでpng形式の画像からマスク画像を作成する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

iOSでpng形式の画像からマスク画像を作成する方法を書きたいと思います。

今回は以下の環境を前提に説明します。

Mac OS X 10.8 Moutain lion
Xcode 4.6.2
iOS SDK 6.1
iPhone 5

プロジェクトの作成

まずは、XcodeよりSingle View Applicationを選択し、以下の内容でプロジェクトを作成しましょう。

項目 設定値
Product Name MaskImageSample
Organization Name 自分の名前(サンプルなのでテキトー)
Company Identifier 会社名(サンプルなのでテキトー)
Class Prefix なし
Devices iPhone
Use Storyboards チェックする(ストーリーボードを使用)
Use Automatic Reference Counting チェックする(ARC有効)
Include Unit Tests チェックしない(unit testのターゲットを含まない)

マスク画像を作成するUIImageのカテゴリを定義しよう

早速今回のお題で一番大事なところから実装します。作成したMaskImageSampleにUIImage+Maskを作成し、以下のように記述してください。

UIImage+Mask.h
#import <UIKit/UIKit.h>

/**
 UIImage機能拡張
 */
@interface UIImage (Mask)

/**
 マスクイメージを取得する
 @param  maskColor  マスクカラー
 @return マスクイメージ
 */
- (UIImage *)generateMaskImage:(UIColor *)maskColor;

@end
UIImage+Mask.m
#import "UIImage+Mask.h"

@implementation UIImage (Mask)

#pragma mark - Public methods

- (UIImage *)generateMaskImage:(UIColor *)maskColor
{
    // 描画サイズ
    CGRect rect = CGRectMake(0.0f, 0.0f, self.size.width, self.size.height);
    
    // 画像サイズでビットマップグラフィックコンテキストを取得
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(NULL,
                                             rect.size.width,
                                             rect.size.height,
                                             8,
                                             0,
                                             colorSpace,
                                             kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(colorSpace);
    
    if (ctx == NULL) {
        return nil;
    }
    
    // 指定色を一面に塗ってそのコンテキストからCGImageRefを生成
    CGContextSetFillColorWithColor(ctx, maskColor.CGColor);
    CGContextFillRect(ctx, rect);
    CGImageRef colorImageRef = CGBitmapContextCreateImage(ctx);
    
    // 一旦コンテキストをクリア
    CGContextClearRect(ctx, rect);
    
    // マスク
    CGContextClipToMask(ctx, rect, self.CGImage);
    CGContextDrawImage(ctx, rect, colorImageRef);
    
    // ビットマップグラフィックコンテキストからマスク済み画像を生成
    CGImageRef maskedImageRef = CGBitmapContextCreateImage(ctx);
    UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];
    
    CGImageRelease(colorImageRef);
    CGImageRelease(maskedImageRef);
    CGContextRelease(ctx);
    
    return maskedImage;
}

@end

特に重要なのがvoid CGContextClipToMask(CGContextRef c, CGRect rect, CGImageRef mask)関数です。この関数を用いてCGContextに指定された矩形でマスクイメージを生成します。

そして、次の行にあるvoid CGContextDrawImage(CGContextRef c, CGRect rect, CGImageRef image)関数を使用して指定した色で塗る訳です。

UIImage+Maskを使用する

ViewControllerでUIImage+Maskを使用するように変更しましょう。

#import "ViewController.h"
#import "UIImage+Mask.h"

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // マスク画像を生成するpng画像
    UIImage *image = [UIImage imageNamed:@"face_hirai_small"];
    
    // マスク画像を生成
    UIImage *maskedImage = [image generateMaskImage:[UIColor blackColor]];
    
    UIImageView *imageView = [[UIImageView alloc] initWithImage:maskedImage];
    
    [self.view addSubview:imageView];
}

@end

あとはマスク画像を生成するpng画像を指定するだけです。自分の顔でまことに恐縮ですが、今回は以下の画像を使用します。

face_hirai_small

実行結果

ios-tips-4_1