Reputation: 1976
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
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
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