원문
개요
이 글에서 이야기하는 Swift의 이미지에 그레이스케일 적용하는 세 가지 방법은 다음과 같습니다.
- 그레이스케일로 변환 가능하지만 화질을 유지하려면 시간이 걸리는
CIFilter
- 시간이 덜 걸리고 한 번에 여러 이미지에 적용할 수 있지만 투명한 요소(transparent elements)를 색상으로 바꾸는
CoreGraphics
필터 - Swift UI에서
View
에 그레이스케일 옵션 추가하기
첫 번째 방법 – CIFilter
이미지에 그레이스케일을 적용한다고 하면 이미지용 필터가 바로 떠오릅니다. 시중에 이미지에 필터를 적용할 수 있는 앱이 많이 있습니다. 그리고 이것이 Swift에서 그레이스케일을 사용하는 가장 일반적인 방법이기도 합니다.
이 경우 이미지에 효과와 필터를 추가하기 위해 만든 CIFilter
를 사용합니다. CIFilter
에는 iOS 사진 앱의 효과에 사용되는 CIPhotoEffectNoir
라는 구성 요소가 있습니다.
이미지에 적용할 수 있는 2가지 유사한 효과도 있습니다.
CIPhotoEffectMono
CIPhotoEffectTonal
따라서 이미지 품질을 손상시키지 않고 그레이스케일을 추가하려면 이 기능을 적용하면 됩니다.
func grayscale(image: UIImage, filterName: String = "CIPhotoEffectNoir") -> UIImage? { let context = CIContext(options: nil) if let filter = CIFilter(name: filterName) { filter.setValue(CIImage(image: image), forKey: kCIInputImageKey) if let output = filter.outputImage { if let cgImage = context.createCGImage(output, from: output.extent) { return UIImage(cgImage: cgImage) } } } return nil }
이 효과는 잘 작동하지만 모든 CIFilter
와 마찬가지로 문제는 소요 시간에 있습니다. CIPhotoEffectNoir
(또는 기타)로 이미지를 변경하는 데 몇 초가 걸립니다. CIFilter
가 이미지 품질을 유지하기 때문입니다. 따라서 한 번에 둘 이상의 이미지를 변환하려면 시간이 걸립니다.
두 번째 방법 – CGColorSpaceCreateDeviceGray
시간이 덜 걸리고 한 번에 둘 이상의 이미지에 대해 구현할 수 있는 또 다른 옵션은 CoreGraphics
입니다.
함수를 살펴보겠습니다.
func convertToGrayScale(image: UIImage) -> UIImage? { let imageRect: CGRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height) let colorSpace = CGColorSpaceCreateDeviceGray() let width = image.size.width let height = image.size.height let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue) let context = CGContext(data: nil, width: Int(width), height: Int(height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) if let cgImg = image.cgImage { context?.draw(cgImg, in: imageRect) if let makeImg = context?.makeImage() { let imageRef = makeImg let newImage = UIImage(cgImage: imageRef) return newImage } } return UIImage() }
훨씬 빠르게 작동하지만 한계도 있습니다. 투명 요소가 포함된 이미지에는 CGImageAlphaInfo.none
을 사용할 수 없습니다. 이는 모든 PNG가 투명도 없이 이미지로 변환된다는 것을 의미합니다. 이미지의 배경색을 지우면 검은색으로 바뀝니다.
이것은 색상을 교체하여 처리할 수도 있지만 이 글에서는 그레이스케일에만 초점을 맞추고 싶습니다.
세 번째 방법 – SwiftUI 전용
마지막으로 이미지를 그레이스케일로 변환하는 가장 간단한 방법을 보여 드리겠습니다. 이것은 SwiftUI에서만 작동하므로 스토리보드에서는 사용할 수 없습니다. View
에 grayscale
이라는 옵션을 추가하기만 하면 됩니다.
func grayscale(_ amount: Double) -> some View
여기서 “amount
“는 보기에 적용하려는 그레이스케일의 강도입니다. 이 옵션은 구현하기가 매우 쉽지만 이미지를 CGColorSpace
객체로 변환하는 것만큼 빠르게 작동하지 않는다는 점을 기억해야 합니다.
struct Saturation: View { var body: some View { HStack { ForEach(0..<6) { Color.red.frame(width: 60, height: 60, alignment: .center) .grayscale(Double($0) * 0.1999) .overlay(Text("\(Double($0) * 0.1999 * 100, specifier: "%.4f")%"), alignment: .bottom) .border(Color.gray) } } } }
0개의 댓글