Here is my code from Eugene's Blog(https://eugenebokhan.io/introduction-to-metal-compute-part-four)
public var cgImage: CGImage? {
let bytesPerRow = self.width * 4
let length = bytesPerRow * self.height
let rgbaBytes = UnsafeMutableRawPointer.allocate(byteCount: length, alignment: MemoryLayout<UInt8>.alignment)
defer {
rgbaBytes.deallocate()
}
let destinationRegion = MTLRegion(origin: .init(x: 0, y: 0, z: 0),
size: .init(width: self.width,
height: self.height,
depth: self.depth))
self.getBytes(rgbaBytes, bytesPerRow: bytesPerRow, from: destinationRegion, mipmapLevel: 0)
let colorScape = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageByteOrderInfo.order32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue)
guard let data = CFDataCreate(nil, rgbaBytes.assumingMemoryBound(to: UInt8.self), length),
let dataProvider = CGDataProvider(data: data),
let cgImage = CGImage(width: self.width,
height: self.height,
bitsPerComponent: 8,
bitsPerPixel: 32,
bytesPerRow: bytesPerRow,
space: colorScape,
bitmapInfo: bitmapInfo,
provider: dataProvider,
decode: nil,
shouldInterpolate: true,
intent: .defaultIntent)
else { return nil }
return cgImage
}