简体   繁体   English

当UIView到UIImage尝试释放数据时,BAD_ACCESS

[英]BAD_ACCESS when trying to free data when UIView to UIImage

I intended to take a snapshot of a UIView that drawed by OpenGL ES into an UIImage , here is the code I used: 我打算拍摄由OpenGL ES绘制到UIImage中的UIView的快照,这是我使用的代码:

 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;
}

I was intended to use free(data); 我打算使用free(data); before return , but that would raises a BAD_ACCESS runtime error. return之前,但这会引发BAD_ACCESS运行时错误。

So my questions is, how to free properly? 所以我的问题是,如何正确free Or should I free them after the image releases? 或者我应该free他们的形象发布后?

You should use CGDataProviderCreateWithData's CGDataProviderReleaseDataCallback as described here . 您应该使用CGDataProviderCreateWithData's CGDataProviderReleaseDataCallback描述这里

Simply add the freeData function callback: 只需添加freeData函数回调:

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

and pass it to CGDataProviderCreateWithData : 并将其传递给CGDataProviderCreateWithData

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

This is my current code and it works just fine. 这是我当前的代码,并且工作正常。

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;
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM