Hello,
I'm having trouble with a memory leak. The memory used in my app grows until it crashes. I have been able to pinpoint a leak with Instruments Leaks but I'm a bit at loss about why it's leaking now, and I'm wondering if this isn't a bug in UIImageJPEGRepresentation:
I have been able to reproduce the leak in a simpler project:
- (IplImage *)iplImageFromUIImage:(UIImage *)image {
CGImageRef imageRef;
CGColorSpaceRef colorSpaceRef;
CGContextRef context;
IplImage * iplImage;
IplImage * returnImage;
imageRef = image.CGImage;
colorSpaceRef = CGColorSpaceCreateDeviceRGB();
iplImage = cvCreateImage( cvSize( image.size.width, image.size.height ), IPL_DEPTH_8U, 4 );
context = CGBitmapContextCreate
(
iplImage->imageData,
iplImage->width,
iplImage->height,
iplImage->depth,
iplImage->widthStep,
colorSpaceRef,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault
);
CGContextDrawImage( context, CGRectMake( 0, 0, image.size.width, image.size.height ), imageRef );
CGContextRelease( context );
CGColorSpaceRelease( colorSpaceRef );
returnImage = cvCreateImage( cvGetSize( iplImage ), IPL_DEPTH_8U, 3 );
cvCvtColor( iplImage, returnImage, CV_RGBA2BGR);
cvReleaseImage( &iplImage );
return returnImage;
}
- (CGImageRef)createThroughIplImage:(UIImage *)image {
IplImage* originalIplImage = [self iplImageFromUIImage:image];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
IplImage *iplImage = cvCreateImage(cvGetSize(originalIplImage), IPL_DEPTH_8U, 4);
cvCvtColor(originalIplImage, iplImage, CV_RGB2RGBA);
NSData *data = [NSData dataWithBytes:iplImage->imageData length:iplImage->imageSize];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
CGImageRef imageRef = CGImageCreate
(
iplImage->width,
iplImage->height,
iplImage->depth,
iplImage->depth * iplImage->nChannels,
iplImage->widthStep,
colorSpace,
kCGImageAlphaNone|kCGBitmapByteOrderDefault,
provider,
NULL,
false,
kCGRenderingIntentDefault
);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
cvReleaseImage(&iplImage);
cvReleaseImage(&originalIplImage);
return imageRef;
}
- (CGImageRef)createDirect:(UIImage *)image {
CGImageRef ref = image.CGImage;
return (CGImageRef)CFBridgingRetain((__bridge id _Nullable)(ref));
}
- (IBAction)leak:(id)sender {
UIImage *image = [UIImage imageNamed:@"photo.jpg"];
// This version leaks:
CGImageRef imageRef = [self createThroughIplImage:image];
// This version doesn't leak:
// CGImageRef imageRef = [self createDirect:image]
UIImage *resultImage = [[UIImage alloc] initWithCGImage:imageRef];
CGImageRelease(imageRef);
NSData *JPEGData = UIImageJPEGRepresentation(resultImage, 0.80);
NSLog(@"byte length = %lu", (unsigned long)JPEGData.length);
}
The leak seems to be because of an unbalanced retain in UIImageJPEGRepresentation. See here the screenshot from the Leaks instruments: https://i.imgsafe.org/f375344139.png
I'd be happy to have some feedback about this. If this is confirmed to be a bug in UIImageJPEGRepresentation, I will submit a bug report but I'm happy to have a workaround in the meantime.
Thanks!
Bruno