Skip to content

Instantly share code, notes, and snippets.

@steipete
Created August 13, 2011 20:52
Show Gist options
  • Save steipete/1144242 to your computer and use it in GitHub Desktop.
Save steipete/1144242 to your computer and use it in GitHub Desktop.
Preload UIImage for super-smooth interaction. especially great if you use JPGs, which otherwise produce a noticeable lag on the main thread.
- (UIImage *)pspdf_preloadedImage {
CGImageRef image = self.CGImage;
// make a bitmap context of a suitable size to draw to, forcing decode
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef imageContext = CGBitmapContextCreate(NULL, width, height, 8, width*4, colourSpace,
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
CGColorSpaceRelease(colourSpace);
// draw the image to the context, release it
CGContextDrawImage(imageContext, CGRectMake(0, 0, width, height), image);
// now get an image ref from the context
CGImageRef outputImage = CGBitmapContextCreateImage(imageContext);
UIImage *cachedImage = [UIImage imageWithCGImage:outputImage];
// clean up
CGImageRelease(outputImage);
CGContextRelease(imageContext);
return cachedImage;
}
@mickeyl
Copy link

mickeyl commented Apr 10, 2017

Any idea whether this applies to watchOS as well?

@lastcc
Copy link

lastcc commented Jul 20, 2017

ah... why apple don't let us:

let image = UIImage(...)

image.prepareForRenderingAsynchronously = true

@dannofx
Copy link

dannofx commented Aug 2, 2017

Thanks for the snippet!
Swift 3 version:

import UIKit

extension UIImage {
    
    func forceLoad() -> UIImage {
        guard let imageRef = self.cgImage else {
            return self //failed
        }
        let width = imageRef.width
        let height = imageRef.height
        let colourSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo: UInt32 = CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
        guard let imageContext = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: width * 4, space: colourSpace, bitmapInfo: bitmapInfo) else {
            return self //failed
        }
        let rect = CGRect(x: 0, y: 0, width: width, height: height)
        imageContext.draw(imageRef, in: rect)
        if let outputImage = imageContext.makeImage() {
            let cachedImage = UIImage(cgImage: outputImage)
            return cachedImage
        }
        return self //failed
    }
    

}

@v57
Copy link

v57 commented Mar 8, 2018

Pls don't forget to add old image orientation with:
let cachedImage = UIImage(cgImage: outputImage, scale: scale, orientation: imageOrientation)

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