Memory leak with UIImage method "drawInRect"

1.8k views Asked by At

I have question about correct using UIImage and method drawInRect.

I use iPad 4,Xcode Version 6.1.1, IOS 8.1.2 and I used ARC and I have tried without ARC

So, I have image "1.jpg".

Image Properties:

Dimension: 7500 x 8871 pixels

Resolution: 72 pixels/inch

Color Space: RGB

Alpha Channel: NO

I need to rescale the original image "1.jpg"

I use this code:

UIImage *originalImage=[UIImage imageNamed:@"1.jpg"];
CGSize newSize=(CGSizeMake(4096, 4096));
originalImage=[self GetScaledImage : originalImage andSize: newSize];

//----Scaling Method----------------------//

-(UIImage *) GetScaledImage :(UIImage *) inputImage andSize :(CGSize) inputSize
{

 UIImage *newImage=[[[UIImage alloc] initWithCGImage:inputImage.CGImage] autorelease];    
 if (newImage)
 {        
     UIGraphicsBeginImageContext(inputSize);
     [newImage drawInRect: CGRectMake(0, 0, inputSize.width, inputSize.height)];
     newImage = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
 }

 return newImage;
}

My question:

if I use newSize: (4096, 4096)

UIImage *originalImage=[UIImage imageNamed:@"1.jpg"];
CGSize newSize=(CGSizeMake(4096, 4096));

Memory now: 3.1 MB

originalImage=[self GetScaledImage : originalImage andSize: newSize];

Memory now: 4.3 MB

and it works correct

but if I use newSize: (3000, 4096)

I have this:

UIImage *originalImage=[UIImage imageNamed:@"1.jpg"];
CGSize newSize=(CGSizeMake(3000, 4096));

Memory now: 3.1 MB

originalImage=[self GetScaledImage : originalImage andSize: newSize];

Memory now: 52 MB

and it works incorrect

and magic: if I use newSize: (4096,3000) it works correct too but (3000,4096) works incorrect

So, my question: How does it work?

2

There are 2 answers

0
izhylenko On

I suppose there is no magic. The CGImage object is not deallocated but owned. For this, you need to set image.CGImage to some variable and then release it with

CFRelease(cgImage);

Also try to clear graphics context after all processing done.

0
Sheldon Huang On

You can solve the problem by using the following method instead.

+ (UIImage *)scaleImageWithData:(NSData *)data withSize:(CGSize)size
                          scale:(CGFloat)scale
                    orientation:(UIImageOrientation)orientation {
    CGFloat maxPixelSize = MAX(size.width, size.height);
    CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil);
    NSDictionary *options = @{(__bridge id)kCGImageSourceCreateThumbnailFromImageAlways:(__bridge id)kCFBooleanTrue,
                              (__bridge id)kCGImageSourceThumbnailMaxPixelSize:[NSNumber numberWithFloat:maxPixelSize]
                              };
    CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options);
    UIImage *resultImage = [UIImage imageWithCGImage:imageRef scale:scale orientation:orientation];
    CGImageRelease(imageRef);
    CFRelease(sourceRef);
    
    return resultImage;
}