iPhone - CGBitmapContextCreateImage 泄漏,还有其他人遇到这个问题吗?

发布于 2024-08-05 07:46:54 字数 1395 浏览 6 评论 0原文

还有其他人遇到过这个问题吗?我经常使用 NSTimer 调整图像大小。使用 Instruments 后,它没有显示任何内存泄漏,但我的 objectalloc 继续攀升。它直接指向CGBitmapContextCreateImage。

有人知道解决办法吗?或者甚至可能的想法?

-(UIImage *) resizedImage:(UIImage *)inImage : (CGRect)thumbRect : (double)interpolationQuality
{
    CGImageRef          imageRef = [inImage CGImage];
    CGImageAlphaInfo    alphaInfo = CGImageGetAlphaInfo(imageRef);

    if (alphaInfo == kCGImageAlphaNone)
        alphaInfo = kCGImageAlphaNoneSkipLast;

    // Build a bitmap context that's the size of the thumbRect
    CGContextRef bitmap = CGBitmapContextCreate(
                    NULL,
                    thumbRect.size.width,
                    thumbRect.size.height,      
                    CGImageGetBitsPerComponent(imageRef),
                    4 * thumbRect.size.width,   
                    CGImageGetColorSpace(imageRef),
                    alphaInfo
                    );

    // Draw into the context, this scales the image
    CGContextSetInterpolationQuality(bitmap, interpolationQuality);
    CGContextDrawImage(bitmap, thumbRect, imageRef);

    // Get an image from the context and a UIImage
    CGImageRef  ref = CGBitmapContextCreateImage(bitmap);
    UIImage*    result = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);   // ok if NULL
    CGImageRelease(ref);

    return [result autorelease];
}

Has anyone else come across this problem? I am resizing images pretty often with an NSTimer. After using Instruments it does not show any memory leaks but my objectalloc just continues to climb. It points directly to CGBitmapContextCreateImage.

Anyone know of a solution? or Even possible ideas?

-(UIImage *) resizedImage:(UIImage *)inImage : (CGRect)thumbRect : (double)interpolationQuality
{
    CGImageRef          imageRef = [inImage CGImage];
    CGImageAlphaInfo    alphaInfo = CGImageGetAlphaInfo(imageRef);

    if (alphaInfo == kCGImageAlphaNone)
        alphaInfo = kCGImageAlphaNoneSkipLast;

    // Build a bitmap context that's the size of the thumbRect
    CGContextRef bitmap = CGBitmapContextCreate(
                    NULL,
                    thumbRect.size.width,
                    thumbRect.size.height,      
                    CGImageGetBitsPerComponent(imageRef),
                    4 * thumbRect.size.width,   
                    CGImageGetColorSpace(imageRef),
                    alphaInfo
                    );

    // Draw into the context, this scales the image
    CGContextSetInterpolationQuality(bitmap, interpolationQuality);
    CGContextDrawImage(bitmap, thumbRect, imageRef);

    // Get an image from the context and a UIImage
    CGImageRef  ref = CGBitmapContextCreateImage(bitmap);
    UIImage*    result = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);   // ok if NULL
    CGImageRelease(ref);

    return [result autorelease];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

最单纯的乌龟 2024-08-12 07:46:54

你应该发布 imageRef 吗?

CGImageRelease(imageRef);

Should you be releasing imageRef?

CGImageRelease(imageRef);
下壹個目標 2024-08-12 07:46:54

只是一个健全性检查:您是否释放了返回的 UIImage - 通常我会期望一个分配新对象(在本例中为 UIImage)的函数在名称中创建?

也许你想要

return [result autorelease]

Just a sanity check: are you releasing the return UIImage -- normally i would expect a function that allocating a new object (in this case a UIImage) to have create in the name?

Perhaps you want

return [result autorelease]

?

暮倦 2024-08-12 07:46:54

为什么不使用更简单的UIGraphicsBeginImageContext

@implementation UIImage(ResizeExtension)
- (UIImage *)resizedImageWithSize:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)interpolationQuality;
@end
@implementation UIImage(ResizeExtension)
- (UIImage *)resizedImageWithSize:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)interpolationQuality
{
    UIGraphicsBeginImageContext(newSize);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetInterpolationQuality(context, interpolationQuality);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return result;
}

@end

此外,这将返回当前自动释放池保留的图像;如果您要在循环中创建许多此类图像,请手动分配和耗尽 NSAutoreleasePool

Why not use the simpler UIGraphicsBeginImageContext?

@implementation UIImage(ResizeExtension)
- (UIImage *)resizedImageWithSize:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)interpolationQuality;
@end
@implementation UIImage(ResizeExtension)
- (UIImage *)resizedImageWithSize:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)interpolationQuality
{
    UIGraphicsBeginImageContext(newSize);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetInterpolationQuality(context, interpolationQuality);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return result;
}

@end

Also, this will return an image retained by the current autorelease pool; if you are creating many of these images in a loop, allocate and drain an NSAutoreleasePool manually.

送君千里 2024-08-12 07:46:54

好的,这里的问题是我们将 CGBitmapContextCreateImage 的返回定义为 CGImageRef,它应该是 CGImage。您的分配(假设是 malloc)不断增加的原因是因为 CGImage 本身永远不会被释放。尝试下面的代码。另外,不需要自动释放结果,因为它永远不会被“分配”。

在您再次通过分配在仪器中运行更改后,这一次您将希望不会看到活动字节持续增加。

我是在 PC 上输入的,因此如果将其放入 XCode 中,可能会出现语法错误;然而,这应该可以解决问题。

 // Get an image from the context and a UIImage     
CGImage  cgImage = CGBitmapContextCreateImage(bitmap);     
UIImage*    result = [UIImage imageWithCGImage:cgImage];      
CGContextRelease(bitmap);   // ok if NULL     
CGImageRelease(cgImage);      
return result; 

Ok, the problem here is that we are defining the return from CGBitmapContextCreateImage as CGImageRef, it should be CGImage. The reason your allocations (im assuming malloc) are perpetually increasing is becuase the CGImage itself is never getting released. Try the below code. Also, there is no need to autorelease the result since it is never 'Alloc'd.

After you make the changes run in insturments with allocation again, this time you will hopefully not see an continual increase in the live bytes.

I typed this on PC so there may be a syntax error if you drop it into XCode; however, this should do the trick.

 // Get an image from the context and a UIImage     
CGImage  cgImage = CGBitmapContextCreateImage(bitmap);     
UIImage*    result = [UIImage imageWithCGImage:cgImage];      
CGContextRelease(bitmap);   // ok if NULL     
CGImageRelease(cgImage);      
return result; 
⊕婉儿 2024-08-12 07:46:54

如果您使用垃圾收集,请使用 CFMakeCollectable(posterFrame)。如果您使用传统的内存管理,则非常简单:

return (CGImageRef)[(id)posterFrame autorelease];

将 CFTypeRef(在本例中为 CGImageRef)转换为 Objective-C 对象指针,向其发送 -autorelease 消息,然后将结果转换回 CGImageRef。此模式适用于(几乎)任何与 CFRetain() 和 CFRelease() 兼容的类型。

If you're using garbage collection, use CFMakeCollectable(posterFrame). If you're using traditional memory management, it's very straightforward:

return (CGImageRef)[(id)posterFrame autorelease];

You cast the CFTypeRef (in this case, a CGImageRef) to an Objective-C object pointer, send it the -autorelease message, and then cast the result back to CGImageRef. This pattern works for (almost) any type that's compatible with CFRetain() and CFRelease().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文