为何CIFilter.differenceBlendMode与View的blendMode表现不一致?
问题:CIFilter.differenceBlendMode与SwiftUI blendMode效果不一致,原因是什么?
测试代码
struct ContentView: View { var processed: CIImage { let filter = CIFilter.differenceBlendMode() filter.inputImage = UIImage(resource: .image).cgImage.map({CIImage(cgImage: $0)}) filter.backgroundImage = UIImage(resource: .whiteBg).cgImage.map({CIImage(cgImage: $0)}) return filter.outputImage! } var body: some View { VStack(spacing: 0) { Image(ciImage: processed) .resizable() .scaledToFit() Image(.image) .resizable() .scaledToFit() .blendMode(.difference) } } }
运行效果

运行此代码会生成两张不同的图像。
问题原因与解决方法
该滤镜缺少坐标系修正的设置。
CIImage的坐标系原点在左下角,而SwiftUI的Image视图采用UIKit的坐标系(原点在左上角)。直接将UIImage转成CIImage后使用滤镜,会导致图像上下翻转,和SwiftUI原生blendMode的效果产生差异。
修正后的代码如下:
struct ContentView: View { var processed: CIImage { guard let inputCGImage = UIImage(resource: .image).cgImage, let backgroundCGImage = UIImage(resource: .whiteBg).cgImage else { fatalError("图片加载失败") } let inputImage = CIImage(cgImage: inputCGImage) let backgroundImage = CIImage(cgImage: backgroundCGImage) // 添加翻转变换匹配坐标系 let flippedInput = inputImage.transformed(by: CGAffineTransform(scaleX: 1, y: -1)) let flippedBackground = backgroundImage.transformed(by: CGAffineTransform(scaleX: 1, y: -1)) let filter = CIFilter.differenceBlendMode() filter.inputImage = flippedInput filter.backgroundImage = flippedBackground // 输出后翻转回原坐标系 return filter.outputImage!.transformed(by: CGAffineTransform(scaleX: 1, y: -1)) } var body: some View { VStack(spacing: 0) { Image(ciImage: processed) .resizable() .scaledToFit() Image(.image) .resizable() .scaledToFit() .blendMode(.difference) } } }
内容的提问来源于stack exchange,提问作者Kyle Fang
相关产品推荐
相关产品推荐

