Dan Drews
Dan Drews

Reputation: 1976

Memory Leak UIIMageFromCVMat

I am trying to convert a CVMat into a UIImage, but am running into a memory leak and cannot for the life of me figure out where. the issue lies. I am using the same function that openCV uses in their sample code Located Here.

The code says the following:

+(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat{
    NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()];
    CGColorSpaceRef colorSpace;

    if (cvMat.elemSize() == 1) {
        colorSpace = CGColorSpaceCreateDeviceGray();
    } else {
        colorSpace = CGColorSpaceCreateDeviceRGB();
    }

    CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
    bool alpha = cvMat.channels() == 4;
    CGBitmapInfo bitMapInfo = (alpha ? kCGImageAlphaLast : kCGImageAlphaNone) | kCGBitmapByteOrderDefault;
    // Creating CGImage from cv::Mat
    CGImageRef imageRef = CGImageCreate(cvMat.cols,                                 //width
                                        cvMat.rows,                                 //height
                                        8,                                          //bits per component
                                        8 * cvMat.elemSize(),                       //bits per pixel
                                        cvMat.step[0],                            //bytesPerRow
                                        colorSpace,                                 //colorspace
                                        bitMapInfo,                                 // bitmap info
                                        provider,                                   //CGDataProviderRef
                                        NULL,                                       //decode
                                        false,                                      //should interpolate
                                        kCGRenderingIntentDefault                   //intent
                                        );


    // Getting UIImage from CGImage
    UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpace);

    return finalImage; 
}

Does anybody have any suggestions on where the issue could be? (We have narrowed down and know for certain that this is the place with the leak).

Edit

To give some more information that I have found: If the output of the function is never used, there are no issues. It is only if we assign this result to a variable within a different class that we run into issues.

Upvotes: 4

Views: 1176

Answers (2)

Dan Drews
Dan Drews

Reputation: 1976

Okay, after much searching, the solution has been discovered (though I still do not have a very deep understanding of the problem, and if somebody could point me in the right direction for the why it was an issue, that'd be wonderful).

All that needed to be done was to wrap the lines of code that used the result of this in a @autoreleasepool{} tag.

I found the basic idea of the solution from this question

Upvotes: 4

Reinhard Männer
Reinhard Männer

Reputation: 15217

assuming you are not using ARC, my guess is that the problematic statement is
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
The __bridge does not transfer ownership, so CGDataProviderRelease(provider); does not release the original object.
You had either to release data explicitly, or use __bridge_transfer to transfer ownership to provider, which is then released with CGDataProviderRelease(provider);

Upvotes: 0

Related Questions