How to render to offscreen bitmap then blit to screen using Core Graphics

前端 未结 4 1709
有刺的猬
有刺的猬 2020-12-15 19:51

I would like to render to an offscreen bitmap (or array of RGBA values) and then blit those to a UIView during in the view\'s drawRect function. I

相关标签:
4条回答
  • 2020-12-15 20:35

    For future reference, here is a full example in Swift 2.1 of rendering to an offscreen bitmap and displaying it on the screen.

    Note that once you have created the bitmap context you can keep drawing more content into it, and updating the view when you want. This is great if you want to do a lengthy drawing operation on a background thread and periodically show progress to the user.

    View Controller:

    import UIKit
    
    class ViewController: UIViewController {
        @IBOutlet var myView: MyView!
        var bitmapContext: CGContext?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            createBitmapContext()
            drawContentIntoBitmap()
            myView.update(from: bitmapContext)
            releaseBitmapContext()
        }
    
        func createBitmapContext() {
            bitmapContext = CGBitmapContextCreate(
                nil,                                                        // auto-assign memory for the bitmap
                Int (myView.bounds.width * UIScreen.mainScreen().scale),    // width of the view in pixels
                Int (myView.bounds.height * UIScreen.mainScreen().scale),   // height of the view in pixels
                8,                                                          // 8 bits per colour component
                0,                                                          // auto-calculate bytes per row
                CGColorSpaceCreateDeviceRGB(),                              // create a suitable colour space
                CGImageAlphaInfo.PremultipliedFirst.rawValue)               // use quartz-friendly byte ordering
        }
    
        func drawContentIntoBitmap() {
            CGContextScaleCTM(bitmapContext, UIScreen.mainScreen().scale, UIScreen.mainScreen().scale)  // convert to points dimensions
            CGContextSetStrokeColorWithColor (bitmapContext, UIColor.redColor().CGColor)
            CGContextSetLineWidth (bitmapContext, 5.0)
            CGContextStrokeEllipseInRect (bitmapContext, CGRectMake(50, 50, 100, 100))
        }
    
        func releaseBitmapContext() {
            bitmapContext = nil // in Swift, CGContext and CGColorSpace objects are memory managed by automatic reference counting
        }
    }
    

    Subclass of UIView:

    import UIKit
    
    class MyView: UIView {     
        var cgImage: CGImage?
    
        func update(from bitmapContext: CGContext?) {
            cgImage = CGBitmapContextCreateImage(bitmapContext)
            setNeedsDisplay()
        }
    
        override func drawRect(rect: CGRect) {
            let displayContext = UIGraphicsGetCurrentContext()
            CGContextDrawImage(displayContext, bounds, cgImage)
        }
    
    }
    
    0 讨论(0)
  • 2020-12-15 20:36

    You can use a CGBitmapContext. You can generate an image from a CGBitmapContext and draw it during your drawRect.

    0 讨论(0)
  • 2020-12-15 20:44

    Use CGDataProviderCreateWithData and CGImageCreate if you don't need the bitmap context and just want the CGImageRef.

    0 讨论(0)
  • 2020-12-15 20:47

    To render into an offscreen context and save it as a CGImageRef:

    void *bitmapData = calloc(height, bytesPerLine);
    CGContextRef offscreen = CGBitmapContextCreate(..., bitmapData, ...)
    // draw stuff into offscreen
    CGImageRef image = CGBitmapContextCreateImage(offscreen);
    CFRelease(offscreen);
    free(bitmapData);
    

    To draw it on the screen:

    - (void)drawRect:(CGRect)rect {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextDrawImage(context, rect, image);
    }
    

    You could also just save the image in the view's layer's contents property (view.layer.contents = image), or use a UIImageView.

    0 讨论(0)
提交回复
热议问题