Skip to content

Instantly share code, notes, and snippets.

@ericleiyang
Created October 23, 2020 11:52
Show Gist options
  • Save ericleiyang/b0414e284db7e17e918d42ce5403e185 to your computer and use it in GitHub Desktop.
Save ericleiyang/b0414e284db7e17e918d42ce5403e185 to your computer and use it in GitHub Desktop.
import UIKit
import CoreImage
import Metal
import MetalKit
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var mtkView: MTKView!
// Metal resources
var device: MTLDevice!
var commandQueue: MTLCommandQueue!
var sourceTexture: MTLTexture!
// Core Image resources
var context: CIContext!
let filter = CIFilter(name: "CIGaussianBlur")!
let colorSpace = CGColorSpaceCreateDeviceRGB()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// UIBlurEffect
let blurEffect = UIBlurEffect(style: .light)
let blurEffectView = UIVisualEffectView()
blurEffectView.frame = CGRect(x: 0, y: 0, width: imageView.frame.width, height: 400)
blurEffectView.center = imageView.center
self.imageView.addSubview(blurEffectView)
UIView.animate(withDuration: 5) {
blurEffectView.effect = blurEffect
}
// CIFilter
let blurredRect = CGRect(x: 0,
y: imageView.center.y - 200,
width: imageView.frame.width,
height: 400)
let context = CIContext()
imageView.image = imageView.image?.blurredImage(with: context,
radius: 20,
atRect: blurredRect)
// Metal
device = MTLCreateSystemDefaultDevice()
commandQueue = device.makeCommandQueue()
let textureLoader = MTKTextureLoader(device: device)
sourceTexture = try! textureLoader.newTexture(cgImage: UIImage(named: "street.png")!.cgImage!)
let view = self.mtkView!
view.delegate = self
view.device = device
view.framebufferOnly = false
context = CIContext(mtlDevice: device)
}
}
extension ViewController: MTKViewDelegate {
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
}
func draw(in view: MTKView) {
if let currentDrawable = view.currentDrawable,
let commandBuffer = commandQueue.makeCommandBuffer() {
let inputImage = CIImage(mtlTexture: sourceTexture)!.oriented(.down)
filter.setValue(inputImage, forKey: kCIInputImageKey)
filter.setValue(10.0, forKey: kCIInputRadiusKey)
context.render(filter.outputImage!,
to: currentDrawable.texture,
commandBuffer: commandBuffer,
bounds: mtkView.bounds,
colorSpace: colorSpace)
commandBuffer.present(currentDrawable)
commandBuffer.commit()
}
}
}
extension UIImage {
func blurredImage(with context: CIContext, radius: CGFloat, atRect: CGRect) -> UIImage? {
guard let ciImg = CIImage(image: self) else { return nil }
let cropedCiImg = ciImg.cropped(to: atRect)
let blur = CIFilter(name: "CIGaussianBlur")
blur?.setValue(cropedCiImg, forKey: kCIInputImageKey)
blur?.setValue(radius, forKey: kCIInputRadiusKey)
if let ciImgWithBlurredRect = blur?.outputImage?.composited(over: ciImg),
let outputImg = context.createCGImage(ciImgWithBlurredRect, from: ciImgWithBlurredRect.extent) {
return UIImage(cgImage: outputImg)
}
return nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment