カメラアプリ開発入門
(第3回)
画像加工のいろは
2013/7/27 名古屋iPhone開発者勉強会
基本的な画像加工について学ぶ
13年7月27日土曜日
大塚 崇(おおつか たかし)
DJ / フリーランスのエンジニア・プログラマ
ハンドル名: takatronix
Facebook/Twitter/Skype/LINE/Weibo -> takatronix
http://takatronix.com
趣味興味:旅行、語学、筋トレ、LEGO、FX、心理学、 
脳科学、宇宙
自己紹介
13年7月27日土曜日
リリースしたアプリ
セクシーミラー、SEXY SCAN、 放射能汚染
地図、和牛スキャン ...
(代表作)
セクシーミラー-編集不要の神自撮りアプリ
13年7月27日土曜日
http://sexymirror-app.com
2013/1リリース イギリスのiPhone総合で
10位に、現在55万ダウンロード
セクシーミラー-編集不要の神自撮りアプリ
13年7月27日土曜日
画像加工の話の前に
Objective-Cのクラスを拡張する方法
Category(カテゴリ)を覚えよう
13年7月27日土曜日
カテゴリって?
クラスを継承せずにクラスを拡張できる
Objective-Cの言語仕様
13年7月27日土曜日
クラス継承との比較
メリット
デメリット
メンバ変数の追加はできない
既存のクラスを拡張できる
13年7月27日土曜日
具体的なメリット
画像加工のフィルタをViewControllerから
UIImageのメソッドに引越し
プロジェクトに依存しないため
使い回しが楽 (゚д゚)ウマー
13年7月27日土曜日
カテゴリの文法をおぼよう
13年7月27日土曜日
クラス名+カテゴリ名.h
@interface クラス名 (カテゴリ名)
-追加する関数宣言
@end
クラス名+カテゴリ名.m
@implementation クラス名 (カテゴリ名)
-追加する関数の実装
@end
13年7月27日土曜日
UIImageを拡張する
13年7月27日土曜日
File->New->File...
13年7月27日土曜日
追加するクラスとカテゴリ名を設定
13年7月27日土曜日
タン、タンターンとひな形が完成
13年7月27日土曜日
http://takatronix.com/tutorial/20130525.zip
カメラアプリ開発入門1プロジェクト
http://takatronix.com/tutorial/20130727.zip
今回のプロジェクト一式
13年7月27日土曜日
第一回目ので作成したフィルタ
をカテゴリに移動
13年7月27日土曜日
// モノクロフィルタ
-(UIImage*)monochromeFilter:(UIImage*)image{
// UIImageをCoreImageに変換する
CIImage* ciImage = [[CIImage alloc] initWithImage:image];
ViewControllerの関数から
// モノクロフィルタ
-(UIImage*)monochromeFilter{
// UIImageをCoreImageに変換する
CIImage* ciImage = [[CIImage alloc] initWithImage:self];
UIImage+Test.m
引数は必要なくself(自分の画像)をソースにする
13年7月27日土曜日
UIimage+Test.h
@interface UIImage (Test)
// モノクロフィルタ
-(UIImage*)monochromeFilter;
// ケラレフィルタ(カメラの周辺光量落ち)
-(UIImage*)vignetteFilter;
@end
13年7月27日土曜日
imageView.image = [self monochromeFilter:image];
imageView.image = [image monochromeFilter];
ViewControllerにフィルタがある場合
(前回までの記述方法)
UIImageのカテゴリの場合
13年7月27日土曜日
_imageView.image = [[image monochromeFilter] vignetteFilter];
フィルタを重ねる
モノクロフィルタ -> ケラレ
13年7月27日土曜日
さてここから本題
13年7月27日土曜日
オフスクリーン描画と
グラフィックスコンテキスト
を理解する
13年7月27日土曜日
オフスクリーン
画面に表示されていないメモリ上のスクリーン
仮想画面とも言われる
13年7月27日土曜日
コンテキストとは
(英)Context :文の前後関係、文脈
ペンの色や背景色などを保存するリソース
グラフィックコンテキスト
13年7月27日土曜日
解像度を変更する
13年7月27日土曜日
UIImageに解像度変更機能を追加
-(UIImage*)resizedImage:(CGSize)size{
// 新しいサイズでオフスクリーンバッファを作成する
UIGraphicsBeginImageContext(size);
// 現在のコンテキスト(オフスクリーンバッファ)に 自分のイメージを描写する
[self drawInRect:CGRectMake(0,0,size.width,size.height)];
// オフスクリーンバッファをUIImageに変換
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
// オフスクリーンバッファを破棄
UIGraphicsEndImageContext();
// 新しい画像を返す
return newImage ;
}
13年7月27日土曜日
画像の切り出し
13年7月27日土曜日
UIImageに切り出し機能を追加
// 画像の一部分を切り出す
-(UIImage*)cropImage:(CGRect)rect{
CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], rect);
UIImage *retImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return retImage;
}
13年7月27日土曜日
画像の反転
13年7月27日土曜日
UIImageに画像反転機能を追加する
- (UIImage *)mirrorImage{
CGImageRef imgRef = [self CGImage]; // 画像データ取得
UIGraphicsBeginImageContext(self.size);
// コンテキスト取得
CGContextRef context = UIGraphicsGetCurrentContext();
// コンテキストの軸をXもYも等倍で反転
CGContextTranslateCTM( context, self.size.width, self.size.height); // コンテキストの原点変更
CGContextScaleCTM( context, -1.0, -1.0);
// コンテキストにイメージを描画
CGContextDrawImage( context, CGRectMake( 0, 0, self.size.width, self.size.height), imgRef);
// コンテキストからイメージを取得
UIImage *retImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return retImg;
}
13年7月27日土曜日
座標系の話
CoreGraphicsは左下基準
Y軸が反転している
13年7月27日土曜日
CTMとは
変換行列(CTM : Current Transformation Matrix)
13年7月27日土曜日
画像の回転
13年7月27日土曜日
画像の回転-(UIImage*)rotateImage:(int)angle{
CGImageRef imgRef = [self CGImage];
CGContextRef context;
// 角度に応じて現在のコンテキストのCTMを変更
switch (angle) {
case 90:
UIGraphicsBeginImageContext(CGSizeMake(self.size.height, self.size.width));
context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, self.size.height, self.size.width);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextRotateCTM(context, M_PI/2.0);
break;
case 180:
UIGraphicsBeginImageContext(CGSizeMake(self.size.width, self.size.height));
context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, self.size.width, 0);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextRotateCTM(context, -M_PI);
break;
case 270:
UIGraphicsBeginImageContext(CGSizeMake(self.size.height, self.size.width));
context = UIGraphicsGetCurrentContext();
CGContextScaleCTM(context, 1.0, -1.0);
CGContextRotateCTM(context, -M_PI/2.0);
break;
default:
return self;
}
// オフスクリーンに描写->UIImage変換
CGContextDrawImage(context, CGRectMake(0, 0, self.size.width, self.size.height), imgRef);
UIImage *retImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return retImage;
}
13年7月27日土曜日
プロジェクトとこのスライドはここから
落とせますよ。
http://takatronix.com/tutorial/20130727.zip
13年7月27日土曜日
takatronix検索
http://takatronix.com
13年7月27日土曜日
ありがとうございました
takatronix検索
http://takatronix.com
13年7月27日土曜日

カメラアプリ開発入門3