Skip to content

Instantly share code, notes, and snippets.

@muukii
Created September 28, 2015 05:32
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save muukii/fbb523538e14bc4c75a2 to your computer and use it in GitHub Desktop.
Save muukii/fbb523538e14bc4c75a2 to your computer and use it in GitHub Desktop.
CIImageView (Using Metal)
//
// MTKCIImageView.swift
// Fil
//
// Created by Muukii on 9/27/15.
// Copyright © 2015 muukii. All rights reserved.
//
import Foundation
import Metal
import MetalKit
class MTKCIImageView: MTKView {
var image: CIImage? {
didSet {
self.draw()
}
}
var originalImageExtent: CGRect = CGRect.zero {
didSet {
}
}
var scale: CGFloat {
return max(self.frame.width / originalImageExtent.width, self.frame.height / originalImageExtent.height)
}
func update() {
guard let img = image where destRect.size.width <= img.extent.size.width && destRect.size.height <= img.extent.size.height else {
return
}
self.draw()
}
let context: CIContext
let commandQueue: MTLCommandQueue
convenience init(frame: CGRect) {
let device = MTLCreateSystemDefaultDevice()
self.init(frame: frame, device: device)
}
override init(frame frameRect: CGRect, device: MTLDevice?) {
guard let device = device else {
fatalError("Can't use Metal")
}
commandQueue = device.newCommandQueueWithMaxCommandBufferCount(5)
context = CIContext(MTLDevice: device, options: [kCIContextUseSoftwareRenderer:false])
super.init(frame: frameRect, device: device)
self.framebufferOnly = false
self.enableSetNeedsDisplay = false
self.paused = true
self.clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 0)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func drawRect(rect: CGRect) {
JEDump(rect, "Draw Use Metal")
guard let image = self.image else {
return
}
let dRect = destRect
let drawImage: CIImage
if dRect == image.extent {
drawImage = image
} else {
let scale = max(dRect.height / image.extent.height, dRect.width / image.extent.width)
drawImage = image.imageByApplyingTransform(CGAffineTransformMakeScale(scale, scale))
}
let commandBuffer = commandQueue.commandBufferWithUnretainedReferences()
guard let texture = self.currentDrawable?.texture else {
return
}
guard let colorSpace = drawImage.colorSpace ?? CGColorSpaceCreateDeviceRGB() else {
return
}
context.render(drawImage, toMTLTexture: texture, commandBuffer: commandBuffer, bounds: dRect, colorSpace: colorSpace)
commandBuffer.presentDrawable(self.currentDrawable!)
commandBuffer.commit()
}
private var destRect: CGRect {
let scale: CGFloat
if UIScreen.mainScreen().scale == 3 {
// BUG?
scale = 2.0 * (2.0 / UIScreen.mainScreen().scale) * 2
} else {
scale = UIScreen.mainScreen().scale
}
let destRect = CGRectApplyAffineTransform(self.bounds, CGAffineTransformMakeScale(scale, scale))
return destRect
}
}
@satishVekariya
Copy link

Hi, i get orientation and flip issue in simulator. same like: https://stackoverflow.com/questions/60164536/flipped-picture-after-render-in-metal

@satishVekariya
Copy link

Any solution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment