English 中文(简体)
使用CGDataProviderCreateWithData回调
原标题:Using CGDataProviderCreateWithData callback

我使用CGDataProviderCreateWithData(最终)从一个mallocated字节数组创建一个UIImage。我这样调用CGDataProviderCreateWithData:

 provider = CGDataProviderCreateWithData(NULL, dataPtr, dataLen, callbackFunc);

哪里

dataPtr is the previously malloced array of data bytes for the image, dataLen is the number of bytes in the dataPtr array, and callbackFunc is as described in the CGDataProviderCreateWithData documentation:

 void callbackFunc(void *info, const void *data, size_t size);

回调函数是在数据提供程序发布时调用的,所以我可以在那里释放()dataPtr,但我可能想继续使用它(dataPtr),并在稍后的某个阶段释放它。这段代码将被多次调用,流看起来像:

  1. malloc(dataPtr)
  2. create image (call CGDataProviderCreateWithData etc)
  3. display image
  4. release image (and so release data provider created by CGDataProviderCreateWithData)
  5. continue to use dataPtr
  6. free(dataPtr)

因此1..6可以被执行多次。我不希望dataPtr在程序的整个执行过程中一直存在(而且它的大小可能会改变),所以我想根据需要对其进行malloc/释放。

问题是,我无法在CGDataProviderCreateWithData的回调中释放(dataPtr),因为我仍然想使用它,所以我想稍后释放它——在我知道数据提供程序不再需要它之前,我无法释放它(据我所知,CGDataProvierCreateWithData使用了我传递的数组,它不需要副本)。

在我知道可以释放并重新malloc dataPtr之前,我无法执行上面的(1),所以我真正想做的是阻止等待数据提供程序被释放(好吧,我想知道我是否应该重新输入1..6代码块,在数据提供程序释放之前我无法执行此操作)。它将是-我创建数据提供程序,创建图像并立即显示它,然后释放数据提供程序。问题是,直到UIImage发布并完成它之后,数据提供程序才真正发布。

我对objective-c和iOS相当陌生。我是不是错过了一些显而易见的东西?

最佳回答

我所做的和你想要实现的基本上是一样的,我只是走了不同的路。

整个过程被封装到NSOperation中,因此您可以控制调度内存使用。

CGImageRef imageRef = [image CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);

NSUInteger bitsPerComponent = CGImageGetBitsPerComponent(imageRef);


UInt8 *rawData = calloc((height * width * bitsPerComponent), sizeof(UInt8));

NSUInteger bytesPerRow = CGImageGetBytesPerRow(imageRef);


CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                            bitsPerComponent, bytesPerRow, colorSpace,
                                            kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);

if (context)
{   

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); 
            // This is the place you get access to data trough rawData. Do whatever you want with it, when done, get image with 
 CGImageRef newImg = CGBitmapContextCreateImage(context);
 }

subclass CALayer, override drawInContext and use CGBitmapContextGetData to get raw data. Don t have much experience with this though, sorry, but if you want to see instant changes on image based on user input, I d do it this way:

Subclass UIView and CALayer which becomes layer for view and displays image. View gets input and image data (from CGBitmapContextGetData) in layer class is manipulated based on input. Even CATiledLayer can be used for huge images in this way. When done with image, just release UIView and replace it with new one. I ll gladly provide help if you need any, just ping here.

问题回答

如果malloc提供程序数据的内存,那么您确实希望在回调中释放。不要试图以任何方式规避这一点。它太容易泄漏,并且容易受到简单内存问题的影响。

话虽如此,有两种简单的解决方案可以解决您的问题。两者之一:

  • 制作您自己的数据副本,您将与提供商分开管理;或

  • 不要使用CGDataProvider方法的void*格式副本,而是使用CFData版本副本(例如CGDataProviderCreateWithCFData),然后您可以维护自己对该数据对象的强引用(或者,如果在非ARC代码中,则自己执行数据对象的保留操作)。在解决所有强引用之前(或者,在非ARC代码中,使用相应的发布自动发布call解决所有手动保留调用),不会解除分配对象。

使用这两种方法中的任何一种,您都可以继续让CGProviderRef根据需要管理内存,但您也可以继续将数据对象用于自己的目的。

I ran into a similar problem as well. I wanted to use CGImageCreateWithJPEGDataProvider, so used CGDataProviderRef with a malloc d byte array. I was getting the same problem, when trying to free the byte array at some point after creating the Data Provider Reference. It occurs because the data provider reference takes over the ownership of the byte array, so can only be freed by the reference, when it is done with it. I agree with @TheBlack in that if you need the data elsewhere, make a copy of it.





相关问题
Code sign Error

I have created a new iPhone application.I have two mach machines. I have created the certificate for running application in iPhone in one mac. Can I use the other mac for running the application in ...

ABPersonViewController Usage for displaying contact

Created a View based Project and added a contact to the AddressBook using ABAddressBookRef,ABRecordRef now i wanted to display the added contact ABPersonViewController is the method but how to use in ...

将音频Clips从Peter改为服务器

我不禁要问,那里是否有任何实例表明从Peit向服务器发送音响。 I m不关心电话或SIP风格的解决办法,只是一个简单的袖珍流程......

• 如何将搜查线重新定位?

我正试图把图像放在搜索条左边。 但是,问题始于这里,搜索条线不能重新布署。

热门标签