In my app I need to load large JPEG images and display them in a scroll view. In order to keep the UI responsive, I decided to load the images in the background, then display them on the main thread. In order to fully load them in the background, I force each image to be decompressed. I was using this code to decompress an image (note that my app is iOS 7 only, so I understand that using these methods on a background thread is OK):
+ (UIImage *)decompressedImageFromImage:(UIImage *)image {
UIGraphicsBeginImageContextWithOptions(image.size, YES, 0);
[image drawAtPoint:CGPointZero];
UIImage *decompressedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return decompressedImage;
}
However, I still had long load times, UI stutter, and a lot of memory pressure. I just found another solution:
+ (UIImage *)decodedImageWithImage:(UIImage *)image {
CGImageRef imageRef = image.CGImage;
// System only supports RGB, set explicitly and prevent context error
// if the downloaded image is not the supported format
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL,
CGImageGetWidth(imageRef),
CGImageGetHeight(imageRef),
8,
// width * 4 will be enough because are in ARGB format, don't read from the image
CGImageGetWidth(imageRef) * 4,
colorSpace,
// kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little
// makes system don't need to do extra conversion when displayed.
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
CGColorSpaceRelease(colorSpace);
if ( ! context) {
return nil;
}
CGRect rect = (CGRect){CGPointZero, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)};
CGContextDrawImage(context, rect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage *decompressedImage = [[UIImage alloc] initWithCGImage:decompressedImageRef];
CGImageRelease(decompressedImageRef);
return decompressedImage;
}
This code is orders of magnitude better. The image loads almost immediately, there is no UI stutter, and the memory usage has gone way down.
So my question is two-fold:
An object that manages image data in your app.
UIImageView *imageview = [[UIImageView alloc] initWithFrame:CGRectMake(10.0, 20.0, 0.0, 0.0)]; UIImage *myimg = [UIImage imageNamed:@"A1. jpg"]; imageview. image=myimg; [imageview sizeToFit]; And don't forget to add image view to view hierarchy.
You can display an image in a SwiftUI view by using the Image view. First you need to add the image to a new image set in your Assets. xcassets file in the Xcode project navigator.
I assume that you're running this on a Retina device. In UIGraphicsBeginImageContextWithOptions
, you asked for the default scale, which is the scale of the main screen, which is 2. This means that it's generating a bitmap 4x as large. In the second function, you're drawing at 1x scale.
Try passing a scale of 1 to UIGraphicsBeginImageContextWithOptions
and see if your performance is similar.
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