views:

230

answers:

2

I'm trying to take a CGImage and copy its data into a buffer for later processing. The code below is what I have so far, but there's one thing I don't like about it - it's copying the image data twice. Once for CGDataProviderCopyData() and once for the :getBytes:length call on imgData. I haven't been able to find a way to copy the image data directly into my buffer and cut out the CGDataProviderCopyData() step, but there has to be a way...any pointers? (...pun ftw)

NSData *imgData = (NSData *)(CGDataProviderCopyData(CGImageGetDataProvider(myCGImageRef)));

CGImageRelease(myCGImageRef);

// i've got a previously-defined pointer to an available buffer called "mybuff"
[imgData getBytes:mybuff length:[imgData length]];
A: 

Unless you see a performance problem when you use Instruments to measure it, I don't think that copying it twice is a huge problem. You could always store the CFDataRef imgData directly instead of the mybuff.

Edit
I'm talking about this kind of code:
In your class interface add an array:

NSMutableArray *images;

In your init: method: create the array:

images = [[NSMutableArray alloc] init];

and have a dealloc;

-(void)dealloc{
    [images release];
}

and in your code that saves each image:

CGDataRef imageDataRef = CGDataProviderCopyData(CGImageGetDataProvider(myCGImageRef)));
[images addObject: (NSData*)imageDataRef];
CGRelease(imageDataRef);
lucius
The problem is this code is executing in quick succession: I'm screengrabbing then filling the buffer with image data as fast as I can. Right now the best I can do on the iPhone 3G is 11.5 FPS but I think it can do better. If I were doing it once then moving on, I would say you're correct in asserting that it's not that big of a performance hit...but in this situation I can benefit from any middle-men I can cut out. Could you elaborate on your statement "You could always store the CFDataRef imgData directly..."?
jtrim
Return the NSData object and use its -bytes method to access the bytes of the image instead of using your buffer is what lucius meant. Another point: just because you are using all these methods with the word "copy" in them does not mean the actual byte data is being physically copied. If all of the objects are immutable. IT's possible that they all use the same byte buffer.
JeremyP
JeremyP - It seems to me that Apple is always purposefully literal in their documentation. I've found that if they use the word "copy", that you're getting a copy.
jtrim
lucius - I see what you mean now, and I was doing that previous to the solution I'm working on now. I learned by example that things that are "mutable" aren't as fast as a raw buffer. Please correct me if I'm wrong, but if you've got an NSMutableArray and you want to add an item to that array, it has to allocate memory for that item, and it has to do the same for each item added (that statement assuming you don't know how many items you'll need to dump in the mutable array). I'm assuming the performance hit comes in allocating new memory for the item to be added.
jtrim
JeremyP - Since I'm unsure on whether it actually "copies" or not, I've asked a new question here: http://stackoverflow.com/questions/2744639/cocoa-does-cgdataprovidercopydata-actually-copy-the-bytes-or-just-the-point
jtrim
Yeah, in my experience, allocating memory is a fairly expensive operation. If you want the maximum performance, you need to allocate all your buffers beforehand. You probably want to avoid Obj-C method calls to avoid objc_msgSend() overhead too.
lucius
Lucius - cool, thanks a bunch
jtrim
jtrim: “I've found that if they use the word "copy", that you're getting a copy.” Not necessarily. If you send a `copy` message to an immutable plist object (string, array, etc.), you'll get the same object retained. No need to copy what can't be changed, after all.
Peter Hosey
A: 

See this answer: http://stackoverflow.com/questions/2744639/cocoa-does-cgdataprovidercopydata-actually-copy-the-bytes-or-just-the-point

Looks like direct access to the buffer behind a CGDataProvider is restricted to private APIs.

jtrim