2011-09-21 56 views
5

我正在爲iphone繪製應用程序。在我的代碼中,我使用的是包含輪廓圖像的imageView,我在其中將CAEAGLLayer用於在輪廓圖像中填充顏色。Paint app的OpenGL ES內容的屏幕截圖

- (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;} 

使用功能相結合該屏幕截圖與輪廓圖:

- (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(); 

}

保存此圖像使用到畫冊現在我使用的功能考慮的OpenGL ES [CAEAGLLayer]呈現的內容截圖功能

-(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]; } 

上面的代碼正在工作,但圖像質量屏幕截圖很差。在畫筆的輪廓上,有一個灰色的輪廓。我已經上傳了我的應用程序的截圖,它是開放性內容& UIImage的組合。

Screenshot

有沒有什麼辦法讓opengles-CAEaglelayer內容Retina顯示屏幕截圖。

預先感謝您!

回答

4

我不認爲這個決議是你的問題在這裏。如果屏幕上顯示的圖形上沒有灰顯的輪廓,則可能是您在保存過程中觀察到壓縮人爲因素。您的圖像可能被保存爲質量較低的JPEG圖像,其中僞像將顯示在銳利的邊緣上,如您的圖形中的圖像。

要解決這個問題,本·魏斯的答案here爲迫使你的圖片下面的代碼保存到照片庫爲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 

雖然這可能是解決你的問題,最簡單的方法在這裏,您也可以嘗試採用多采樣抗鋸齒技術,正如Apple在iOS版OpenGL ES編程指南的「Using Multisampling to Improve Image Quality」部分所述。根據您的填充率限制情況,MSAA可能會導致您的應用程序出現一些放緩現象。

+0

感謝Brad,這就是我一直在尋找的! – user392406

1

當您創建CG位圖上下文時,您正在使用kCGImageAlphaPremultipliedLast。雖然我看不到你的OpenGL代碼,但我認爲你的OpenGL上下文並不能渲染預乘alpha。不幸的是,在IIRC中,不可能在iOS上創建非預乘積的CG位圖上下文(它將使用kCGImageAlphaLast,但我認爲這會使創建調用失敗),因此您可能需要手動預乘數據從OpenGL中獲取它並製作CG上下文。

另一方面,你的OpenGL上下文有alpha通道嗎?你能不能讓它變成不透明的白色,然後用kCGImageAlphaNoneSkipLast?