缓冲区 - > CGImageRef-> UIImage的内存管理模式是什么?

Ben*_*tto 14 iphone core-graphics core-foundation uiimage quartz-2d

我有一个函数,它获取一些位图数据并从中返回一个UIImage*.它看起来像这样:

UIImage * makeAnImage() 
{
    unsigned char * pixels = malloc(...);
    // ...
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, pixelBufferSize, NULL);
    CGImageRef imageRef = CGImageCreate(..., provider, ...);
    UIImage * image =  [[UIImage alloc] initWithCGImage:imageRef];
    return [image autorelease];
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以确切地解释谁在这里拥有什么记忆?我想要正确清理,但我不确定如何安全地进行清理.文档在这些上是模糊的.如果free在创建UIImage之后我在此函数末尾的像素,然后使用UIImage,我崩溃了.如果我在创建UIImage之后释放提供者或imageRef,我没有看到崩溃,但他们显然已经完全传递了像素,所以我对释放这些中间状态感到不安.

(我知道每个CF文档我都需要在后者上调用release,因为它们来自Create函数,但是我可以在使用UIImage之前这样做吗?)大概我可以使用提供者的dealloc回调来清理像素缓冲区,还有什么?

谢谢!

ken*_*ytm 21

这里的拇指规则是" -release*它,如果你不需要它".

因为你不再需要providerimageRef之后,你应该-release全部,即

UIImage * image =  [[UIImage alloc] initWithCGImage:imageRef];
CGDataProviderRelease(provider);
CGImageRelease(imageRef);
return [image autorelease];
Run Code Online (Sandbox Code Playgroud)

pixel不是通过引用计数来管理的,因此您需要告诉CG API在必要时为您释放它们.做这个:

void releasePixels(void *info, const void *data, size_t size) {
   free((void*)data);
}
....

CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, pixelBufferSize, releasePixels);
Run Code Online (Sandbox Code Playgroud)

顺便说一下,你可以用+imageWithCGImage:而不是[[[* alloc] initWithCGImage:] autorelease].更好的是+imageWithData:,你不需要弄乱CG和malloc东西.

(*:除非retainCount从一开始就认为是零.)


Pet*_*sey 8

unsigned char * pixels = malloc(...);
Run Code Online (Sandbox Code Playgroud)

您拥有pixels缓冲区是因为您已将它集中在一起.

CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, pixelBufferSize, NULL);
Run Code Online (Sandbox Code Playgroud)

Core Graphics遵循Core Foundation规则.您拥有数据提供者是因为您创建了它.

您没有提供发布回调,因此您仍然拥有pixels缓冲区.如果您提供了发布回调,则CGDataProvider对象将在此处获取缓冲区的所有权.(通常是一个好主意.)

CGImageRef imageRef = CGImageCreate(..., provider, ...);
Run Code Online (Sandbox Code Playgroud)

您拥有CGImage对象是因为您创建了它.

UIImage * image =  [[UIImage alloc] initWithCGImage:imageRef];
Run Code Online (Sandbox Code Playgroud)

您拥有UIImage对象,因为您已将其分配.

您还拥有CGImage对象.如果UIImage对象想拥有CGImage对象,它将保留它或制作自己的副本.

return [image autorelease];
Run Code Online (Sandbox Code Playgroud)

您放弃了对图像的所有权.

所以你的代码泄漏像素(你没有将所有权转移到数据提供者而你自己没有发布),数据提供者(你没有发布它)和CGImage(你没有发布它) .固定版本会将像素的所有权转移到数据提供者,并在UIImage准备好时释放数据提供者和CGImage.或者,imageWithData:正如KennyTM建议的那样使用.