Untitled
unknown
plain_text
2 years ago
3.9 kB
5
Indexable
// // Viewfinder.swift // Roll // // Created by Rasmus Nielsen on 29/06/2023. // import AVKit import MetalKit import CoreImage import CoreImage.CIFilterBuiltins import Photos class Viewfinder: MTKView { // https://developer.apple.com/wwdc20/10008 lazy var commandQueue = device!.makeCommandQueue()! lazy var context = CIContext( mtlCommandQueue: commandQueue, options: [ .name : "FilterContext", .cacheIntermediates: false ] ) lazy var renderDestination = CIRenderDestination( width: Int(drawableSize.width), height: Int(drawableSize.height), pixelFormat: colorPixelFormat, commandBuffer: nil, mtlTextureProvider: { self.currentDrawable!.texture } ) /// Current image to show as preview var image: CIImage? /// Filter applied to `image` var filter: CIFilter? override init(frame frameRect: CGRect, device: MTLDevice?) { super.init(frame: frameRect, device: device) framebufferOnly = false backgroundColor = .clear delegate = self } required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension Viewfinder: MTKViewDelegate { func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { // Todo } func draw(in view: MTKView) { guard let view = view as? Viewfinder, let image = view.image, let drawable = view.currentDrawable, let buffer = view.commandQueue.makeCommandBuffer() else { return } do { try view.context.startTask( toRender: image, to: view.renderDestination ) buffer.present(drawable) buffer.commit() } catch { print(error.localizedDescription) } } } extension Viewfinder: AVCaptureVideoDataOutputSampleBufferDelegate { func captureOutput( _ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection ) { guard let imageBuffer = sampleBuffer.imageBuffer else { // Could not get an image buffer return } // Get a CI Image let sampleImage = CIImage(cvImageBuffer: imageBuffer) // Get the original size of the image let originalSize = sampleImage.extent.size // A rect with our frame's aspect ratio that fits in the viewfinder let targetRect = AVMakeRect( aspectRatio: originalSize, insideRect: CGRect( origin: .zero, size: drawableSize ) ) // A transform to size our frame to targetRect let scale = CGAffineTransform( scaleX: targetRect.size.width / originalSize.width, y: targetRect.size.height / originalSize.height ) // A transform to center our frame within the viewfinder let translate = CGAffineTransform( translationX: targetRect.origin.x, y: targetRect.origin.y ) // Apply a filter filter?.setValue(sampleImage.clampedToExtent(), forKey: kCIInputImageKey) // Apply the transforms to the image let scaledImage = (filter?.outputImage ?? sampleImage) .cropped(to: sampleImage.extent) .transformed(by: scale.concatenating(translate)) // Set the image on the viewfinder image = scaledImage } func captureOutput(_ output: AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { // print(#function) } }
Editor is loading...