Last active
November 14, 2024 13:22
-
-
Save hanrw/20ce624888ebc1cceef75c1f19f518dd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func mosaicRectangles(in image: UIImage, from quadrilaterals: [QuadrilateralBox]) -> [QuadrilateralBox: UIImage] { | |
var resultMap: [QuadrilateralBox: UIImage] = [:] | |
guard var ciImage = CIImage(image: image) else { | |
print("Couldn't create CIImage.") | |
return resultMap | |
} | |
// Correct the orientation because `CIImage.init` can lose it | |
ciImage = ciImage.oriented(forExifOrientation: Int32(image.imageOrientation.rawValue)) | |
let ciContext = CIContext(options: nil) | |
for quad in quadrilaterals { | |
// Create a CGPath representing the quadrilateral | |
let path = CGMutablePath() | |
path.move(to: quad.topLeft.asCGPoint) | |
path.addLine(to: quad.topRight.asCGPoint) | |
path.addLine(to: quad.bottomRight.asCGPoint) | |
path.addLine(to: quad.bottomLeft.asCGPoint) | |
path.closeSubpath() | |
// Calculate the bounding box of the quadrilateral | |
let boundingBox = path.boundingBoxOfPath | |
// Create a mask image for the quadrilateral | |
UIGraphicsBeginImageContext(ciImage.extent.size) | |
if let context = UIGraphicsGetCurrentContext() { | |
context.addPath(path) | |
context.setFillColor(UIColor.white.cgColor) | |
context.fillPath() | |
} | |
guard let maskUIImage = UIGraphicsGetImageFromCurrentImageContext() else { | |
UIGraphicsEndImageContext() | |
continue | |
} | |
UIGraphicsEndImageContext() | |
guard let maskCIImage = CIImage(image: maskUIImage) else { | |
continue | |
} | |
// Apply the mask to only the relevant part of the image | |
let maskCropped = maskCIImage.cropped(to: boundingBox) | |
let ciImageCropped = ciImage.cropped(to: boundingBox) | |
let pixelationScale: CGFloat = 20.0 | |
let pixelatedImage = ciImageCropped | |
.applyingFilter("CIPixellate", parameters: [kCIInputScaleKey: pixelationScale]) | |
let resultImage = pixelatedImage.applyingFilter("CIBlendWithMask", parameters: [ | |
kCIInputBackgroundImageKey: ciImageCropped, | |
kCIInputMaskImageKey: maskCropped | |
]) | |
if let cgImage = ciContext.createCGImage(resultImage, from: boundingBox) { | |
let resultUIImage = UIImage(cgImage: cgImage) | |
resultMap[quad] = resultUIImage | |
} | |
} | |
return resultMap | |
} |
Author
hanrw
commented
Nov 14, 2024
func blurRectangles(in image: UIImage, from quadrilaterals: [QuadrilateralBox]) -> UIImage? {
guard var ciImage = CIImage(image: image) else {
print("Couldn't create CIImage.")
return nil
}
// correct the orientation becuase `CIImage.init` can lose it
ciImage = ciImage.oriented(forExifOrientation: Int32(image.imageOrientation.rawValue))
let ciContext = CIContext(options: nil)
var maskCanvasImage = CIImage.empty().cropped(to: ciImage.extent)
for quad in quadrilaterals {
// Create a CGPath representing the quadrilateral
let path = CGMutablePath()
path.move(to: quad.topLeft.asCGPoint)
path.addLine(to: quad.topRight.asCGPoint)
path.addLine(to: quad.bottomRight.asCGPoint)
path.addLine(to: quad.bottomLeft.asCGPoint)
path.closeSubpath()
// Draw the path into a CIImage
UIGraphicsBeginImageContext(ciImage.extent.size)
if let context = UIGraphicsGetCurrentContext() {
context.addPath(path)
context.setFillColor(UIColor.white.cgColor)
context.fillPath()
}
guard let maskUIImage = UIGraphicsGetImageFromCurrentImageContext() else {
UIGraphicsEndImageContext()
continue
}
UIGraphicsEndImageContext()
guard let maskCIImage = CIImage(image: maskUIImage) else {
continue
}
// Composite this mask over the existing canvas
maskCanvasImage = maskCIImage.composited(over: maskCanvasImage)
}
let blurRadius: Double = 30.0
let blurredImage = ciImage
.clampedToExtent()
.applyingGaussianBlur(sigma: blurRadius)
.cropped(to: ciImage.extent)
let resultImage = blurredImage.applyingFilter("CIBlendWithMask", parameters: [
kCIInputBackgroundImageKey: ciImage,
kCIInputMaskImageKey: maskCanvasImage
])
if let cgImage = ciContext.createCGImage(resultImage, from: resultImage.extent) {
return UIImage(cgImage: cgImage)
}
return nil
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment