问题描述
我的项目正在使用针对iOS(2.4.9)的openCV.我发现函数 MatToUIImage 会导致内存泄漏,并且仅在iOS 10.X上出现.
My project is working with openCV for iOS(2.4.9). And I found function MatToUIImage which will cause memory leaks, and it only occurs on iOS 10.X.
在我将此功能(2.4.9)更新为最新版本(3.2.0)之后,一切正常.唯一的区别是 CGBitmapInfo .
After I updated this function(2.4.9) to latest(3.2.0) version everything got worked. The only difference is CGBitmapInfo.
那么谁能告诉我为什么?
So can anyone tell me why?
2.4.9
UIImage* MatToUIImage(const cv::Mat& image) {
NSData *data = [NSData dataWithBytes:image.data
length:image.elemSize()*image.total()];
CGColorSpaceRef colorSpace;
if (image.elemSize() == 1) {
colorSpace = CGColorSpaceCreateDeviceGray();
} else {
colorSpace = CGColorSpaceCreateDeviceRGB();
}
CGDataProviderRef provider =
CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
// Creating CGImage from cv::Mat
CGImageRef imageRef = CGImageCreate(image.cols,
image.rows,
8,
8 * image.elemSize(),
image.step.p[0],
colorSpace,
kCGImageAlphaNone|
kCGBitmapByteOrderDefault,
provider,
NULL,
false,
kCGRenderingIntentDefault
);
// Getting UIImage from CGImage
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return finalImage;
}
3.2.0
UIImage* MatToUIImage(const cv::Mat& image) {
NSData *data = [NSData dataWithBytes:image.data
length:image.elemSize()*image.total()];
CGColorSpaceRef colorSpace;
if (image.elemSize() == 1) {
colorSpace = CGColorSpaceCreateDeviceGray();
} else {
colorSpace = CGColorSpaceCreateDeviceRGB();
}
CGDataProviderRef provider =
CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
// Preserve alpha transparency, if exists
bool alpha = image.channels() == 4;
CGBitmapInfo bitmapInfo = (alpha ? kCGImageAlphaLast : kCGImageAlphaNone) | kCGBitmapByteOrderDefault;
// Creating CGImage from cv::Mat
CGImageRef imageRef = CGImageCreate(image.cols,
image.rows,
8,
8 * image.elemSize(),
image.step.p[0],
colorSpace,
bitmapInfo,
provider,
NULL,
false,
kCGRenderingIntentDefault
);
// Getting UIImage from CGImage
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return finalImage;
}
推荐答案
重要更新(5.06.2017)最后,手动执行CFRelease
并不是一个好主意,因为它可以提高麻烦胜于解决!不过,这给了我一个线索,即泄漏与NSData
(非)释放有某种联系.
Important update (5.06.2017) Finally, to perform CFRelease
manually turned out to be bad idea as it can raise more troubles than solve! Though, it gave me a clue that leaks are somehow connected with NSData
(not-)releasing.
我注意到从后台线程的块中调用它时,它会按预期与ARC自动释放,
I noticed that it's released automatically as expected with ARC when called from block in background thread, like that:
- (void)runInBackgroundWithImageBuffer:(CVImageBufferRef)imageBuffer
callback:(void (^)())callback {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[self processImageBuffer:imageBuffer];
if (callback != nil) {
callback();
}
});
}
- (void)previewOpenCVImage:(cv::Mat *)image {
UIImage *preview = MatToUIImage(*image);
dispatch_async(dispatch_get_main_queue(), ^{
// _imagePreview has (UIImageView *) type
[_imagePreview setImage:preview];
});
}
这篇关于OpenCV MatToUIImage导致内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!