如何在iOS中从MTKView生成屏幕快照图像?
我在如何在iOS中从MTKView生成屏幕快照图像?,ios,objective-c,metal,Ios,Objective C,Metal,我在ios9.1中引用并通过MetalKit制作模型查看器应用程序 我想从MTKView制作屏幕快照图像(RGBA格式)。 但是,我只有黑色的图像 我该怎么办 谢谢你的阅读 代码: 自我解决 我发现了一个类似的例子 我为以下几点编写代码 1:使用Objective-C 2:不使用扩展MTLTexture - (IBAction)onCapture:(id)sender { id<MTLTexture> lastDrawableDisplayed = [metalView.cu
ios9.1
中引用并通过MetalKit
制作模型查看器应用程序
我想从MTKView
制作屏幕快照图像(RGBA格式)。
但是,我只有黑色的图像
我该怎么办
谢谢你的阅读
代码:
自我解决
我发现了一个类似的例子
我为以下几点编写代码
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);
}
此错误已在以下修复中修复。
所以,我更改了MTKView的设置
metalView.framebufferOnly = false;
谢谢。请参阅:
对于swift 4.0
let lastDrawableDisplayed = metalView?.currentDrawable?.texture
if let imageRef = lastDrawableDisplayed?.toImage() {
let uiImage:UIImage = UIImage.init(cgImage: imageRef)
}
extension MTLTexture {
func bytes() -> UnsafeMutableRawPointer {
let width = self.width
let height = self.height
let rowBytes = self.width * 4
let p = malloc(width * height * 4)
self.getBytes(p!, bytesPerRow: rowBytes, from: MTLRegionMake2D(0, 0, width, height), mipmapLevel: 0)
return p!
}
func toImage() -> CGImage? {
let p = bytes()
let pColorSpace = CGColorSpaceCreateDeviceRGB()
let rawBitmapInfo = CGImageAlphaInfo.noneSkipFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
let bitmapInfo:CGBitmapInfo = CGBitmapInfo(rawValue: rawBitmapInfo)
let selftureSize = self.width * self.height * 4
let rowBytes = self.width * 4
let releaseMaskImagePixelData: CGDataProviderReleaseDataCallback = { (info: UnsafeMutableRawPointer?, data: UnsafeRawPointer, size: Int) -> () in
return
}
let provider = CGDataProvider(dataInfo: nil, data: p, size: selftureSize, releaseData: releaseMaskImagePixelData)
let cgImageRef = CGImage(width: self.width, height: self.height, bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: rowBytes, space: pColorSpace, bitmapInfo: bitmapInfo, provider: provider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)!
return cgImageRef
}
}
self.mtkView.framebufferOnly=否
- (UIImage *)imageWithCurrentTexture:(MTKView *)mtkView {
CIContext * context = [CIContext contextWithMTLDevice:mtkView.device];
CIImage *outputImage = [[CIImage alloc] initWithMTLTexture:mtkView.currentDrawable.texture options:@{kCIImageColorSpace:(__bridge_transfer id)CGColorSpaceCreateDeviceRGB()}];
CGImageRef cgImg = [context createCGImage:outputImage fromRect:CGRectMake(0, 0, [UIScreen mainScreen].nativeBounds.size.width, [UIScreen mainScreen].nativeBounds.size.height)];
UIImage *resultImg = [UIImage imageWithCGImage:cgImg scale:1.0 orientation:UIImageOrientationDownMirrored];
CGImageRelease(cgImg);
return resultImg;
}
let lastDrawableDisplayed = metalView?.currentDrawable?.texture
if let imageRef = lastDrawableDisplayed?.toImage() {
let uiImage:UIImage = UIImage.init(cgImage: imageRef)
}
extension MTLTexture {
func bytes() -> UnsafeMutableRawPointer {
let width = self.width
let height = self.height
let rowBytes = self.width * 4
let p = malloc(width * height * 4)
self.getBytes(p!, bytesPerRow: rowBytes, from: MTLRegionMake2D(0, 0, width, height), mipmapLevel: 0)
return p!
}
func toImage() -> CGImage? {
let p = bytes()
let pColorSpace = CGColorSpaceCreateDeviceRGB()
let rawBitmapInfo = CGImageAlphaInfo.noneSkipFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
let bitmapInfo:CGBitmapInfo = CGBitmapInfo(rawValue: rawBitmapInfo)
let selftureSize = self.width * self.height * 4
let rowBytes = self.width * 4
let releaseMaskImagePixelData: CGDataProviderReleaseDataCallback = { (info: UnsafeMutableRawPointer?, data: UnsafeRawPointer, size: Int) -> () in
return
}
let provider = CGDataProvider(dataInfo: nil, data: p, size: selftureSize, releaseData: releaseMaskImagePixelData)
let cgImageRef = CGImage(width: self.width, height: self.height, bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: rowBytes, space: pColorSpace, bitmapInfo: bitmapInfo, provider: provider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)!
return cgImageRef
}
}
- (UIImage *)imageWithCurrentTexture:(MTKView *)mtkView {
CIContext * context = [CIContext contextWithMTLDevice:mtkView.device];
CIImage *outputImage = [[CIImage alloc] initWithMTLTexture:mtkView.currentDrawable.texture options:@{kCIImageColorSpace:(__bridge_transfer id)CGColorSpaceCreateDeviceRGB()}];
CGImageRef cgImg = [context createCGImage:outputImage fromRect:CGRectMake(0, 0, [UIScreen mainScreen].nativeBounds.size.width, [UIScreen mainScreen].nativeBounds.size.height)];
UIImage *resultImg = [UIImage imageWithCGImage:cgImg scale:1.0 orientation:UIImageOrientationDownMirrored];
CGImageRelease(cgImg);
return resultImg;
}