news 2026/9/13 4:28:51

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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

如果你手里已经有一个现成的CIFilter(CoreImage 滤镜),想在图片下载完成后自动应用它,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并返回outputImage

struct 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)时闭包返回nil
  • identifier文档建议采用反向域名格式(见 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.md):

let 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”)。具体到CIImageProcessor,Filter.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 } // ... }

据此可以判断三种情况:

  1. 滤镜正常生效:视图中显示的是滤镜处理后的图片,且处理结果以identifier参与缓存键写入缓存。
  2. CIFilter(name:)名字写错:闭包中guard不通过、返回nilapply会原样返回base——视图显示未处理的原图,而不是报错中断。
  3. 输入不是 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 图片生效,转换失败(滤镜返回nilCIContext渲染失败)时返回原图而不是抛出错误,调试时若发现“滤镜没生效”,优先检查滤镜名称和输入图片类型这两点。
  • 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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 4:27:10

260+国旗Sketch素材包:从Symbol命名到批量导出与校验

简介:面向UI设计师与产品经理,这份《全球国旗图标集》汇集了260多个国家与地区的矢量国旗素材,以Sketch格式呈现,可直接用于移动应用、网站界面、地理信息系统、国际会议展示等场景,免去逐个绘制的重复劳动。压缩包大小…

作者头像 李华
网站建设 2026/9/13 4:21:02

AI工具全解析:从写作到编程的智能助手应用

1. AI工具全景概览:从写作到编程的全能助手AI工具正在重塑我们的工作方式。从文字创作到图像生成,从视频剪辑到代码编写,各类AI工具已经渗透到专业领域的每个角落。根据最新统计,目前市场上活跃的AI工具已超过1000种,涵…

作者头像 李华