17
CAIM:04 「画像を合成する」 演習講師:渡邉 賢悟 (渡辺電気株式会社)

CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

CAIM:04 「画像を合成する」

演習講師:渡邉 賢悟 (渡辺電気株式会社)

Page 2: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

04:1 画像を合成する(基礎)

Page 3: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

使用するプログラム

• ios_caim04_.zip • 解凍して、中のios_caim04.xcodeprojをダブルクリック

Page 4: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

複数画像の準備 (Data.swift)• 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

class Data { // 画像データ var image_base: CAIMImagePtr! // 表示用台紙画像 var image_lena: CAIMImagePtr! // lena.png読み込み画像 // 初期化 private init() { // 画像作成(表示台紙用データ)画面全体の大きさにする let wid = Int(UIScreen.mainScreen().bounds.width * 2) let hgt = Int(UIScreen.mainScreen().bounds.height * 2) self.image_base = CAIMImageCreate(wid, hgt) // 画像の作成(lena.pngを読み込む) self.image_lena = CAIMImageCreateWithFile(CAIMBundle("lena.png")) } }

• image_baseが表示用の画像、image_lenaが「lena.png」を読み込んだ素材用画像である

Page 5: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

ImageProc.composite関数• 複数の処理をまとめて書くcomposite関数を用意した

// 各種画像合成処理 static func composite() { // data.image_baseを少し青くする ImageProc.fillColor(data.image_base, color: CAIMColor(R: 0.8, G: 0.9, B: 1.0, A: 1.0)) // data.image_lenaを、data.image_baseの(20,20)の位置に貼り付ける ImageProc.pasteImage(data.image_lena, img_dst: data.image_base, tx: 20, ty: 20, opacity:0.5)

// …(その他の描画、合成処理を適宜追加しよう)… }

• 初期のコードでは、 • image_baseを薄青に塗りつぶす (fillColor) • image_lenaをimage_baseに貼り付ける (pasteImage)

• 上記の処理を行いたい

Page 6: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

イメージ図

data.image_base (表示用台紙画像)

data.image_lena (素材画像)

貼り付けdata.image_base (処理後)

半分透ける

Page 7: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

色指定可の塗りつぶし関数(実装済み)• ImageProc.swiftのfillColorはcolor引数で色指定ができる // 画像を塗りつぶす関数 static func fillColor(img:CAIMImagePtr, color:CAIMColor) { // 結果画像のデータを取得 let mat = CAIMImageMatrix(img) // 元画像のピクセルデータ let wid = CAIMImageWidth(img) // 元画像の横幅 let hgt = CAIMImageHeight(img) // 元画像の縦幅 // 画像のすべてのピクセルを1つずつ処理する for(var y:Int = 0; y < hgt; ++y) { for(var x:Int = 0; x < wid; ++x) { mat[y][x] = color } } }

• 利用する際はCAIMColorを指定する •ImageProc.fillColor(data.image_base, color: CAIMColor(R: 0.8, G: 0.9, B: 1.0, A: 1.0))

Page 8: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

画像の貼り付け合成関数(1)• ImageProc.swiftのpasteImageを完成させる • img_src(素材画像)をimg_dst(台紙画像)に貼り付ける。貼り付け位置を(tx,ty)で指定する。opacityは透け具合を0.0~1.0で指定する

• static func pasteImage(img_src:CAIMImagePtr, img_dst:CAIMImagePtr, tx:Int, ty:Int, opacity:Float=1.0) { // 貼り付ける素材画像のデータを取得 let mat_src = CAIMImageMatrix(img_src) // 元画像のピクセルデータ let wid_src = CAIMImageWidth(img_src) // 元画像の横幅 let hgt_src = CAIMImageHeight(img_src) // 元画像の縦幅 // 貼り付けられる台紙画像のデータを取得 let mat_dst = CAIMImageMatrix(img_dst) // 元画像のピクセルデータ let wid_dst = CAIMImageWidth(img_dst) // 元画像の横幅 let hgt_dst = CAIMImageHeight(img_dst) // 元画像の縦幅 // 処理範囲を計算 let min_x = tx let min_y = ty let max_x = tx + wid_src let max_y = tx + hgt_src …(次ページに続く)…

Page 9: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

画像の貼り付け合成関数(2) …(続き) for(var y:Int = min_y; y < max_y; ++y) { for(var x:Int = min_x; x < max_x; ++x) { // 素材画像(lena)の色をとってくる座標を計算 let x2 = x - tx let y2 = y - ty // 素材画像側のはみ出し防止 if(x2 < 0 || y2 < 0 || x2 >= wid_src || y2 >= hgt_src) { continue; } // 台紙画像の(x, y)から色をとってくる let R = mat_dst[y][x].R let G = mat_dst[y][x].G let B = mat_dst[y][x].B let A = mat_dst[y][x].A // 引数のopacityの値に合わせて、素材画像の色と台紙画像の色を混ぜる mat_dst[y][x].R = mat_src[y2][x2].R * opacity + R * (1.0-opacity) mat_dst[y][x].G = mat_src[y2][x2].G * opacity + G * (1.0-opacity) mat_dst[y][x].B = mat_src[y2][x2].B * opacity + B * (1.0-opacity) mat_dst[y][x].A = mat_src[y2][x2].A * opacity + A * (1.0-opacity) } } }

• mat_dst(台紙側の色)を取得し、素材画像の色と混ぜて新しい色をmat_dstに設定し直している • 色を混ぜる比率をopacity,(1.0-opacity)で行うのがポイント

Page 10: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

drawRect関数の改良(1)• CAIM03で作ったdrawRectにopacityを使った合成処理を追加しよう // 四角を描く関数 static func drawRect(img:CAIMImagePtr, x1:Int, y1:Int, x2:Int, y2:Int, color:CAIMColor, opacity:Float=1.0) { // 画像のデータを取得 let mat = CAIMImageMatrix(img) // 画像のピクセルデータ let wid = CAIMImageWidth(img) // 画像の横幅 let hgt = CAIMImageHeight(img) // 画像の縦幅 // 2点の座標値の小さい方、大きい方を判別して別の変数に入れる let min_x = min(x1, x2) let min_y = min(y1, y2) let max_x = max(x1, x2) let max_y = max(y1, y2)

…(次ページに続く)…

Page 11: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

drawRect関数の改良(2) …(続き)

// min_x~max_x, min_y~max_yまでの範囲を塗る for(var y:Int = min_y; y <= max_y; ++y) { for (var x:Int = min_x; x <= max_x; ++x) { // x,yが画像外にはみだしたら、エラー防止のためcontinueで処理をスキップする if(x < 0 || y < 0 || x >= wid || y >= hgt) { continue; } // 画像の(x, y)から色をとってくる let R = mat[y][x].R let G = mat[y][x].G let B = mat[y][x].B let A = mat[y][x].A // 引数のopacityの値に合わせて、新しい色と元画像の色を混ぜる mat[y][x].R = color.R * opacity + R * (1.0-opacity) mat[y][x].G = color.G * opacity + G * (1.0-opacity) mat[y][x].B = color.B * opacity + B * (1.0-opacity) mat[y][x].A = color.A * opacity + A * (1.0-opacity) } } }

• 引数にopacityを追加し、ループ処理の中で画像の色と塗る色を混ぜる計算を追加すれば良い

Page 12: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

composite関数で絵を描く• 作った関数を用いて、opacityをいろいろ設定しながら絵を描いてみよう

• 必要な画像をData.swiftに追加しよう • これまで作ってきたグラデーションなども合成してみよう

// 各種画像合成処理 static func composite() { // data.image_baseを少し青くする ImageProc.fillColor(data.image_base, color: CAIMColor(R: 0.8, G: 0.9, B: 1.0, A: 1.0)) // data.image_lenaを、data.image_baseの(20,20)の位置に貼り付ける ImageProc.pasteImage(data.image_lena, img_dst: data.image_base, tx: 20, ty: 20, opacity:0.5)

// …(その他の描画、合成処理を適宜追加しよう)… }

Page 13: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

04:2 画像を合成する(応用)

Page 14: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

応用演習(1):CAIM03のdrawコード改良

• CAIM03で自作したdrawCircleなどをCAIM04にコピーし、 • 引数opacityを追加して画像合成できるように改良する

Page 15: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

04:3 Swiftプログラミング入門(4)

Page 16: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

バンドル - 外部ファイルの利用(1)• バンドルとは(lena.pngのような)外部ファイルをアプリ内で利用する方法である • まずアプリ内で使いたい画像を、アプリのプロジェクトフォルダ内にコピーする

Page 17: CAIM:04 「画像を合成する」 · 複数画像の準備 (Data.swift) • 今回は複数の画像を合成して絵を作る • 合成につかう「素材画像」と、素材を貼り付ける「表示用台紙画像」をData.swiftに用意する

バンドル - 外部ファイルの利用(2)• プロジェクトフォルダ内にコピーした画像をXCodeに追加する • リストに増えたことを確認できたら、プログラム内で読み込み可能となる