Skip to content

Instantly share code, notes, and snippets.

@JoshuaSullivan
Created May 28, 2024 14:46
Show Gist options
  • Save JoshuaSullivan/9730bba5336f41f2519ded4bf37bff8f to your computer and use it in GitHub Desktop.
Save JoshuaSullivan/9730bba5336f41f2519ded4bf37bff8f to your computer and use it in GitHub Desktop.
Metal-backed CoreImage Renderer
import UIKit
import CoreImage
import Metal
public class Renderer {
public enum Error: Swift.Error {
case failedToCreateRenderer
case infiniteRenderRect
case failedToRenderImage
}
/// Having access to this is useful if you want to use a MTKView to display the output.
public let queue: MTLCommandQueue
/// Does the rendering.
private let context: CIContext
public init() throws {
guard
let device = MTLCreateSystemDefaultDevice(),
let queue = device.makeCommandQueue()
else {
throw Error.failedToCreateRenderer
}
self.queue = queue
context = CIContext(mtlCommandQueue: queue)
}
/// Renders a CIImage using a GPU-backed CIContext.
///
/// - Parameter image: The `CIImage` to render.
/// - Parameter rect: The area of the image to render.
/// - Returns: A UIImage of the render.
///
/// - Throws: A `Renderer.Error` if the image failed to render or the image extent was infinite and no render rect was specified.
///
public func render(image: CIImage, inRect rect: CGRect? = nil) throws -> UIImage {
let renderRect = rect ?? image.extent
guard renderRect != .infinite else {
throw Error.infiniteRenderRect
}
guard let cgImage = context.createCGImage(image, from: renderRect) else {
throw Error.failedToRenderImage
}
return UIImage(cgImage: cgImage)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment