PDA

View Full Version : Manipulate image correct?




MayPeng
Mar 9, 2012, 04:05 AM
- (char *)getFramebuffer
{
CGImageRef imageRef = CGDisplayCreateImage(displayID);
if(imageRef == NULL)
return NULL;

CGContextRef context = CreateARGBBitmapContext(imageRef );
if(context == NULL)
return NULL;

size_t w = CGImageGetWidth(imageRef );
size_t h = CGImageGetHeight(imageRef);
CGRect rect = {{0,0},{w,h}};

rfbLog("111");
CGContextDrawImage(context, rect,imageRef );
rfbLog("222");


char *returnValue = (char *)CGBitmapContextGetData(context);

return returnValue;
}



///////////////////////////////////////////////
CGContexRef CreateARGBBitmapContext(CGImageRef inImage)
{
int bitmapBytesPerRow;
int bitmapByteCount;
CGColorSpaceRef colorSpace;
char *bitmapData;
CGContextRef context = NULL;
size_t pixelsWidth = CGImageGetWidth(inImage);
size_t pixelsHeight = CGImageGetHeight(inImage);
bitmapBytesPerRow = pixelsWidth * 4;
bitmapByteCount = bitmapBytesPerRow * pixelsHeight ;
colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
if(colorSpace == NULL )
return NULL;

bitmapData = (char *)malloc(sizeof(char ) * bitmapByteCount );
if(bitmapData== NULL )
{
CGColorSpaceRelease(colorSpace);
return NULL;
}

context = CGBitmapContextCreate(bitmapData,
pixelsWidth ,
pixelsHeight,
8,
bitmapBytesPerRow ,
colorSpace ,
kCGImageAlphaPremultipliedLast);
if(context == NULL)
free(bitmapData);

CGColorSpaceRelease(colorSpace);

return context;
}



Code always error "CGImageDataLock : cannot allocate memory" after printing "111".

I spent so much time on it but still don't find the reason。

THKS!!!



robvas
Mar 9, 2012, 02:19 PM
What are you trying to do with the image?

xStep
Mar 9, 2012, 07:37 PM
They are trying to copy the bytes of a CGImage (apparently from a screen capture) into a context for byte level access to the image data, as seen in Apple Technical Q&A QA1509 (https://developer.apple.com/library/mac/#qa/qa1509/_index.html).

So, the image is passed to a function that figures out the size and creates & returns a retained context for further processing. Upon return, given a valid context, they are copying the bytes of the image via the CGContextDrawImage(); function. That is the line the crash is occurring on given the description occurring after printing 111.

They only suggestion I have is for the OP is to test every step through the flow to be sure they have what they are expecting.

Is the error happening for every frame capture, or randomly after some number of frames have been captured.?

MayPeng
Mar 12, 2012, 09:13 PM
What are you trying to do with the image?

The purpose is to capture the remote desktop screen then send it to local computer, just like VNC .

----------

They are trying to copy the bytes of a CGImage (apparently from a screen capture) into a context for byte level access to the image data, as seen in Apple Technical Q&A QA1509 (https://developer.apple.com/library/mac/#qa/qa1509/_index.html).

So, the image is passed to a function that figures out the size and creates & returns a retained context for further processing. Upon return, given a valid context, they are copying the bytes of the image via the CGContextDrawImage(); function. That is the line the crash is occurring on given the description occurring after printing 111.

They only suggestion I have is for the OP is to test every step through the flow to be sure they have what they are expecting.

Is the error happening for every frame capture, or randomly after some number of frames have been captured.?

My purpose is to capture the remote desktop screen then send it to local computer through USB interface , just like VNC .

The error isn't happening for every frame capture, but it always happens when the image shows for 3~4 minitutes in the window on local computer.

MayPeng
Mar 13, 2012, 03:47 AM
- (char *)getFrameBuffer
{
CGImageRef imageRef = CGDisplayCreateImage(displayID);

CFDataRef dataRef = CGDataProviderCopyData(CGImageGetDataProvider(imageRef));

UInt8 *pixelBuf = (UInt8*)CFDataGetBytePtr(dataRef);

CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);

CGContextRef ctx = CGBitmapContextCreate(pixelBuf,
CGImageGetWidth(imageRef),
CGImageGetHeight(imageRef),
8,
CGImageGetBytesPerRow(imageRef),
colorSpace,
kCGImageAlphaPremultipliedFirst);

CGImageRef image = CGBitmapContextCreateImage(ctx);

CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(image));

char *returnValue = (char*)CFDataGetBytePtr(data);

return returnValue;
}

The code above can also meet the requirement , but after screen image keeps for 2 minutes it occur ERROR:malloc :mmap(size = .....) failed(error code = 12)
error:can't allocate region

but I don't use the malloc function, Where does the code error?

ps. The error will occur at the place after CGDataProviderCopyData executes.

xStep
Mar 13, 2012, 03:54 AM
Maybe (I think likely) you are running out of memory. Remember to release your contexts and images after use, I suppose after you have sent them over your connection.

If you are releasing your resources, perhaps slicing the image into sections and only sending the sections that have been altered would help.

If you are using manual memory management, use the Analyze selection under the Product mention to look for possible issues. After that, choose Profile under the Product menu and in the selection box that pops up choose Leaks which will also add Allocations to the profile. Ideally you should see a spike in memory at the start of the image exchange and then see it decrease and increase but overall stay below some common high value until you stop sending images, at which time it should decrease to nearly zero (what ever the app when not processing and sending images takes up).

The WWDC 08 video "1-56 Session 925 - Debugging and Profiling Your iPhone Application" might be helpful to learn about the Profiler, called Instruments. Look at the 300-series videos in the WWDC 2010 list for more.

MayPeng
Mar 15, 2012, 09:36 PM
Good luck! Reason was found! It's right that imageRef and contextRef must be released manually when not used.