[SwiftUI] CAShapeLayer와 UIImage를 사용하여 이미지 합성

환경



Swift5
SwiftUI
Xcode11.5

실현하는 것



SwiftUI 프레임워크를 사용하여 모든 이미지에 도형을 합성합니다. 이 기사에서는이 귀여운 강아지를 원형 모양으로 둘러 쌉니다.


구현


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로 렌더링
- 위의 두 이미지를 하나의 이미지로 합성

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()
    }
}

시뮬레이터 또는 실제 기계로 실행



지금까지 만든 이미지가 다음과 같이 표시됩니다.



소감



자작 앱을 작성하고 있는 단계에서, 촬영한 사진의 UIImage와 합성한 도형의 위치 관계로 엉망이었으므로, 이 기사에서 정리하게 했습니다.

(* 짧은 다리로 귀엽다)

참고문헌



SwiftUI에서 MVVM
h tp : // 쉰다. 하테나 bぉg. 코m/엔트리/2019/12/22/133157
【Swift4】UIView를 UIImage로 변환하여 이미지로 카메라 롤에 저장하는 방법
htps : //p 여과 등 mぃふぇ. 코m/410

좋은 웹페이지 즐겨찾기