我尝试了很多技术,例如使用 CIImage 或将数据复制到 uint_32ts 的缓冲区中,但它们都有自己的问题。到目前为止我发现的最简单的是:
extension MTLTexture {
func toImage() -> NSImage? {
assert (pixelFormat == .rgba32Float)
let rowByteCount = width * 16
let bytes = UnsafeMutablePointer<Float>.allocate(capacity: width * height * 4)
defer {
bytes.deallocate()
}
getBytes(bytes,
bytesPerRow: rowByteCount,
from: MTLRegion(origin: MTLOrigin(x: 0, y: 0, z: 0),
size: MTLSize(width: width, height: height, depth: 1)),
mipmapLevel: 0)
let context = CGContext(data: bytes,
width: width,
height: height,
bitsPerComponent: 32,
bytesPerRow: rowByteCount,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.floatComponents.rawValue)
guard let cgImage = context?.makeImage() else { print("Failed making cgImage"); return nil }
return NSImage(cgImage: cgImage, size: NSSize(width: width, height: height))
}
}
这将创建正确大小的图像,但它是完全透明的。有时使用预览放大时,图像中某些特征的轮廓会闪烁,但一旦图像渲染,它就会消失。我确保同步图像,并确保bytes
缓冲区具有非零值。我也尝试过使用 s 的缓冲区SIMD4<Float>
而不是Float
s,但它产生了相同的结果。