2016-01-31 108 views
3

我參考MetalKitEssentials,並通過MetalKitiOS 9.1中進行模型查看器應用。如何從iOS中的MTKView製作屏幕截圖圖像?

我想從MTKView製作截屏圖像(RGBA格式)。 但是,我只得到黑色的圖像。

我該怎麼辦?

謝謝您的閱讀!

代碼:

@implemtntation MetalViewController 
{ 
    MTKView *metalView; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidload]; 
    [self setup]; 
} 

- (void)setup 
{ 
    metalDevice = MTLCreateSystemDefaultDevice(); 
    commandQueue = [metalDevice newCommandQueue]; 
    defaultLibrary = [metalDevice newDefaultLibrary]; 

    metalView = [[MTKView alloc] initWithFrame:self.view.frame]; 
    [self.view addSubview:metalView]; 

    metalView.delegate = self; 
    metalView.device = metalDevice; 
    metalView.sampleCount = 4; 
    metalView.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; 
    metalView.opaque = false; 
    metalView.framebufferOnly = true; 
    // and more set up for Metal ... 
} 

// if you make screen shot, call this method. 
- (IBAction)onCapture:(id)sender 
{ 
    CGRect screenRect = [[UIScreen mainScreen] bounds]; 
    UIGraphicsBeginImageContextWithOptions(screenRect.size, YES, 0.0); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextFillRect(context, screenRect); 

    // draw image to context 
    [metalView.layer renderInContext:context]; 

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

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

- (void)completeSavedImage:(UIImage *)_image didFinishSavingWithError:(NSError *)_error contextInfo:(void *)_contextInfo 
{ 
    if (!_error) 
    { 
     NSLog(@"ok"); 
    } 
    else 
    { 
     NSLog(@"error"); 
    } 
} 

@end 

回答

3

自行解決。

我找到了一個類似的topic

而我爲以下幾點寫代碼。

1:使用Objective-C

2:沒有使用延長MTLTexture

- (IBAction)onCapture:(id)sender 
{ 
    id<MTLTexture> lastDrawableDisplayed = [metalView.currentDrawable texture]; 

    int width = (int)[lastDrawableDisplayed width]; 
    int height = (int)[lastDrawableDisplayed height]; 
    int rowBytes = width * 4; 
    int selfturesize = width * height * 4; 

    void *p = malloc(selfturesize); 

    [lastDrawableDisplayed getBytes:p bytesPerRow:rowBytes fromRegion:MTLRegionMake2D(0, 0, width, height) mipmapLevel:0]; 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaFirst; 

    CGDataProviderRef provider = CGDataProviderCreateWithData(nil, p, selfturesize, nil); 
    CGImageRef cgImageRef = CGImageCreate(width, height, 8, 32, rowBytes, colorSpace, bitmapInfo, provider, nil, true, (CGColorRenderingIntent)kCGRenderingIntentDefault); 

    UIImage *getImage = [UIImage imageWithCGImage:cgImageRef]; 
    CFRelease(cgImageRef); 
    free(p); 

    NSData *pngData = UIImagePNGRepresentation(getImage); 
    UIImage *pngImage = [UIImage imageWithData:pngData]; 
    UIImageWriteToSavedPhotosAlbum(pngImage, self, 
     @selector(completeSavedImage:didFinishSavingWithError:contextInfo:), nil); 
} 

但是,我得到在getBytes方法以下EXEC錯誤。

failed assertion `texture must not be a framebufferOnly texture.' 

在以下修復中已修復此錯誤。 因此,我更改了MTKView的設置。

metalView.framebufferOnly = false; 

謝謝。