Back to Blog

[Core Image] CIFilter - 사진에 다양한 시스템 필터 효과 주기

2024년 03월 17일
5분
Swift
CIFilter, 이미지 필터, Core Image, iOS, 글또 9기, Swift
[Core Image] CIFilter - 사진에 다양한 시스템 필터 효과 주기

개인적으로 이미지나 비디오 등의 미디어 플레이, 편집 등 멀티미디어 관련 기술에 관심이 많아 자료를 많이 찾아보는 편인데, 최근 미디어에 여러 필터를 적용하는 방법을 찾아보았습니다.
이번 시간에는 미디어에 다양한 효과를 주는 방법 중 Core Image(이하 '코어 이미지') 프레임워크에서 지원하는 CIFilter를 이용하여 사진에 다양한 효과를 주는 방법에 대해 알아보려고 합니다.

Core Image

코어 이미지는 Apple의 퍼스트파티 프레임워크의 하나로, 정지 영상 및 동영상 이미지에 고성능 처리를 제공하는 이미지 처리 및 분석 기술입니다.
코어 이미지를 사용해서 시스템에서 제공하거나 혹은 사용자가 지정한 다양한 필터를 사용하여 이미지를 처리하거나 필터를 연결하여 복잡한 효과를 만들 수 있습니다.

CIFilter

CIFilter는 코어 이미지에서 하나 이상의 입력 이미지를 처리하거나 새로운 이미지 데이터를 생성하여 이미지를 제작하는 이미지 프로세서입니다.

이미지를 처리하거나 필터 제너레이터를 만들거나, 또는 사용자 정의 필터를 작성할 때 내장된 코어 이미지 필터를 활용하려면 CIFilter 객체를 CIImage, CIContextCIColor와 같은 다른 코어 이미지 클래스와 함께 사용합니다.

CIImage의 처리는 CIContext 객체에서 이루어집니다.
CIContext는 생성하는 데 많은 비용이 들기 때문에 초기 설정 중에 생성하여 필요할 때마다 앱 전체에서 재사용하는 것이 좋습니다.

let context = CIContext()

이렇게 만들어 둔 CIContext는 후에 필터를 선택한 후에, 아래와 같이 원본 이미지에 필터를 적용하여 CGImage로 내보내는 등의 용도로 사용됩니다.

let cgImage = context.createCGImage(image, from: image.extent)

KVC 방식으로 필터 적용하기

일반적으로 CIFilter는 하나 이상의 이미지를 입력으로 받아 CIImage를 생성합니다.
하지만, 일부 필터는 다른 유형의 입력 매개변수를 기반으로 이미지를 생성하기도 합니다.
CIFilter 객체의 매개변수는 키-값(key-value)을 사용하여 설정 및 검색됩니다.

아래는 KVC(Key-Value Coding) 방식을 사용하여 SepiaTone 필터를 적용하는 함수의 예시입니다.

func sepiaFilter(\_ image: CIImage, intensity: Double) -> CIImage? {
let filter = CIFIlter(name: "CISepiaTone")
 
    filter?.setValue(image, forKey: kCIInputImageKey)
    filter?.setValue(intensity, forKey: kCIInputIntensityKey)
 
    return filter?.outputImage
 
}

이렇게 KVC 방식으로 필터를 적용할 수도 있지만, 이 경우 CIFilter의 name을 문자열로 직접 작성하므로 오타가 발생할 수도 있고, 어떤 키와 어떤 값을 사용할 수 있는지를 알기가 비교적 어렵습니다.

type-safe API 사용하여 필터 적용하기

코어 이미지에서는 위와 같이 문자열 기반 API에 의존할 때 발생할 수 있는 런타임 오류를 방지하기 위해 type-safe CIFIlter 인스턴스를 생성하는 메서드를 제공합니다.

type-safe API를 사용하려면 CoreImage.CIFIlterBuiltins를 import 해야 합니다.

import CoreImage
import CoreImage.CIFilterBuiltins

type-safe 접근 방식은 옵셔널이 아닌 필터를 반환합니다.
반환된 필터는 관련 프로토콜(예를 들어 sepiaTone()CISepiaTone)을 준수하므로 매개 변수를 프로퍼티로 사용할 수 있습니다.

아래의 코드는 위에서 KVC 방식을 사용하여 작성했던 SepiaTone 필터를 type-safe API를 사용하여 다시 작성한 함수 예시입니다.

func sepiaFilter(\_ image: CIImage, intensity: Float) -> CIImage? {
let filter = CIFilter.sepiaTone()
 
    filter.intensity = intensity
    filter.inputImage = image
 
    return filter?.outputImage
 
}

마무리

이번 시간에는 Core ImageCIFilter를 사용하여 사진에 시스템 필터 효과를 주는 방법에 대해 알아 보았습니다.

CIFilter는 위에서 설명한 sepiaTone 필터 뿐만 아니라 bokehBlur, boxBlur 등의 Blur Filter, gammaAdjust, toneCurve 등의 Color Adjustment Filter, colorInvert, falseColor` 등의 Color Effect Filter 등 다양한 종류의 필터를 사용할 수 있습니다.

더 다양한 필터는 아래의 필터 카테고리에서 각각의 카테고리 페이지를 참조하여 확인할 수 있습니다.

필터 카테고리

위에서 사용된 코드 및 간단한 예시 코드는 여기에서 확인하실 수 있습니다.

후기

사실 동영상에 필터를 적용하는 방법을 먼저 공부하기 시작했는데, 영상에 필터를 적용하는 방법을 작성하기에 앞서 사진에 적용하는 방법을 먼저 작성하고 싶어서 이렇게 정리해봤는데요.

공부할 때는 다양한 시스템 필터를 이렇게 저렇게 사용해보느라 시간이 오래 걸렸는데, 막상 글로 옮기면서 불필요하거나 중복되는 내용들을 다 잘라내고 주요 내용만 남기다보니 생각했던 것보단 글이 많이 짧다는 느낌이 드네요.

또, 처음에 작성할 때는 이 필터 저 필터에 대해 다 정리하다보니 사진도 많았었는데, 불필요한 내용을 삭제하다보니 사진이 하나도 남지 않게 된 부분도 많이 아쉽네요.

이렇게 시스템에서 제공하는 필터 말고도 더 다양한 효과에 대해서도 공부하고 있는데, 빠른 시간 내에 그 내용에 대해서도 작성할 수 있으면 좋겠습니다.

참고자료

댓글 및 반응

GitHub 계정으로 댓글을 남기거나 반응을 남길 수 있습니다