Core Image는 이미지 조작을 위한 Apple의 프레임워크이다. 선명하게 하기, 흐림 효과, 비네팅, 픽셀화 등을 적용하여 기존 이미지를 변경해준다.
그러나 Core Image는 SwiftUI에도, UIKit에도 잘 통합되지 않는다고 한다. 그래서 아래의 Image를 적절히 사용할 필요가 있다.
assets에 저장한 이미지를 UIImage로 변경하고 CoreImage로 조작하는 예시는 아래와 같다.
import CoreImage
import CoreImage.CIFilterBuiltins
func loadImage() {
let inputImage = UIImage(resource: .cat)
let beginImage = CIImage(image: inputImage)
let context = CIContext()
let currentFilter = CIFilter.sepiaTone()
currentFilter.inputImage = beginImage
currentFilter.intensity = 1
// 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
guard let cgImage = context.createCGImage(outputImage, from: outputImage.extent) else { return }
// convert that to a UIImage
let uiImage = UIImage(cgImage: cgImage)
// and convert that to a SwiftUI image
image = Image(uiImage: uiImage)
}
sepiaTone() 필터가 적용된 모습이다.
아래처럼 필터를 조절해서 다른 효과도 줄 수 있다.
let currentFilter = CIFilter.pixellate()
currentFilter.inputImage = beginImage
currentFilter.scale = 100
let currentFilter = CIFilter.twirlDistortion()
currentFilter.inputImage = beginImage
currentFilter.radius = 1000
currentFilter.center = CGPoint(x: inputImage.size.width / 2, y: inputImage.size.height / 2)
효과를 줄 때 radius, intense, scale 등 설정해야 하는 속성이 다른데, older API를 활용해서 설정하는 방법도 있다.
let currentFilter = CIFilter.twirlDistortion()
currentFilter.inputImage = beginImage
let amount = 1.0
let inputKeys = currentFilter.inputKeys
if inputKeys.contains(kCIInputIntensityKey) {
currentFilter.setValue(amount, forKey: kCIInputIntensityKey) }
if inputKeys.contains(kCIInputRadiusKey) { currentFilter.setValue(amount * 200, forKey: kCIInputRadiusKey) }
if inputKeys.contains(kCIInputScaleKey) { currentFilter.setValue(amount * 10, forKey: kCIInputScaleKey) }
제일 첫 번째 줄의 CIFilter 뒤의 효과만 원하는 대로 변경하면 된다.
![]() | ![]() | ![]() |
---|
boxBlur/dotScreen/zumBlur
ContentUnavailableView는 앱에서 보여줄 컨텐츠가 없는 경우에 표준적으로 보여줄 수 있는 view이다. 최소 title과 image로 나타낼 수 있다.
struct ContentView: View {
var body: some View {
ContentUnavailableView("Not found", systemImage: "questionmark", description: Text("You find an empty page."))
}
}
혹은 title, description 등에 각각 view를 설정할 수도 있다.
struct ContentView: View {
var body: some View {
ContentUnavailableView {
Label("Not found", systemImage: "questionmark")
} description: {
Text("You found an empty page.")
} actions: {
Button("Go back") {
// create a snippet
}
.buttonStyle(.bordered)
}
}
}