How to get transparent image from OpenGL ES context on iPhone
I got a problem with OpenGL ES on iPhone.
I'm working on a project, it draws something on the view, and then save the image. It also has a background image. I combined the image get from view and the backgroun开发者_C百科d image.
I set the view's opaque property as NO, but the image get from the view still opaque. So I could not combine the two images together. I could only see the front image, the background image was nowhere to be found.
CAEAGLLayer *EAGLLayer = (CAEAGLLayer *)self.layer;
EAGLLayer.opaque = NO;
Get image code like this:
- (UIImage *)GetImage
{
CGFloat Width = self.frame.size.width;
CGFloat Height = self.frame.size.height;
GLubyte *TmpBuffer = (GLubyte *)malloc(Width * Height * 4);
glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, TmpBuffer);
GLubyte *Buffer = (GLubyte *)malloc(Width * Height * 4);
for(int y=0; y<Height; y++) {
for(int x=0; x<Width * 4; x++) {
Buffer[((NSInteger)Height - 1 - y) * (NSInteger)Width * 4 + x] = TmpBuffer[y * 4 * (NSInteger)Width + x];
}
}
CGDataProviderRef Provider = CGDataProviderCreateWithData(NULL, Buffer, Width * Height * 4, NULL);
int BitsPerComponent = 8;
int BitsPerPixel = 32;
int BytesPerRow = 4 * 480;
CGColorSpaceRef ColorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo BitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent RenderingIntent = kCGRenderingIntentDefault;
// Make the cgimage.
CGImageRef ImageRef = CGImageCreate(480, 320,
BitsPerComponent,
BitsPerPixel,
BytesPerRow,
ColorSpaceRef,
BitmapInfo,
Provider,
NULL, NO,
RenderingIntent);
return [UIImage imageWithCGImage:ImageRef];
}
Combine code like this:
- (void)Combine:(UIImage *)Back
{
UIGraphicsBeginImageContext(self.frame.size);
CGContextRef aContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(aContext);
CGContextScaleCTM(aContext, 1.0, -1.0);
CGContextTranslateCTM(aContext, 0, -self.frame.size.height);
UIImage *Front = [self GetImage];
CGContextDrawImage(aContext,
CGRectMake(0, 0, self.frame.size.width, self.frame.size.height),
Back.CGImage);
CGContextDrawImage(aContext,
CGRectMake(0, 0, self.frame.size.width, self.frame.size.height),
Front.CGImage);
CGContextRestoreGState(aContext);
UIImageWriteToSavedPhotosAlbum(UIGraphicsGetImageFromCurrentImageContext(), nil, nil, nil);
UIGraphicsEndImageContext();
}
What should I do? any suggest will be pleased. thanks in advance.
I have done exactly this.
I used the following CAEAGLLayer properties:
eaglLayer.opaque = NO;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
and in your -(UIImage *)GetImage method rather use:
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
if needed your Combine: method can be adjusted to save the two combined images to a UIImage by using:
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
hope this helps :)
How are you creating your OpenGL buffer? Specifically, in your EAGLView, when or you set the drawableProperties
class property of your CAEAGLLayer, it should look something like:
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
If you use kEAGLColorFormatRGB565 instead of kEAGLColorFormatRGBA8, your framebuffer will not be storing an alpha value, so it will always be opaque.
If you're not already setting this property, try setting it.
精彩评论