ylliX - Online Advertising Network

How to get UIImage from OpenGL in Swift 3

As you probably notices, simple screen drawing is useless if it comes to OpenGL view. So is it possible to generate UIImage from such? Of course, lets suppose your custom drawing class extends UIView, then just add:

func getSnapshot() -> UIImage? {
    
    let s = CGRect(x: 0.0, y: 0.0, width: self.bounds.width, height: self.bounds.height)
    let dataLength = Int(s.size.width * s.size.height * 4.0)
    let buffer: UnsafeMutableRawPointer? = malloc(dataLength)
    glReadPixels(0, 0, GLsizei(s.size.width), GLsizei(s.size.height), GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), buffer);
    
    let pixelData: UnsafePointer = (UnsafeRawPointer(buffer)?.assumingMemoryBound(to: UInt8.self))!
    let cfdata: CFData = CFDataCreate(kCFAllocatorDefault, pixelData, dataLength * MemoryLayout<GLubyte>.size)

    let provider: CGDataProvider! = CGDataProvider(data: cfdata)
    
    let iref: CGImage? = CGImage(width: Int(s.size.width), height: Int(s.size.height), bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: Int(s.size.width)*4, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGBitmapInfo.byteOrder32Big, provider: provider, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)

    UIGraphicsBeginImageContext(CGSize(width: CGFloat(s.size.width), height: CGFloat(s.size.height)))
    let cgcontext: CGContext? = UIGraphicsGetCurrentContext()
    cgcontext!.setBlendMode(CGBlendMode.copy)
    cgcontext!.draw(iref!, in: CGRect(x: CGFloat(0.0), y: CGFloat(0.0), width: CGFloat(s.size.width), height: CGFloat(s.size.height)))
    let image: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    return image
}

This code works in XCode 9 and Swift 3.x.

Leave a Reply