Core ImageとSwiftUIの統合
Integrating Core Image with SwiftUI
struct ContentView: View { @State private var image: Image? var body: some View { VStack { image? .resizable() .scaledToFit() } .onAppear(perform: loadImage) } func loadImage() { image = Image("Example") } }
SwiftUIのImageビューとは別に、他の3つのイメージタイプは次のとおりです。
UIImage、これはUIKitから来ています。これは、ビットマップ(PNGなど)、ベクター(SVGなど)、さらにはアニメーションを形成するシーケンスなど、さまざまな画像タイプを処理できる非常に強力な画像タイプです。UIImageUIKitの標準の画像タイプで、3つのうちSwiftUIのImageタイプに最も近いタイプです。
CGImage、Core Graphicsによるものです。これは、実際には単なるピクセルの2次元配列である単純なイメージタイプです。
CIImage、Core Imageから来ています。これは、画像の生成に必要なすべての情報を保存しますが、要求されない限り、実際にはそれをピクセルに変換しません。AppleはCIImage、実際の画像ではなく「画像レシピ」と呼んでいます。
いくつかの相互運用性があります。
私たちは、作成することができますUIImageからしCGImageて、作成CGImageからUIImage。
私たちは、作成することができますCIImageからUIImageからCGImage、および作成することができますCGImageからCIImage。
私たちは、SwiftUI作成することができImage、Aの両方からUIImageとCGImage。
import SwiftUI import CoreImage import CoreImage.CIFilterBuiltins struct ContentView: View { @State private var image: Image? var body: some View { VStack { image? .resizable() .scaledToFit() } .onAppear(perform: loadImage) } //-------------- func loadImage() { //CIImageこれはCore Imageで使用したいものです。 guard let inputImage = UIImage(named: "IMG_1308") else { return } let beginImage = CIImage(image: inputImage) // more code to come //コンテキストとフィルターを作成します。 let context = CIContext() //セピアは単純なフィルターであるため、2つのプロパティしかありません。 //セピア効果を適用する強さを0(元の画像)と1(フルセピア)の範囲で指定します。 let currentFilter = CIFilter.sepiaTone() //フィルターをカスタマイズして、動作を変更できます。 currentFilter.inputImage = beginImage currentFilter.intensity = 1 // let currentFilter = CIFilter.pixellate() // currentFilter.inputImage = beginImage // currentFilter.scale = 50 // let currentFilter = CIFilter.crystallize() // currentFilter.setValue(beginImage, forKey: kCIInputImageKey) // currentFilter.radius = 200 // guard let currentFilter = CIFilter(name: "CITwirlDistortion") else { return } // currentFilter.setValue(beginImage, forKey: kCIInputImageKey) // currentFilter.setValue(2000, forKey: kCIInputRadiusKey) // currentFilter.setValue(CIVector(x: inputImage.size.width / 2, y: inputImage.size.height / 2), forKey: kCIInputCenterKey) // get a CIImage from our filter or exit if that fails guard let outputImage = currentFilter.outputImage else { return } // attempt to get a CGImage from our CIImage if let cgimg = context.createCGImage(outputImage, from: outputImage.extent) { // convert that to a UIImage let uiImage = UIImage(cgImage: cgimg) // and convert that to a SwiftUI image image = Image(uiImage: uiImage) } } //-------------- }
SwiftUIビューでのUIViewControllerのラップ
Wrapping a UIViewController in a SwiftUI view
このプロジェクトでは、ユーザーにフォトライブラリから画像をインポートするように依頼します。UIKitには、これを行うための専用コードが付属していますが、これはSwiftUIに移植されていないため、そのブリッジを自分で作成する必要があります。
ライブラリから写真を選択するようにユーザに尋ねるのUIKitののシステムと呼ばれるビューコントローラを使用するためUIImagePickerController、およびデリゲートプロトコルと呼ばれるUINavigationControllerDelegateとUIImagePickerControllerDelegate。SwiftUIはこれら2つを直接使用できないため、ラップする必要があります。
UIKitビューコントローラーをラップするには、UIViewControllerRepresentableプロトコルに準拠した構造体を作成する必要があります。
もう1つはと呼ばれ、updateUIViewController()SwiftUIの状態が変化したときにビューコントローラーを更新できるように設計されています。
// // ImagePicker.swift // Core-Image // // Created by Naoki Abe on 2020/08/22. // Copyright © 2020 Naoki Abe. All rights reserved. // import Foundation import SwiftUI //struct ImagePicker: UIViewControllerRepresentable { // typealias UIViewControllerType = UIImagePickerController //} ////Type 'ImagePicker' does not conform to protocol 'UIViewControllerRepresentable' ////Do you want to add protocol stubs? //// Fix ↓ struct ImagePicker: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> UIImagePickerController { let picker = UIImagePickerController() return picker } func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) { } typealias UIViewControllerType = UIImagePickerController }
import SwiftUI struct ContentView: View { @State private var image: Image? @State private var showingImagePicker = false var body: some View { VStack { image? .resizable() .scaledToFit() Button("Select Image") { self.showingImagePicker = true } } .sheet(isPresented: $showingImagePicker) { ImagePicker() } } }
ただし、選択したばかりの画像は表示されません。SwiftUI Imageをビューに配置したにもかかわらず、からの選択をどこにも割り当てていないことがわかりますUIImagePickerController。
それを実現するには、まったく新しいコンセプトであるコーディネーターが必要です。
PART3へ続く!!