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

为何为CIMaskedVariableBlur添加CILinearGradient后UIImageView图像缩小?

问题解决:应用CIMaskedVariableBlur后图像缩小

图像缩小的核心原因有两个:

  • 从CIImage转换回UIImage时未保留原图像的缩放比例(scale)和方向(orientation)
  • 渐变滤镜未指定与原图像匹配的范围(extent),可能导致蒙版尺寸不匹配

修复步骤:

  1. 保留原图像的scale和orientation:创建最终UIImage时,传入原图像的scale和orientation参数,确保渲染时使用正确的像素密度。
  2. 设置渐变滤镜的extent:为CILinearGradient滤镜指定与输入图像相同的范围,保证蒙版尺寸与原图像一致。
  3. 使用CIContext渲染图像:直接通过CIContext将CIImage转为CGImage,再创建UIImage,避免UIImage(ciImage:)的潜在渲染问题。

修正后的代码:

self.view.addSubview(imageView)
imageView.contentMode = .scaleAspectFill
imageView.layer.masksToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
imageView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 270).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 480).isActive = true

if let uiImage = UIImage(named: "Image"), let ciImage = CIImage(image: uiImage) {
    let imageExtent = ciImage.extent
    let h = imageExtent.size.height
    
    guard let topGradient = CIFilter(name:"CILinearGradient") else {
        return
    }
    topGradient.setValue(CIVector(x:0, y:0.85 * h), forKey:"inputPoint0")
    topGradient.setValue(CIColor.green, forKey:"inputColor0")
    topGradient.setValue(CIVector(x:0, y:0.6 * h), forKey:"inputPoint1")
    topGradient.setValue(CIColor(red:0, green:1, blue:0, alpha:0), forKey:"inputColor1")
    topGradient.setValue(CIVector(ciImage: ciImage), forKey: "inputExtent") // 设置渐变范围
    
    guard let bottomGradient = CIFilter(name:"CILinearGradient") else {
        return
    }
    bottomGradient.setValue(CIVector(x:0, y:0.35 * h), forKey:"inputPoint0")
    bottomGradient.setValue(CIColor.green, forKey:"inputColor0")
    bottomGradient.setValue(CIVector(x:0, y:0.6 * h), forKey:"inputPoint1")
    bottomGradient.setValue(CIColor(red:0, green:1, blue:0, alpha:0), forKey:"inputColor1")
    bottomGradient.setValue(CIVector(ciImage: ciImage), forKey: "inputExtent") // 设置渐变范围
    
    guard let gradientMask = CIFilter(name:"CIAdditionCompositing") else {
        return
    }
    gradientMask.setValue(topGradient.outputImage, forKey: kCIInputImageKey)
    gradientMask.setValue(bottomGradient.outputImage, forKey: kCIInputBackgroundImageKey)
    
    guard let maskedVariableBlur = CIFilter(name:"CIMaskedVariableBlur") else {
        return
    }
    maskedVariableBlur.setValue(ciImage, forKey: kCIInputImageKey)
    maskedVariableBlur.setValue(gradientMask.outputImage, forKey: "inputMask")
    
    if let selectivelyFocusedCIImage = maskedVariableBlur.outputImage {
        // 使用CIContext渲染并保留原图像的scale和orientation
        let context = CIContext(options: [.useSoftwareRenderer: false])
        if let cgImage = context.createCGImage(selectivelyFocusedCIImage, from: imageExtent) {
            let finalImage = UIImage(cgImage: cgImage, scale: uiImage.scale, orientation: uiImage.imageOrientation)
            imageView.image = finalImage
        }
    }
}

关键说明:

  • inputExtent:确保渐变滤镜生成的蒙版尺寸与原图像完全一致,避免蒙版缩放导致的图像变形。
  • CIContext渲染:相比直接使用UIImage(ciImage:),通过CGImage转换能更可靠地控制渲染结果,尤其是在多滤镜组合场景下。
  • scale和orientation:原图像的scale(如2x、3x)决定了像素密度,保留该参数可避免图像在Retina屏幕上被错误缩放。

内容的提问来源于stack exchange,提问作者yilmazburk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:59:56