2012-02-06 66 views
3

我正在爲客戶端開發增強現實應用程序。 OpenGL和EAGL部分已經在Unity 3D中完成,並在我的應用程序中實現爲View。glReadPixels只保存1/4屏幕大小的快照

我現在需要的是一個按鈕,捕捉OpenGL內容的截圖,這是最後面的視圖。

我試着自己寫,但是當我點擊一個帶有指定IBAction的按鈕時,它只保存屏幕的1/4(左下角) - 儘管它確實將它保存到相機膠捲中。

所以基本上,我怎樣才能讓它保存整個屏幕大小,而不是隻有四分之一?

這裏是我的方法的代碼:

-(IBAction)tagBillede:(id)sender 
{ 
    UIImage *outputImage = nil; 

    CGRect s = CGRectMake(0, 0, 320, 480);    
    uint8_t *buffer = (uint8_t *) malloc(s.size.width * s.size.height * 4); 

    if (!buffer) goto error; 

    glReadPixels(0, 0, s.size.width, s.size.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);  

    CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, buffer, s.size.width * s.size.height * 4, NULL); 

    if (!ref) goto error; 

    CGImageRef iref = CGImageCreate(s.size.width, s.size.height, 8, 32, s.size.width * 4, CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault, ref, NULL, true, kCGRenderingIntentDefault); 

    if (!iref) goto error;   

    size_t width = CGImageGetWidth(iref);  
    size_t height = CGImageGetHeight(iref);  
    size_t length = width * height * 4;    
    uint32_t *pixels = (uint32_t *)malloc(length); 

    if (!pixels) goto error; 

    CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * 4,  
     CGImageGetColorSpace(iref), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big); 

    if (!context) goto error;    

    CGAffineTransform transform = CGAffineTransformIdentity;  
    transform = CGAffineTransformMakeTranslation(0.0f, height);  
    transform = CGAffineTransformScale(transform, 1.0, -1.0);  
    CGContextConcatCTM(context, transform);    
    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), iref);   
    CGImageRef outputRef = CGBitmapContextCreateImage(context); 

    if (!outputRef) goto error; 

    outputImage = [UIImage imageWithCGImage: outputRef]; 

    if (!outputImage) goto error;  

    CGDataProviderRelease(ref); 
    CGImageRelease(iref);  
    CGContextRelease(context);  
    CGImageRelease(outputRef); 
    free(pixels); 
    free(buffer); 

    UIImageWriteToSavedPhotosAlbum(outputImage, self, @selector(image: didFinishSavingWithError: contextInfo:), nil); 
} 

回答

2

我懷疑你使用的設備與Retina顯示屏,這是640×960。您需要考慮屏幕比例;在非Retina顯示器上爲1.0,在Retina顯示器上爲2.0。嘗試像這樣初始化s

CGFloat scale = UIScreen.mainScreen.scale; 
CGRect s = CGRectMake(0, 0, 320 * scale, 480 * scale);    
2

如果設備是視網膜設備,則需要自己調整opengl內容。實際上,您只需要捕捉寬度的一半和高度的一半即可指定您需要的左下角。

您需要爲視網膜屏幕既您的寬度和高度的兩倍,但實際上,你應該在屏幕的規模乘以:

CGFloat scale = [[UIScreen mainScreen] scale]; 
CGRect s = CGRectMake(0, 0, 320.0f * scale, 480.0f * scale); 
+0

謝謝您的幫助 - 我真的很感激它:) 你們倆都告訴我,這也是非常有意義的。儘管我從「CGRect s = CGRectMake」部分獲得了「未使用的變量」,但它仍然不會捕獲超過屏幕左下角的內容? – Thomas 2012-02-09 11:07:43

+0

@Thomas是你用我們的代碼替換你的代碼嗎?在您發佈的代碼中,您定義了一個用於創建緩衝區的'CGRect',並在您調用'glReadPixels'時定義了一個CGRect。如果用上面兩行代替那行代碼,則不會得到有關未使用變量的警告,而是會捕獲整個屏幕。 – 2012-02-09 13:46:55

0

以爲我會幫腔和,並在同一時間,拋出一些感激:)

我得到它的工作就像一個魅力現在,這裏的清理代碼:

UIImage *outputImage = nil; 

CGFloat scale = [[UIScreen mainScreen] scale]; 
CGRect s = CGRectMake(0, 0, 320.0f * scale, 480.0f * scale);    
uint8_t *buffer = (uint8_t *) malloc(s.size.width * s.size.height * 4); 

glReadPixels(0, 0, s.size.width, s.size.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);  

CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, buffer, s.size.width * s.size.height * 4, NULL); 

CGImageRef iref = CGImageCreate(s.size.width, s.size.height, 8, 32, s.size.width * 4, CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault, ref, NULL, true, kCGRenderingIntentDefault); 

size_t width = CGImageGetWidth(iref);  
size_t height = CGImageGetHeight(iref);  
size_t length = width * height * 4;    
uint32_t *pixels = (uint32_t *)malloc(length); 

CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * 4,  
              CGImageGetColorSpace(iref), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big);   

CGAffineTransform transform = CGAffineTransformIdentity;  
transform = CGAffineTransformMakeTranslation(0.0f, height);  
transform = CGAffineTransformScale(transform, 1.0, -1.0);  
CGContextConcatCTM(context, transform);    
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), iref);   
CGImageRef outputRef = CGBitmapContextCreateImage(context); 

outputImage = [UIImage imageWithCGImage: outputRef]; 

CGDataProviderRelease(ref); 
CGImageRelease(iref);  
CGContextRelease(context);  
CGImageRelease(outputRef); 
free(pixels); 
free(buffer); 

UIImageWriteToSavedPhotosAlbum(outputImage, nil, nil, nil);