2013-02-14 94 views
1

我打算採取UIView是drawed通過OpenGL ESUIImage的快照,這裏是我使用的代碼:BAD_ACCESS當時的UIView到的UIImage

if(context){ 
    [EAGLContext setCurrentContext:context]; 
    glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer); 
    NSInteger dataLength = framebufferWidth * framebufferHeight * 4; 

    GLubyte* data = (GLubyte*)malloc(dataLength) ; // malloc(myDataLength); 
    glReadPixels(0, 0, framebufferWidth, framebufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, data); 

    // make data provider with data. 
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, dataLength, NULL); 

    // prep the ingredients 
    int bitsPerComponent = 8; 
    int bitsPerPixel = 32; 
    int bytesPerRow = 4 * framebufferWidth; 
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; 
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 

    // make the cgimage 
    CGImageRef result = CGImageCreate(framebufferWidth, framebufferHeight, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); 

    // then make the uiimage from that 
    UIImage *image = [UIImage imageWithCGImage:result]; 
    CGImageRelease(result); 
    CGColorSpaceRelease(colorSpaceRef); 
    CGDataProviderRelease(provider); 
    //free(data); 

    return image; 
} 

我打算用free(data);return之前,但會引起BAD_ACCESS運行時錯誤。

所以我的問題是,如何free正確?或者我應該free他們在圖像發佈後?

+0

你可以在代碼的發佈部分之前記錄'data'嗎? – esh 2013-02-14 11:09:39

+1

您是否嘗試過使用Apple的示例代碼? http://developer.apple.com/library/ios/#qa/qa1704/_index.html – trojanfoe 2013-02-14 11:15:16

+0

你可以在你的其他版本之前放置'free(data)',看看會發生什麼,像這樣'free(data); CGImageRelease(結果); CGColorSpaceRelease(colorSpaceRef); CGDataProviderRelease(provider);' ? – esh 2013-02-14 11:16:12

回答

0

這是我當前的代碼,它工作得很好。

if(context){ 
    [EAGLContext setCurrentContext:context]; 
    glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer); 
    NSInteger dataLength = width * height * 4; 
    int bitsPerComponent = 8; 
    int bitsPerPixel = 32; 
    int bytesPerRow = 4 * width; 
    GLubyte* data = (GLubyte*)malloc(dataLength) ; 
    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); 

    // make upside down 
    GLubyte* swp = (GLubyte*)malloc(width * 4); 
    for (int h = 0; h < height/2; h++) { 
     memcpy(swp, data + (height - 1 - h) * bytesPerRow, bytesPerRow); 
     memcpy(data + (height - 1 - h) * bytesPerRow, data + h * bytesPerRow, bytesPerRow); 
     memcpy(data + h * bytesPerRow, swp, bytesPerRow); 
    } 

    NSData* nsData = [NSData dataWithBytesNoCopy:data length:dataLength freeWhenDone:YES]; 
    // make data provider with data. 
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)nsData); 

    // prep the ingredients 
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; 
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 

    // make the cgimage 
    CGImageRef result = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); 
    CGColorSpaceRelease(colorSpaceRef); 
    CGDataProviderRelease(provider); 

    // then make the uiimage from that 
    UIImage *image = [UIImage imageWithCGImage:result]; 
    CGImageRelease(result); 

    return image; 
} 
+1

托馬斯卡明是正確的。你的代碼在數據和swp上創建內存泄漏。 malloc之後,你必須打電話免費(數據)和提供商回調是正確的方式來做到這一點。免費(swp)呼叫在「顛倒」循環之後。 – velkyel 2015-01-13 09:14:02

1

您應該使用CGDataProviderCreateWithData'sCGDataProviderReleaseDataCallbackhere所述。

只需添加freeData回調函數:

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

,並把它傳遞給CGDataProviderCreateWithData

CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, dataLength, freeData); 
+0

它不起作用。 storeColor中仍爲BAD_ACCESS。 – 2013-02-14 13:32:38

+0

storeColor在哪裏? – 2013-02-14 13:37:48

+0

storeColor是完整的彙編代碼調試窗口的標題。順便說一句,現在的作品..很奇怪 – 2013-02-14 13:48:51