如何在 Swift UI 中将滤色器应用到异步图像?

问题描述 投票:0回答:1

我不知道如何动态过滤(滤色器)正在加载的图像。例如我想动态增加饱和度。

在 SwiftUI 中过滤图像看起来直接使用 [

CI library
] (https://www.hackingwithswift.com/books/ios-swiftui/basic-image-filtering-using-core-image)。

但是我无法弄清楚如何从要操作的异步图像中获取核心图像对象。

我想象它的工作原理是这样的:

AsyncImage(url: URL(string: "https://example.com/icon.png")) { image in
    Image(uiImage: myFilter(image.uiImage.ciImage).uiImage).resizable()
} placeholder: {
    ProgressView()
}
.frame(width: 50, height: 50)

或者也许图像可以扩展?

swift swiftui uiimage core-image ciimage
1个回答
1
投票

AsyncImage
无法给您
UIImage
,但编写自己的
AsyncImage
并为您提供
UIImage
相对容易。

struct AsyncUIImage<Content: View, Placeholder: View>: View {
    let url: URL
    let contentBuilder: (UIImage) -> Content
    let placeholder: Placeholder
    
    @State private var content: Content?
    
    init(url: URL, @ViewBuilder content: @escaping (UIImage) -> Content, @ViewBuilder placeholder: () -> Placeholder) {
        self.url = url
        self.contentBuilder = content
        self.placeholder = placeholder()
    }
    
    var body: some View {
        if let content {
            content
        } else {
            placeholder
                .task {
                    do {
                        let (data, _) = try await URLSession.shared.data(from: url)
                        if let uiImage = UIImage(data: data) {
                            content = contentBuilder(uiImage)
                        }
                    } catch {
                        print(error)
                    }
                }
        }
    }
}

使用示例:

var body: some View {
    AsyncUIImage(url: URL(string: "https://picsum.photos/200")!) { uiImage in
        VStack {
            if let ciImage = CIImage(image: uiImage) {
                processImage(ciImage)
            }
            Image(uiImage: uiImage)
        }
    } placeholder: {
        ProgressView()
    }

}

func processImage(_ ciImage: CIImage) -> Image? {
    let context = CIContext()
    let filter = CIFilter.sepiaTone()
    filter.inputImage = ciImage
    filter.intensity = 1
    guard let output = filter.outputImage else { return nil }
    guard let cgImage = context.createCGImage(output, from: output.extent) else { return nil }
    return Image(uiImage: UIImage(cgImage: cgImage))
}

另请注意,某些

CIFilter
的效果可以使用 SwiftUI 视图修饰符来实现,例如
blur
colorInvert
hueRotation
等。对于这些滤镜,您只需将它们应用到
 Image
AsyncImage
制作。

© www.soinside.com 2019 - 2024. All rights reserved.