Skip to content

Instantly share code, notes, and snippets.

@christianselig
Created February 29, 2024 23:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save christianselig/ef0a05c73d88c678fee0cf54b8b9b4d0 to your computer and use it in GitHub Desktop.
Save christianselig/ef0a05c73d88c678fee0cf54b8b9b4d0 to your computer and use it in GitHub Desktop.
import UIKit
import MetalKit
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let imageView = UIImageView(image: UIImage(named: "landscape.jpeg"))
imageView.frame = CGRect(x: 0, y: 200, width: 350, height: 197)
view.addSubview(imageView)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3)) {
// CARenderer outputs 350 🤕
let texture = imageView.snapshot(device: MTLCreateSystemDefaultDevice()!)!
print(texture.width)
let image = UIImage(ciImage: CIImage(mtlTexture: texture)!)
print(image.size.width * image.scale)
// UIView.drawHierarchy outputs 1,050 as expected 🥳
let rendererFormat = UIGraphicsImageRendererFormat.default()
rendererFormat.opaque = true
let renderer = UIGraphicsImageRenderer(size: imageView.bounds.size, format: rendererFormat)
let image2 = renderer.image { context in
imageView.drawHierarchy(in: imageView.bounds, afterScreenUpdates: false)
}
print(image2.size.width * image2.scale)
}
}
}
extension UIView {
func snapshot(device: MTLDevice) -> MTLTexture? {
let width = Int(bounds.width)
let height = Int(bounds.height)
let desc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .rgba8Unorm, width: width, height: height, mipmapped: false)
desc.usage = [.renderTarget, .shaderRead, .shaderWrite]
let texture = device.makeTexture(descriptor: desc)!
let renderer = CARenderer(mtlTexture: texture)
renderer.layer = layer
renderer.bounds = CGRect(x: 0, y: 0, width: width, height: height)
CATransaction.flush()
renderer.beginFrame(atTime: CACurrentMediaTime(), timeStamp: nil)
renderer.addUpdate(CGRect(x: 0, y: 0, width: width, height: height))
renderer.render()
renderer.endFrame()
return texture
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment