【发布时间】: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 方法中。