63: Instafilter, part 2

그루두·2024년 7월 10일
0

100 days of SwiftUI

목록 보기
71/108

Project 13, part 2

CoreImage

Core Image는 이미지 조작을 위한 Apple의 프레임워크이다. 선명하게 하기, 흐림 효과, 비네팅, 픽셀화 등을 적용하여 기존 이미지를 변경해준다.

그러나 Core Image는 SwiftUI에도, UIKit에도 잘 통합되지 않는다고 한다. 그래서 아래의 Image를 적절히 사용할 필요가 있다.

  • UIImage: UIKit에서 유래했고, SwiftUI의 이미지 타입과 가장 가깝다. 다양한 이미지 타입(비트맵, 벡터 등)을 작업할 수 있다.
  • CGImage: Core Graphics에서 유래했고, 2차원 픽셀 배열이라 간단한 이미지 유형이다.
  • CIImage: Core Image에서 유래했고, 이미지를 생성하기 위한 정보를 저장한다. 요청을 하지 않는다면 픽셀로 바뀌지 않는다. 그래서 an image recipe라고 불린다.

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

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

깃헙 링크

profile
계속 해보자

0개의 댓글

관련 채용 정보