0

此函数的目的是从 openGL 图像返回 UIImage。将其转换为 CG 图像的原因是 openGL 和 UIKit 元素可以相互叠加渲染,这在另一个函数中得到了处理。

奇怪的是,当应用程序在模拟器中运行时,一切正常。但是,在多个不同的 iPad 上测试应用程序后,当drawGlToImage调用该方法时self,应用程序崩溃并出现 EXC_BAD_ACCESS code=1 错误。有谁知道我在这里做什么会导致这种情况?我读过它UIGraphicsBeginImageContext()曾经有线程安全问题,但似乎在 iOS 4 中已修复。

    - (UIImage *)drawGlToImage
{
    self.context = [EAGLContext currentContext];
    [EAGLContext setCurrentContext:self.context];
    UIGraphicsBeginImageContext(self.view.frame.size);

    unsigned char buffer[1024 * 768 * 4];
    NSInteger dataSize = 1024 * 768 * 4;

    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(currentContext);

    glReadPixels(0, 0, 1024, 768, GL_RGBA, GL_UNSIGNED_BYTE, &buffer);

    //flip the image
    GLubyte *flippedBuffer = (GLubyte *) malloc(dataSize);

    for(int y = 0; y <768; y++)
    {
        for(int x = 0; x <1024 * 4; x++)
        {
            if(buffer[y* 4 * 1024 + x]==0)
                flippedBuffer[(767 - y) * 1024 * 4 + x]=1;
            else
                flippedBuffer[(767 - y) * 1024 * 4 + x] = buffer[y* 4 * 1024 + x];
        }
    }



    CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, flippedBuffer, 1024 * 768 * 4, NULL);
    CGImageRef iref = CGImageCreate(1024,768,8,32,1024*4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaLast, ref, NULL, true, kCGRenderingIntentDefault);

    CGContextScaleCTM(currentContext, 1.0, -1.0);
    CGContextTranslateCTM(currentContext, 0, -self.view.frame.size.height);

    UIGraphicsPopContext();
    UIImage *image = [[UIImage alloc] initWithCGImage:iref];
    UIGraphicsEndImageContext();

    return image;
    free(flippedBuffer);
    UIGraphicsPopContext();
}

当一个按钮被按下时,一个被调用的方法会进行这个赋值,这会导致应用程序崩溃。

UIImage *glImage = [self drawGlToImage];
4

2 回答 2

0

我不确定您在哪个阶段调用此方法。但在调用任何 OpenGL 函数之前,您需要设置正确的 OpenGL 上下文。在 Xcode 模板中是这一行

[EAGLContext setCurrentContext:self.context];
于 2012-07-03T21:02:28.023 回答
0

这是用于解决它的代码

- (UIImage *)drawGlToImage {

    // Code borrowed and tweaked from:
    // http://stackoverflow.com/questions/9881143/missing-part-of-the-image-when-taking-screenshot-while-supporting-retina-display

    CGFloat scale = UIScreen.mainScreen.scale;
    CGFloat xOffset = 40.0f;
    CGFloat yOffset = -16.0f;
    CGSize size = CGSizeMake((self.chart.frame.size.width) * scale,
                             self.chart.frame.size.height * scale);

    //Create buffer for pixels
    GLuint bufferLength = size.width * size.height * 4;
    GLubyte* buffer = (GLubyte*)malloc(bufferLength);

    //Read Pixels from OpenGL
    glReadPixels(0.0f, 0.0f, size.width, size.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    //Make data provider with data.
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLength, NULL);

    //Configure image
    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4 * size.width;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGImageAlphaLast;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    CGImageRef iref = CGImageCreate(size.width, size.height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

    uint32_t* pixels = (uint32_t*)malloc(bufferLength);
    CGContextRef context = CGBitmapContextCreate(pixels, size.width, size.height, 8, size.width * 4, CGImageGetColorSpace(iref), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGContextTranslateCTM(context, 0.0f, size.height);
    CGContextScaleCTM(context, 1.0f, -1.0f);

    // These numbers are a little magical.
    CGContextDrawImage(context, CGRectMake(xOffset, yOffset, ((size.width - (6.0f * scale)) / scale) - (xOffset / 2), (size.height / scale) - (yOffset / 2)), iref);
    UIImage *outputImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];

    //Dealloc
    CGDataProviderRelease(provider);
    CGImageRelease(iref);
    CGContextRelease(context);
    free(buffer);
    free(pixels);

    return outputImage;
}
于 2012-07-24T20:26:09.223 回答