UIImageJPEGRepresentation leak

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