为何为CIMaskedVariableBlur添加CILinearGradient后UIImageView图像缩小?
问题解决:应用CIMaskedVariableBlur后图像缩小
图像缩小的核心原因有两个:
- 从CIImage转换回UIImage时未保留原图像的缩放比例(scale)和方向(orientation)
- 渐变滤镜未指定与原图像匹配的范围(extent),可能导致蒙版尺寸不匹配
修复步骤:
- 保留原图像的scale和orientation:创建最终UIImage时,传入原图像的scale和orientation参数,确保渲染时使用正确的像素密度。
- 设置渐变滤镜的extent:为CILinearGradient滤镜指定与输入图像相同的范围,保证蒙版尺寸与原图像一致。
- 使用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
相关产品推荐
相关产品推荐

