65: Instafilter, part 4

그루두·2024년 7월 12일
0

100 days of SwiftUI

목록 보기
73/108

Project 13, part 4

기본 UI 설정하기

기본 UI의 틀을 미리 잡아두었다.

깃헙 링크

PhotosPicker 설정

업로드한 사진이 있으면 사진을 클릭해서, 없으면 ContentUnavailableView를 클릭해서 사진을 고를 수 있도록 label로 설정했다.

                PhotosPicker(selection: $selectedItem) {
                    if let processedImage {
                        processedImage
                            .resizable()
                            .scaledToFit()
                    } else {
                        ContentUnavailableView("No picture", systemImage: "photo.badge.plus", description: Text("Click to import a picture"))
                    }
                }
                .buttonStyle(.plain)
                .onChange(of: selectedItem, loadImage)

그리고 사진을 변경하면 아래 loadImage 함수를 실행해서 선택된 이미지를 UIImage로 변경한다. 해당 함수는 아래에서 좀 더 보완한다.

    func loadImage()  {
        Task {
            guard let imageData = try await selectedItem?.loadTransferable(type: Data.self) else { return }
            guard let inputImage = UIImage(data: imageData) else { return }
        }
    }

Filter 설정하고 사진에 적용하기

이젠 임의로 필터를 설정하고 그 변화를 사진에 적용해야 한다.

먼저, 임의로 필터를 sepiaTone()으로 설정했다. 그리고 나중에 CGImage를 만들기 위해 context도 설정했다.

	@State private var currentFilter = CIFilter.sepiaTone()
    let context = CIContext()

그리고 필터의 intensity도 설정하고 이미지를 필터대로 변화시켜 Image로 변경하는 함수 applyProcess()를 설정한다. processedImage에 변경된 이미지로 설정함으로써 화면에 업로드한 이미지가 변화하는 것을 볼 수 있다.

    func applyProcess() {
        currentFilter.intensity = Float(intensityAmount)
        
        guard let outputImage = try currentFilter.outputImage else { return }
        guard let cgImage = try context.createCGImage(outputImage, from: outputImage.extent) else { return }
        
        let uiImage = UIImage(cgImage: cgImage)
        processedImage = Image(uiImage: uiImage)
    }

추가로 Slider의 값이 바뀜에 따라 intensityAmount가 바로 변화하도록 onChange로 설정한다.

                    Slider(value: $intensityAmount)
                        .onChange(of: intensityAmount, applyProcess)

💡 Core Image filter가 inputImage 속성을 통해 필터를 적용할 수 있는 CIImage로 바꿀 수 있게 한다. 그러나 가끔 치명적인 앱 에러로 이어지기도 해서 아래처럼 kCIInputImageKey과 함께 setValue()를 이용하는 것을 추천한다고 한다.

func loadImage() {
	// ...
    let beginImage = CIImage(image: inputImage)
	currentFilter.setValue(beginImage, forKey: 		kCIInputImageKey)
	applyProcessing()
}

깃헙 링크

왼쪽이 시뮬레이터이고, 오른쪽이 휴대폰에서 실행한 모습이다. 휴대폰이 훨씬 빠르게 적용된다.

profile
계속 해보자

0개의 댓글

관련 채용 정보