【问题标题】:Saving imageRef from GLPaint creates completely black image从 GLPaint 保存 imageRef 会创建完全黑色的图像
【发布时间】:2012-04-09 02:49:19
【问题描述】:

您好,我正在试用绘图应用程序,但在保存绘制的图像时遇到问题。现在我很早就开始学习这个了,但我添加了以下代码: How to get UIImage from EAGLView? 保存绘制的图像。

我创建了一个新应用,然后显示了我创建的 viewController。在 IB 中,我添加了一个名为 PaintingView 的视图,而 imageView 位于其后面。

到目前为止,我对 PaintingView 所做的唯一修改是将背景更改为清除并将背景设置为清除,以便我可以在其后面显示图像。绘图效果很好,我唯一的问题是保存。

- (void)saveImageFromGLView:(UIView *)glView {

    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
        {
            /// This IS being activated with code 0
            NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
    }


    int s = 1;
    UIScreen* screen = [ UIScreen mainScreen ];
    if ( [ screen respondsToSelector:@selector(scale) ] )
        s = (int) [ screen scale ];

    const int w = self.frame.size.width;
    const int h = self.frame.size.height;
    const NSInteger myDataLength = w * h * 4 * s * s;
    // allocate array and read pixels into it.
    GLubyte *buffer = (GLubyte *) malloc(myDataLength);
    glReadPixels(0, 0, w*s, h*s, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    // gl renders "upside down" so swap top to bottom into new array.
    // there's gotta be a better way, but this works.
    GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
    for(int y = 0; y < h*s; y++)
    {
        memcpy( buffer2 + (h*s - 1 - y) * w * 4 * s, buffer + (y * 4 * w * s), w * 4 * s );
    }
    free(buffer); // work with the flipped buffer, so get rid of the original one.

    // make data provider with data.
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
    // prep the ingredients
    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4 * w * s;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    // make the cgimage
    CGImageRef imageRef = CGImageCreate(w*s, h*s, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
    // then make the uiimage from that
    UIImage *myImage = [ UIImage imageWithCGImage:imageRef scale:s orientation:UIImageOrientationUp ];
    UIImageWriteToSavedPhotosAlbum( myImage, nil, nil, nil );
    CGImageRelease( imageRef );
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpaceRef);
    free(buffer2);    

}

将上述代码添加到示例应用程序工作正常,问题是在我的新应用程序中执行此操作。我能说的唯一区别是我没有包括 PaintingWindow - 这会是问题吗?

就好像 saveImage 方法没有看到绘图数据一样。

【问题讨论】:

  • 该方法看起来不错,如果您没有更改原始代码的任何内容(我想这必须来自 brad larson,因为他总是使用这些东西)我唯一能想到的是您是当帧缓冲区被清除时调用它。你在打电话清除帧缓冲区吗?您是否在不将背景设置为清除的情况下尝试过此操作?
  • 好主意 - 我没有尝试过,但遗憾的是没有任何变化。只是一个纯黑色的png。删除缓冲区的唯一地方是在一个名为destroyFrameBuffer 的方法中。这只会在第一次加载视图时调用一次。我很高兴听起来缓冲区已被清除。是否有一个好方法来 NSLog 告诉缓冲区的内容/内容大小?
  • 实际上 - 我刚刚在 saveImage 方法的顶部添加了一个 NSLOG 语句,看起来缓冲区有问题 - 我更新了问题以反映这一点
  • 首先尝试在您确定帧缓冲区完好无损的地方使用此方法,(即使它在渲染方法中,只需添加一个断点,这样它就不会通过尝试保存大量次)。我刚刚看到您将 (UIView *)glView 作为参数,这意味着您可能正试图从其他地方调用它(尽管在这里它什么也不做)。
  • 另外,我已经在整个绘图过程中移动了这个 if 语句,它唯一失败的时间是在这个 saveImage 方法中。

标签: iphone ios ipad opengl-es


【解决方案1】:

应该在 OpenGL 上下文的范围内调用 save 方法。 为了解决这个问题,您可以在同一个渲染 .m 文件中移动您的方法并从外部调用此函数。

您还需要考虑 OpenGL 清除颜色。

(cmets中的详细解释,lol)

【讨论】:

  • 再次感谢 - 总结一下有这个问题的人,我是从主绘图视图控制器而不是渲染层本身调用 save 方法。当我更改此设置时,它似乎仍然无法正常工作,因为我已将 openGL 背景颜色更改为清晰,在 OpenGL 中为黑色。
【解决方案2】:

我发现把 CGBitmapInfo 改成:

CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;

产生透明背景。

【讨论】:

    【解决方案3】:

    啊,你必须在一开始就这样做。

    [EAGLContext setCurrentContext:drawContext];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多