Printing 是否有方法将金属输出捕获为位图或其他适合打印的格式?
我正在使用MTKit将一个应用程序从OpenGL转换为Metal。最初的应用程序允许用户打印正在查看的OpenGL生成的屏幕(我也用核心图形完成了这项工作)。我想用金属做同样的事。我原以为找到解决问题的办法或至少找到解决问题的方法很容易,但我被卡住了。有没有人解决了这个问题,或者有没有人对我应该寻找什么有任何线索 我是一个经验丰富的Mac程序员(我更喜欢Objective-C解决方案,但我在其他方面做了一些工作),我是Metal的高级新手Printing 是否有方法将金属输出捕获为位图或其他适合打印的格式?,printing,bitmap,metal,Printing,Bitmap,Metal,我正在使用MTKit将一个应用程序从OpenGL转换为Metal。最初的应用程序允许用户打印正在查看的OpenGL生成的屏幕(我也用核心图形完成了这项工作)。我想用金属做同样的事。我原以为找到解决问题的办法或至少找到解决问题的方法很容易,但我被卡住了。有没有人解决了这个问题,或者有没有人对我应该寻找什么有任何线索 我是一个经验丰富的Mac程序员(我更喜欢Objective-C解决方案,但我在其他方面做了一些工作),我是Metal的高级新手 MacOS 10.15.3,所有MacBook 斯威夫
- MacOS 10.15.3,所有MacBook
- 斯威夫特5
- 代码11.2.1
framebufferOnly=false代码>
bool-takeScreenshot=true;
///每当视图需要渲染帧时调用
-(void)drawInMTKView:(非空MTKView*)视图
{
//为当前可绘制对象的每个渲染过程创建新的命令缓冲区
id commandBuffer=[\u commandQueue commandBuffer];
commandBuffer.label=@“MyCommand”;
//获取从视图的可绘制纹理生成的renderPassDescriptor
MTLRenderPassDescriptor*renderPassDescriptor=view.currentRenderPassDescriptor;
id currentSwapChainTexture=view.currentDrawable.texture;
//您的渲染代码。。。
[commandBuffer addCompletedHandler:^(id cb)
{
如果(截图)
{
保存纹理(currentSwapChainTexture);
截图=假;
}
}];
//在此处完成渲染并将命令缓冲区推送到GPU
[命令缓冲区提交];
//CPU-GPU同步
if(截图)[commandBuffer waituntlcompleted];
保存纹理功能:
void SaveTexture(id<MTLTexture> texture)
{
int width = (int) texture.width;
int height = (int) texture.height;
int bytePerPixel = 4;
int bytesPerRow = width * bytePerPixel;
int bytesCount = width * height * bytePerPixel;
int bitsPerComponent = 8;
int bitsPerPixel = 32;
void *imageBytes = malloc(bytesCount);
void *destBytes = malloc(bytesCount);
MTLRegion mtlregion = MTLRegionMake2D(0, 0, width, height);
[texture getBytes:imageBytes bytesPerRow:bytesPerRow fromRegion:mtlregion mipmapLevel:0];
vImage_Buffer src;
src.data = imageBytes;
src.width = width;
src.height = height;
src.rowBytes = bytesPerRow;
vImage_Buffer dest;
dest.data = destBytes;
dest.width = width;
dest.height = height;
dest.rowBytes = bytesPerRow;
// BGRA -> RGBA (Swap)
const uint8_t map[4] = {2, 1, 0, 3};
vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags);
CGColorSpaceRef cgColorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3); //kCGColorSpaceSRGB - For sRGB
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
CGContextRef context = CGBitmapContextCreate(destBytes, width, height, bitsPerComponent, bytesPerRow, cgColorSpaceRef, bitmapInfo);
CGImageRef cgImage = CGBitmapContextCreateImage(context);
// Your NSImage
NSImage * image = [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize];
// Save to Photos
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^
{
[PHAssetCreationRequest creationRequestForAssetFromImage: image];
}
completionHandler:^(BOOL success, NSError * error)
{
if(success) printf("Success \n");
}];
free(imageBytes);
free(destBytes);
CGColorSpaceRelease(cgColorSpaceRef);
CGContextRelease(context);
CGImageRelease(cgImage);
texture = nil;
}
void SaveTexture(id纹理)
{
int width=(int)texture.width;
int height=(int)texture.height;
int bytePerPixel=4;
int bytesPerRow=宽度*bytePerPixel;
int字节数=宽度*高度*字节像素;
int bitsPerComponent=8;
int bitsPerPixel=32;
void*imageBytes=malloc(字节数);
void*destBytes=malloc(字节数);
MTLRegion MTLRegion=MTLRegionMake2D(0,0,宽度,高度);
[texture getBytes:imageBytes bytesPerRow:bytesPerRow fromRegion:mtlregion mipmapLevel:0];
vImage_缓冲区src;
src.data=imageBytes;
src.width=宽度;
src.height=高度;
src.rowBytes=bytesPerRow;
vImage_缓冲区目的地;
dest.data=destBytes;
dest.width=宽度;
目的地高度=高度;
dest.rowBytes=bytesPerRow;
//BGRA->RGBA(交换)
常数映射[4]={2,1,0,3};
vImagePermuteChannels_argb888(&src,&dest,map,kvImageNoFlags);
CGColorSpaceRef CGColorSpaceRef=CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3);//kCGColorSpaceSRGB-用于sRGB
CGBitmapInfo bitmapInfo=KCGIMAGEAlphaPremultipledLast | kCGBitmapByteOrder32Big;
CGContextRef context=CGBitmapContextCreate(destBytes、宽度、高度、bitsPerComponent、bytesPerRow、cgColorSpaceRef、bitmapInfo);
CGImageRef cgImage=CGBitmapContextCreateImage(上下文);
//你的NSImage
NSImage*image=[[NSImage alloc]initWithCGImage:cgImage size:NSZeroSize];
//保存到照片
[[PHPhotoLibrary sharedPhotoLibrary]性能更改:^
{
[PhaseSetCreationRequest creationRequestForAssetFromImage:image];
}
completionHandler:^(布尔成功,N错误*错误)
{
if(success)printf(“success\n”);
}];
空闲(imageBytes);
空闲(字节);
cgColorSpacereLase(cgColorSpaceRef);
CGContextRelease(上下文);
CGImageRelease(cgImage);
纹理=零;
}
你到底需要打印什么,屏幕还是纹理?首先是屏幕。一般来说,我以后可能需要打印屏幕外的纹理。但我发现,对于你下面的回答,这并不重要;-)谢谢!稍后再试。效果很好。非常感谢,0xBFE1A8。感谢你的快速回答-我非常感谢你的关注。有e nit:当然,其中一个必须强制对视图进行刷新循环,以引发完成处理程序的执行,这对于SetNeedsDisplay来说足够简单。显示结束时,我手头有一个漂亮的CGImage,但为了一致性,我真的想打印它,而不是存档它。当然,我可以创建视图并仅在ma上打印在线程中,所以需要使用dispatch_async运行打印。有点复杂,但它可以工作。
void SaveTexture(id<MTLTexture> texture)
{
int width = (int) texture.width;
int height = (int) texture.height;
int bytePerPixel = 4;
int bytesPerRow = width * bytePerPixel;
int bytesCount = width * height * bytePerPixel;
int bitsPerComponent = 8;
int bitsPerPixel = 32;
void *imageBytes = malloc(bytesCount);
void *destBytes = malloc(bytesCount);
MTLRegion mtlregion = MTLRegionMake2D(0, 0, width, height);
[texture getBytes:imageBytes bytesPerRow:bytesPerRow fromRegion:mtlregion mipmapLevel:0];
vImage_Buffer src;
src.data = imageBytes;
src.width = width;
src.height = height;
src.rowBytes = bytesPerRow;
vImage_Buffer dest;
dest.data = destBytes;
dest.width = width;
dest.height = height;
dest.rowBytes = bytesPerRow;
// BGRA -> RGBA (Swap)
const uint8_t map[4] = {2, 1, 0, 3};
vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags);
CGColorSpaceRef cgColorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3); //kCGColorSpaceSRGB - For sRGB
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
CGContextRef context = CGBitmapContextCreate(destBytes, width, height, bitsPerComponent, bytesPerRow, cgColorSpaceRef, bitmapInfo);
CGImageRef cgImage = CGBitmapContextCreateImage(context);
// Your NSImage
NSImage * image = [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize];
// Save to Photos
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^
{
[PHAssetCreationRequest creationRequestForAssetFromImage: image];
}
completionHandler:^(BOOL success, NSError * error)
{
if(success) printf("Success \n");
}];
free(imageBytes);
free(destBytes);
CGColorSpaceRelease(cgColorSpaceRef);
CGContextRelease(context);
CGImageRelease(cgImage);
texture = nil;
}