I'm building a photo editor and to keep a good performance I filter a small version of the image first and when the user wants to export it, then I filter the higher resolution image.
I'm using CIGaussianBlur filter but I can't achieve same results for different images resolutions.
This is my code:
class ViewController : UIViewController {
var originalImage = UIImage()
var previewImageView = UIImageView()
var previewCIImage: CIImage!
var scaleFactor = CGFloat()
let blurFilter = CIFilter.gaussianBlur()
var blurSlider = UISlider()
var blurRadius = Float()
override func viewDidLoad() {
previewImageView.image = originalImage.scalePreservingAspectRatio(targetSize: previewImageView.frame.size)
previewCIImage = CIImage(image: previewImageView.image!)
// Get the scale factor
scaleFactor = originalImage.getScaleFactor(targetSize: previewImageView.frame.size)
blurSlider.addTarget(self, action: #selector(blurChanged(slider:)), for: .valueChanged)
}
@objc func blurChanged(slider: UISlider) {
blurRadius = slider.value
let scaledRadius = blurRadius * Float(scaleFactor)
blurFilter.radius = scaledRadius
MTKView.setNeedsDisplay()
}
func exportFullSizeImage() -> UIImage {
let inputImage = CIImage(image: originalImage)!
blurFilter.inputImage = inputImage.clampedToExtent()
// Assuming scaleFactor is 1.0 for the unscaled image
let scaledRadius = blurRadius * 1.0
blurFilter.radius = scaledRadius
let output = (blurFilter.outputImage)!
let outputCGImage = context.createCGImage(output, from: output.extent)
return UIImage(cgImage: outputCGImage!)
}
}
extension UIImage {
func scalePreservingAspectRatio(targetSize: CGSize) -> UIImage {
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
let scaleFactor = min(widthRatio, heightRatio)
let scaledImageSize = CGSize(
width: size.width * scaleFactor,
height: size.height * scaleFactor
)
let renderer = UIGraphicsImageRenderer(
size: scaledImageSize
)
let scaledImage = renderer.image { _ in
self.draw(in: CGRect(
origin: .zero,
size: scaledImageSize
))
}
return scaledImage
}
func getScaleFactor(targetSize: CGSize) -> CGFloat {
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
let scaleFactor = min(widthRatio, heightRatio)
return scaleFactor
}
}
Here's the output of the small version of the image (preview image):
And here's the output of the full size image (unscaled image):
The results are clearly different, the full size/unscaled image has more blur. I need to achieve the same blur effect on both images.
I've found two similar questions: Output of CIFilter has different effect for different sizes of same image and How to achieve same CIFilter effect on multiple sizes of same image
I know the scale factor of the resized image, that's maybe useful to get an answer.

