I have a sequence of images that I want to animate (UIImageView
supports some basic animation but it's not sufficient for my needs).
My first approach was to use UIImageView
and set the image
property when the image. This was too slow. The reason for the poor speed was due to the drawing of the images (which surprised me; I assumed the bottle neck would be loading the image).
My second approach was to use a generic UIView
and set view.layer.contents = image.CGImage
. This gave no noticeable improvement.
Both of these approaches must be performed on the main thread. I think the poor speed is due to having to draw the image data to a CGContext
.
How can I improve the drawing speed? Is it possible draw to the context on a background thread?
I managed to improve performance by doing a few things:
I fixed my build process so that the PNGs were being iOS optimized. (The content for the app is being managed in a separate project which outputs a bundle. The default bundle settings are for an OS X bundle, which does not optimize PNGs).
On a background thread I:
layer.content
on the main thread to the CGImageRefUsed an NSOperationQueue
to manage the operations.
I'm sure there's a better way of doing this, but the above results in acceptable performance.
-(CGImageRef)newCGImageRenderedInBitmapContext //this is a category on UIImage
{
//bitmap context properties
CGSize size = self.size;
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * size.width;
NSUInteger bitsPerComponent = 8;
//create bitmap context
unsigned char *rawData = malloc(size.height * size.width * 4);
memset(rawData, 0, size.height * size.width * 4);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(rawData, size.width, size.height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
//draw image into bitmap context
CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), self.CGImage);
CGImageRef renderedImage = CGBitmapContextCreateImage(context);
//tidy up
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
free(rawData);
//done!
//Note that we're not returning an autoreleased ref and that the method name reflects this by using 'new' as a prefix
return renderedImage;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With