我在理解MTLTexture的pixelFormat如何与NSBitmapImageRep的属性相关时遇到问题?

特别是,我想使用金属计算内核(或内置的MPS方法)从另一个图像中减去图像并暂时保留负值 .

我有一个方法,从具有指定pixelFormat的位图创建MTLTexture:

func textureFrom(bitmap: NSBitmapImageRep, pixelFormat: MTLPixelFormat) -> MTLTexture? {

    guard !bitmap.isPlanar else {
        return nil
    }

    let region = MTLRegionMake2D(0, 0, bitmap.pixelsWide, bitmap.pixelsHigh)

    var textureDescriptor = MTLTextureDescriptor()
    textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: pixelFormat, width: bitmap.pixelsWide, height: bitmap.pixelsHigh, mipmapped: false)

    guard let texture = device.makeTexture(descriptor: textureDescriptor),
        let src = bitmap.bitmapData else { return nil }

    texture.replace(region: region, mipmapLevel: 0, withBytes: src, bytesPerRow: bitmap.bytesPerRow)
    return texture
}

然后我使用纹理进行一些计算(比如减法),当我完成后,我想得到一个位图 . 对于带有.r8Snorm pixelFormat的纹理,我想我能做到:

func bitmapFrom(r8SnormTexture: MTLTexture?) -> NSBitmapImageRep? {

    guard let texture = r8SnormTexture,
        texture.pixelFormat == .r8Snorm else { return nil }

    let bytesPerPixel = 1
    let imageByteCount = Int(texture.width * texture.height * bytesPerPixel)
    let bytesPerRow = texture.width * bytesPerPixel
    var src = [Float](repeating: 0, count: imageByteCount)

    let region = MTLRegionMake2D(0, 0, texture.width, texture.height)
    texture.getBytes(&src, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)

    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
    let colorSpace = CGColorSpaceCreateDeviceGray()

    let bitsPerComponent = 8
    let context = CGContext(data: &src, width: texture.width, height: texture.height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)

    guard let dstImageFilter = context?.makeImage() else {
        return nil
    }

    return NSBitmapImageRep(cgImage: dstImageFilter)
}

但负值不会被保留,它们会以某种方式被限制为零......

任何有关swift如何从位图到纹理和背面的见解都将受到赞赏 .