问题
I have a massive UIImage downloaded from a web resource (>300MBs) which when I attempt to render is causing an app crash due to memory. I am trying to resize the image using the following code:
+ (UIImage *)imageWithImage:(UIImage *)image scaled:(float) scale {
//UIGraphicsBeginImageContext(newSize);
CGSize size = (CGSize){scale * image.size.width, scale * image.size.height};
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
The problem is, as you may have guessed, that this requires actually rendering the image and thus causes the same crash. Is there a way to resize an large image without placing such an enormous memory strain on the system?
回答1:
The problem is that you are holding the image in memory. Download it to disk and use the ImageIO framework to read a "thumbnail" (smaller size) directly from disk without ever having to hold the full-size image in memory.
回答2:
You can try this one + (UIImage *)decodedImageWithImage:(UIImage *)image maxSize:(NSInteger) maxSize.
Code from SDWebImage
#define MAX_IMAGE_SIZE 1000
@implementation UIImage (ForceDecode)
+ (CGSize) originalSize:(UIImage*) image
{
return CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage));
}
+ (UIImage *)decodedImageWithImage:(UIImage *)image {
return [self decodedImageWithImage:image maxSize:MAX_IMAGE_SIZE];
}
+ (UIImage *)decodedImageWithImage:(UIImage *)image maxSize:(NSInteger) maxSize{
if (image.images) {
// Do not decode animated images
return image;
}
CGImageRef imageRef = image.CGImage;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
imageSize = [self checkMaxImageSize:imageSize maxSize:maxSize];
CGRect imageRect = (CGRect){.origin = CGPointZero, .size = imageSize};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
int infoMask = (bitmapInfo & kCGBitmapAlphaInfoMask);
BOOL anyNonAlpha = (infoMask == kCGImageAlphaNone ||
infoMask == kCGImageAlphaNoneSkipFirst ||
infoMask == kCGImageAlphaNoneSkipLast);
// CGBitmapContextCreate doesn't support kCGImageAlphaNone with RGB.
// https://developer.apple.com/library/mac/#qa/qa1037/_index.html
if (infoMask == kCGImageAlphaNone && CGColorSpaceGetNumberOfComponents(colorSpace) > 1) {
// Unset the old alpha info.
bitmapInfo &= ~kCGBitmapAlphaInfoMask;
// Set noneSkipFirst.
bitmapInfo |= kCGImageAlphaNoneSkipFirst;
}
// Some PNGs tell us they have alpha but only 3 components. Odd.
else if (!anyNonAlpha && CGColorSpaceGetNumberOfComponents(colorSpace) == 3) {
// Unset the old alpha info.
bitmapInfo &= ~kCGBitmapAlphaInfoMask;
bitmapInfo |= kCGImageAlphaPremultipliedFirst;
}
// It calculates the bytes-per-row based on the bitsPerComponent and width arguments.
CGContextRef context = CGBitmapContextCreate(NULL,
imageSize.width,
imageSize.height,
CGImageGetBitsPerComponent(imageRef),
0,
colorSpace,
bitmapInfo);
CGColorSpaceRelease(colorSpace);
// If failed, return undecompressed image
if (!context) return image;
CGContextDrawImage(context, imageRect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage *decompressedImage = [UIImage imageWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation];
CGImageRelease(decompressedImageRef);
return decompressedImage;
}
+ (CGSize) checkMaxImageSize:(CGSize) size maxSize:(NSInteger) max
{
CGFloat whRatio = size.width / size.height;
if (size.height > max || size.width > max) {
if (size.height > size.width) {
size.width = max * whRatio;
size.height = max;
}else{
size.width = max ;
size.height = max / whRatio;
}
}
return size;
}
来源:https://stackoverflow.com/questions/38152495/resize-uiimage-under-memory-constraints