2011-09-21 10 views
5

Estoy trabajando en una aplicación de pintura para iphone. En mi código estoy usando un imageView que contiene una imagen de esquema en la que estoy poniendo CAEAGLLayer para rellenar colores en la imagen del contorno. Ahora estoy tomando captura de pantalla de OpenGL ES [CAEAGLLayer] contenido representado usando la función:Captura de pantalla del contenido de OpenGL ES para la aplicación Paint

- (UIImage*)snapshot:(UIView*)eaglview{ 
GLint backingWidth1, backingHeight1; 

// Bind the color renderbuffer used to render the OpenGL ES view 
// If your application only creates a single color renderbuffer which is already bound at this point, 
// this call is redundant, but it is needed if you're dealing with multiple renderbuffers. 
// Note, replace "_colorRenderbuffer" with the actual name of the renderbuffer object defined in your class. 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 

// Get the size of the backing CAEAGLLayer 
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth1); 
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight1); 

NSInteger x = 0, y = 0, width = backingWidth1, height = backingHeight1; 
NSInteger dataLength = width * height * 4; 
GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte)); 

// Read pixel data from the framebuffer 
glPixelStorei(GL_PACK_ALIGNMENT, 4); 
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); 

// Create a CGImage with the pixel data 
// If your OpenGL ES content is opaque, use kCGImageAlphaNoneSkipLast to ignore the alpha channel 
// otherwise, use kCGImageAlphaPremultipliedLast 
CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL); 
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 
CGImageRef iref = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast, 
           ref, NULL, true, kCGRenderingIntentDefault); 

// OpenGL ES measures data in PIXELS 
// Create a graphics context with the target size measured in POINTS 
NSInteger widthInPoints, heightInPoints; 
if (NULL != UIGraphicsBeginImageContextWithOptions) { 
    // On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration 
    // Set the scale parameter to your OpenGL ES view's contentScaleFactor 
    // so that you get a high-resolution snapshot when its value is greater than 1.0 
    CGFloat scale = eaglview.contentScaleFactor; 
    widthInPoints = width/scale; 
    heightInPoints = height/scale; 
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(widthInPoints, heightInPoints), NO, scale); 
} 
else { 
    // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext 
    widthInPoints = width; 
    heightInPoints = height; 
    UIGraphicsBeginImageContext(CGSizeMake(widthInPoints, heightInPoints)); 
} 

CGContextRef cgcontext = UIGraphicsGetCurrentContext(); 

// UIKit coordinate system is upside down to GL/Quartz coordinate system 
// Flip the CGImage by rendering it to the flipped bitmap context 
// The size of the destination area is measured in POINTS 
CGContextSetBlendMode(cgcontext, kCGBlendModeCopy); 
CGContextDrawImage(cgcontext, CGRectMake(0.0, 0.0, widthInPoints, heightInPoints), iref); 

// Retrieve the UIImage from the current context 
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 

UIGraphicsEndImageContext(); 

// Clean up 
free(data); 
CFRelease(ref); 
CFRelease(colorspace); 
CGImageRelease(iref); 

return image;} 

la combinación de esta pantalla imagen del esquema con el uso de la función:

- (void)Combine:(UIImage *)Back{ 


UIImage *Front =backgroundImageView.image; 


//UIGraphicsBeginImageContext(Back.size); 
UIGraphicsBeginImageContext(CGSizeMake(640,960)); 
// Draw image1 
[Back drawInRect:CGRectMake(0, 0, Back.size.width*2, Back.size.height*2)]; 

// Draw image2 
[Front drawInRect:CGRectMake(0, 0, Front.size.width*2, Front.size.height*2)]; 

UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext(); 


UIImageWriteToSavedPhotosAlbum(resultingImage, nil, nil, nil); 


UIGraphicsEndImageContext(); 

}

Guardar esta imagen para ÁlbumDigital usando función

-(void)captureToPhotoAlbum { 
[self Combine:[self snapshot:self]]; 
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Success" message:@"Image saved to Photo Album" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
[alert show]; 
[alert release]; } 

Por encima de código está trabajando pero la imagen qua La calidad de la captura de pantalla es pobre. En los contornos del pincel, hay un contorno grisáceo. He subido una captura de pantalla de mi aplicación que es una combinación de contenido abierto & UIImage.

Screenshot

¿Hay alguna manera de obtener la retina pantalla captura de pantalla de contenido OpenGLES-CAEaglelayer.

¡Gracias de antemano!

Respuesta

4

No creo que la resolución sea su problema aquí. Si no está viendo los contornos grisáceos en su dibujo cuando aparece en la pantalla, lo más probable es que esté observando un artefacto de compresión en el proceso de guardado. Es probable que su imagen se esté guardando como una imagen JPEG de menor calidad, donde los artefactos aparecerán en los bordes afilados, como los de su dibujo.

Para evitar esto, la respuesta de Ben Weiss here proporciona el siguiente código para forzar su imagen se guarden en la biblioteca de fotos como un PNG:

UIImage* im = [UIImage imageWithCGImage:myCGRef]; // make image from CGRef 
NSData* imdata = UIImagePNGRepresentation (im); // get PNG representation 
UIImage* im2 = [UIImage imageWithData:imdata]; // wrap UIImage around PNG representation 
UIImageWriteToSavedPhotosAlbum(im2, nil, nil, nil); // save to photo album 

Si bien esto es probablemente la forma más fácil para hacer frente a su problema aquí, también podría intentar emplear el antialiasing multisample, como describe Apple en la sección "Using Multisampling to Improve Image Quality" de la Guía de programación de OpenGL ES para iOS. Dependiendo de cuán limitado sea el nivel de llenado, MSAA podría provocar un poco de desaceleración en su aplicación.

+0

Gracias Brad, esto es lo que estaba buscando! – user392406

1

Está utilizando kCGImageAlphaPremultipliedLast cuando crea el contexto de mapa de bits de CG. Aunque no puedo ver su código OpenGL, me parece poco probable que su contexto OpenGL esté representando alfa premultiplicado. Desafortunadamente, IIRC, no es posible crear un contexto de mapa de bits CG no premultiplicado en iOS (usaría kCGImageAlphaLast, pero creo que eso hará que la llamada a la creación falle), por lo que es posible que deba premultiplicar los datos a mano entre obteniéndolo de OpenGL y haciendo el contexto CG.

Por otro lado, ¿hay algún motivo por el que su contexto OpenGL tenga un canal alfa? ¿Podría simplemente hacer que sea blanco opaco y luego usar kCGImageAlphaNoneSkipLast?

Cuestiones relacionadas