1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[SwiftUI] CAShapeLayerとUIImageを使って、画像を合成する

Last updated at Posted at 2020-06-15

環境

Swift5
SwiftUI
Xcode11.5

実現すること

SwiftUIフレームワークを使って、任意の画像に図形を合成する。本記事では、このかわいい犬を円の図形で囲むようにします。
Untitled.001.png

実装

ComposedImageModel.swiftが以下になります。

ComposedImageModel.swift
import Foundation
import UIKit

struct ComposedImageModel {
    // 犬の画像格納用
    var image:         UIImage 
    // CAShapeLayer画像格納用
    var layerImage:    UIImage
    // 合成した画像格納用
    var composedImage: UIImage
    
    init() {
        self.image         = UIImage()
        self.layerImage    = UIImage()
        self.composedImage = UIImage()
    }
}

次に以下ComposedImageViewModel.swiftでUIImageを合成する処理を記載していきます。
[主な処理]

  • 犬の画像を格納
  • CAShapeLayerを使って円形の図形を作成 > UIImageにレンダリング
  • 上記2つの画像を1つの画像に合成
ComposedImageViewModel.swift
import Foundation
import UIKit

class ComposedImageViewModel {
    
    var composedImageModel: ComposedImageModel
    
    init() {
        self.composedImageModel = ComposedImageModel()
        composedImages()
    }
    
    // 2つのUIImageを1つのUIImageに合成
    private func composedImages() {
        // いっぬの画像を取得
        self.composedImageModel.image = UIImage(named: "dog")!
        
        // CAShapeLayerと使って円形を描画
        let calayer         = CAShapeLayer()
        let size            = self.composedImageModel.image.size
        calayer.frame       = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        calayer.path        = UIBezierPath(ovalIn: CGRect.init(x: size.width/2 - size.height/2, y: 0, width: size.height, height: size.height)).cgPath
        calayer.fillColor   = UIColor.clear.cgColor
        calayer.strokeColor = UIColor.black.cgColor

        // 円形のCAShapeをUIImageにレンダリング
        UIGraphicsBeginImageContextWithOptions(calayer.frame.size, false, 1)
        let context = UIGraphicsGetCurrentContext()!
        calayer.render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.composedImageModel.layerImage = image!
        
        // いっぬのUIImageとレンダリングされた円形のUIImageを合成
        UIGraphicsBeginImageContext(CGSize(width: size.width, height: size.height))
        self.composedImageModel.image.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        self.composedImageModel.layerImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        self.composedImageModel.composedImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
    }
        
}

次に以下ComposedImageView.swiftで比較できるように

  • 犬のUIImage
  • CAShapeLayerから作成した円形のUIImage
  • 上記2つを合成したUIImage
    を表示します。CAShapeLayerのUIImageに関しては、サイズの大きさがわかりやすいように意図的に背景を赤くして表示しています。
ComposedImageView.swift
import SwiftUI

struct ComposedImageView: View {
    
    private var imageVM = ComposedImageViewModel()
    
    var body: some View {
        VStack {
            // いっぬのImageを表示
            Image(uiImage: self.imageVM.composedImageModel.image)
            // CAShapeからレンタリングしたImageを表示
            Image(uiImage: self.imageVM.composedImageModel.layerImage)
                .background(Color.red)
            // 上記二つのImageを合成したImageを表示
            Image(uiImage: self.imageVM.composedImageModel.composedImage)
        }
    }
}

struct ComposedImageView_Previews: PreviewProvider {
    static var previews: some View {
        ComposedImageView()
    }
}

ContentView.swiftComposedImageViewを記載して、表示させる。

ContentView.swift
import SwiftUI

struct ContentView: View {
    
    var body: some View {
        ComposedImageView()            
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

シミュレーター又は実機で実行

これまで作成した画像が、以下のように表示されます。

Screen Shot 2020-06-15 at 19.43.22.png

所感

自作アプリを作成している段階で、撮影した写真のUIImageと合成した図形の位置関係でごちゃごちゃしたので、本記事でまとめさせてもらいました。

(*短足でかわいいよね)

参考文献

SwiftUIでMVVM
http://sinnderu.hatenablog.com/entry/2019/12/22/133157
【Swift4】UIViewをUIImageに変換し、画像としてカメラロールに保存する方法
https://program-life.com/410

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?