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

不同尺寸同图实现一致CIFilter高斯模糊效果的解决方法

问题根因

你遇到跨分辨率模糊效果不一致的核心原因有两个:

  1. 模糊半径的缩放逻辑写反了
    CIGaussianBlur的radius参数单位是像素,要实现跨分辨率视觉一致的模糊效果,模糊半径需要和图像的像素尺寸成正比缩放。你当前的实现里,预览小图时给半径乘了小于1的scaleFactor(预览图尺寸/原图尺寸)把半径缩小了,导出全尺寸图时却直接用原始滑块值当半径,相当于全尺寸图的模糊半径是预览图的1/scaleFactor倍,自然会比预览效果模糊得多。
  2. 前后处理逻辑不统一
    你在导出全尺寸图时给输入图像加了clampedToExtent()处理避免边缘暗边,但预览渲染时没有做相同处理,也会导致边缘模糊效果存在差异;另外缩放比例计算时没有考虑UIImage的屏幕缩放因子、像素/点单位差异,也会引入细微的效果偏差。

修正方案

按以下步骤调整代码即可实现完全一致的模糊效果:

  • 统一模糊半径的参考基准:把滑块的blurRadius直接定义为预览坐标系下的像素模糊半径,预览渲染时直接使用该值,不需要额外缩放
  • 导出全尺寸图时,按照「图像像素尺寸的缩放比例」等比例放大模糊半径,因为全尺寸图的像素尺寸是预览图的1/scaleFactor倍,对应模糊半径也要乘1/scaleFactor
  • 预览和导出两侧保持完全一致的输入预处理、输出裁剪逻辑
  • 缩放比例计算统一使用像素维度,避免点/像素单位混淆

修正后核心代码

模糊值变更回调

@objc func blurChanged(slider: UISlider) {
    blurRadius = slider.value
    // 和导出逻辑保持一致,先做边缘延伸处理避免暗边
    blurFilter.inputImage = previewCIImage.clampedToExtent()
    // 预览侧直接使用滑块值作为模糊半径
    blurFilter.radius = blurRadius
    MTKView.setNeedsDisplay()
}

全尺寸导出方法

func exportFullSizeImage() -> UIImage {
    let inputImage = CIImage(image: originalImage)!
            
    blurFilter.inputImage = inputImage.clampedToExtent()
    // 按像素比例放大模糊半径,保证视觉效果一致
    let scaledRadius = blurRadius / Float(scaleFactor)
    blurFilter.radius = scaledRadius
    // 裁剪回原图尺寸,避免clampedToExtent导致的画布无限延伸
    let output = blurFilter.outputImage!.cropped(to: inputImage.extent)
    let outputCGImage = context.createCGImage(output, from: output.extent)
    
    return UIImage(cgImage: outputCGImage!)
}

修正缩放比例计算(像素级对齐)

替换你原来的getScaleFactor方法,基于像素尺寸计算比例,避免屏幕缩放因子引入误差:

func getScaleFactor(targetSize: CGSize) -> CGFloat {
    // 预览尺寸转像素:乘屏幕缩放因子
    let previewPixelWidth = targetSize.width * UIScreen.main.scale
    let previewPixelHeight = targetSize.height * UIScreen.main.scale
    // 原图尺寸转像素:乘UIImage自身的scale属性
    let originalPixelWidth = size.width * scale
    let originalPixelHeight = size.height * scale
    
    let widthRatio = previewPixelWidth / originalPixelWidth
    let heightRatio = previewPixelHeight / originalPixelHeight
    return min(widthRatio, heightRatio)
}

调整完成后,可以把导出的全尺寸图缩小到预览图尺寸做叠放对比,两者的模糊程度、边缘效果会完全对齐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:18:40