You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:42:45