Kingfisher 如何用 CIFilter 创建 CIImageProcessor 处理下载图片

发布时间:2026/9/13 4:29:28
Kingfisher 如何用 CIFilter 创建 CIImageProcessor 处理下载图片 Kingfisher 如何用 CIFilter 创建 CIImageProcessor 处理下载图片【免费下载链接】KingfisherA lightweight, pure-Swift library for downloading and caching images from the web.项目地址: https://gitcode.com/GitHub_Trending/ki/Kingfisher如果你手里已经有一个现成的CIFilterCoreImage 滤镜想在图片下载完成后自动应用它Kingfisher 提供了CIImageProcessor协议和Filter包装类型来承接这个需求你只需要把滤镜逻辑写成一个Transformer闭包再让一个类型实现CIImageProcessor通过options: [.processor(...)]传给setImage等加载方法处理后的图片就会显示在视图上并写入缓存。这一路径适用于 UIKit/AppKit 平台即非 watchOS 目标Filter.swift 整个文件被#if !os(watchOS)包裹且 ImageProcessor.swift 的文档注释明确说明 watchOS 不支持包含 filter 的处理器输入图片会原样返回。Filter 和 CIImageProcessor 各自负责什么两个类型的职责在 Filter.swift 中有明确定义Transformer是一个类型别名(CIImage) - CIImage?定义「一张CIImage如何转成另一张」。Filter是对Transformer的包装结构体通过Filter(transform:)初始化public struct Filter { let transform: Transformer /// Creates a Filter from a given Transformer. /// /// - Parameter transform: The value defines how a CIImage can be converted to another one. public init(transform: escaping Transformer) { self.transform transform } // ... }CIImageProcessor是继承自ImageProcessor的协议只要求提供一个filter属性public protocol CIImageProcessor: ImageProcessor { var filter: Filter { get } }协议扩展已经替你实现了process(item:options:)你不需要写处理逻辑本身extension CIImageProcessor { public func process(item: ImageProcessItem, options: KingfisherParsedOptionsInfo) - KFCrossPlatformImage? { switch item { case .image(let image): return image.kf.apply(filter) case .data: return (DefaultImageProcessor.default | self).process(item: item, options: options) } } }也就是说输入已经是图片时直接应用滤镜输入是原始数据时先用DefaultImageProcessor解码成图片再应用滤镜。第一步用 Filter 包装 CIFilter按照 CommonTasks_Processor.md 中 “Creating a processor from CIFilter” 一节Filter闭包内接收一个CIImage调用你的CIFilter并返回outputImagestruct MyCIFilter: CIImageProcessor { let identifier com.yourdomain.myCIFilter let filter Filter { input in guard let filter CIFilter(name: xxx) else { return nil } filter.setValue(input, forKey: kCIInputBackgroundImageKey) return filter.outputImage } }代码中有两处占位内容需要你替换后才能直接使用CIFilter(name: xxx)中的xxx替换为你实际要使用的 CoreImage 滤镜名称创建失败返回nil时闭包返回nilidentifier文档建议采用反向域名格式见 ImageProcessor.swift 中对identifier的说明并且不要用空字符串因为空字符串已被DefaultImageProcessor保留。除了自定义CIFilter(name:)Filter.swift 还内置了两个现成的Filter工厂如果你的需求是上色或调整色彩可以直接复用而不必手写滤镜// 用指定颜色给图片着色 let tintFilter: Filter Filter.tint(.red) // 亮度 / 对比度 / 饱和度 / EV 调整 let colorFilter: Filter Filter.colorControl( Filter.ColorElement(brightness: 0.0, contrast: 1.0, saturation: 1.1, inputEV: 0.0) )Filter.tint的实现展示了文档认可的滤镜写法用CIConstantColorGenerator生成颜色图再用CISourceOverCompositing叠加到输入图上最后cropped(to: input.extent)。第二步把 processor 传给加载方法processor 创建完成后通过.processor选项传给 Kingfisher 的加载 API写法与内置 processor 完全一致引自 CommonTasks_Processor.mdlet processor MyCIFilter() let url URL(string: https://example.com/my_image.png) imageView.kf.setImage(with: url, options: [.processor(processor)])其中https://example.com/my_image.png是文档中的示例 URL替换为你自己的图片地址即可。如果你想在这个滤镜之后再叠加其他处理比如圆角可以用|运算符组合 processor// 先过 CIFilter再裁圆角 let processor MyCIFilter() | RoundCornerImageProcessor(cornerRadius: 20) imageView.kf.setImage(with: url, options: [.processor(processor)])验证滤镜是否生效CommonTasks_Processor.md 给出的成功标准是图片设置流程会应用 processor处理后的图片被发送到视图上并以此存入缓存“The processed image will then be sent to the image view and stored in the cache”。具体到CIImageProcessorFilter.swift 中KingfisherWrapper.apply(_:)展示了失败时的可观察行为public func apply(_ filter: Filter) - KFCrossPlatformImage { guard let cgImage cgImage else { assertionFailure([Kingfisher] Tint image only works for CG-based image.) return base } let inputImage CIImage(cgImage: cgImage) guard let outputImage filter.transform(inputImage) else { return base } guard let result ciContext.value.createCGImage(outputImage, from: outputImage.extent) else { assertionFailure([Kingfisher] Can not make an tint image within context.) return base } // ... }据此可以判断三种情况滤镜正常生效视图中显示的是滤镜处理后的图片且处理结果以identifier参与缓存键写入缓存。CIFilter(name:)名字写错闭包中guard不通过、返回nilapply会原样返回base——视图显示未处理的原图而不是报错中断。输入不是 CG-based 图片会触发assertionFailure([Kingfisher] Tint image only works for CG-based image.)并返回原图。文档同时说明「Only CG-based images are supported」。另外identifier直接影响缓存命中CommonTasks_Processor.md 强调 “It is your responsibility to keep it the same for processors with the same properties/functionality”——属性相同的 processor 必须返回相同identifier否则同一张图会因键不同而无法复用缓存。限制watchOS 不可用Filter相关代码在非 watchOS 平台才编译watchOS 上含 filter 的处理器会直接返回输入图片。滤镜只对 CG-based 图片生效转换失败滤镜返回nil或CIContext渲染失败时返回原图而不是抛出错误调试时若发现“滤镜没生效”优先检查滤镜名称和输入图片类型这两点。identifier避免空字符串组合 processor|后的新 identifier 为\(self.identifier)|\(another.identifier)见 ImageProcessor.swift 中append(another:)的实现。深入阅读可以从 CommonTasks_Processor.md 的 “Creating your own processor” 一节继续了解不依赖Filter、直接实现ImageProcessor的完整写法。【免费下载链接】KingfisherA lightweight, pure-Swift library for downloading and caching images from the web.项目地址: https://gitcode.com/GitHub_Trending/ki/Kingfisher创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考