gpt4 book ai didi

ios - 如何将 bgra8Unorm iOS-Metal 纹理转换为 rgba8Unorm 纹理?

转载 作者:搜寻专家 更新时间:2023-11-01 06:01:43 24 4
gpt4 key购买 nike

我正在使用 iOS 11、XCode 9 和 Metal 2。我有一个像素格式为 bgra8UnormMTLTexture。我无法更改此像素格式,因为根据 pixelFormat documentation :

The pixel format for a Metal layer must be bgra8Unorm, bgra8Unorm_srgb, rgba16Float, BGRA10_XR, or bgra10_XR_sRGB.

其他像素格式不适合我的应用。

现在我想从纹理创建一个 UIImage。我可以通过从纹理 (doc) 中提取像素字节来做到这一点:

getBytes(_:bytesPerRow:bytesPerImage:from:mipmapLevel:slice:)

我正在处理这些字节以获得 UIImage:

func getUIImageForRGBAData(data: Data) -> UIImage? {
let d = (data as NSData)

let width = GlobalConfiguration.textureWidth
let height = GlobalConfiguration.textureHeight
let rowBytes = width * 4
let size = rowBytes * height

let pointer = malloc(size)
memcpy(pointer, d.bytes, d.length)

let colorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGContext(data: pointer, width: width, height: height, bitsPerComponent: 8, bytesPerRow: rowBytes, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)!

let imgRef = context.makeImage()
let image = UIImage(cgImage: imgRef!)
return image
}

但是,CGContext 假定像素采用 rgba8 格式。例如,红色纹理像素在最终的 UIImage 中是蓝色的。有没有办法在此过程中更改像素格式以获得正确的颜色?

最佳答案

此函数会将 .bgra8Unorm 纹理的字节调整为 RGBA 顺序,并根据数据创建一个 UIImage:

func makeImage(from texture: MTLTexture) -> UIImage? {
let width = texture.width
let height = texture.height
let bytesPerRow = width * 4

let data = UnsafeMutableRawPointer.allocate(bytes: bytesPerRow * height, alignedTo: 4)
defer {
data.deallocate(bytes: bytesPerRow * height, alignedTo: 4)
}

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

var buffer = vImage_Buffer(data: data, height: UInt(height), width: UInt(width), rowBytes: bytesPerRow)

let map: [UInt8] = [2, 1, 0, 3]
vImagePermuteChannels_ARGB8888(&buffer, &buffer, map, 0)

guard let colorSpace = CGColorSpace(name: CGColorSpace.genericRGBLinear) else { return nil }
guard let context = CGContext(data: data, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow,
space: colorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue) else { return nil }
guard let cgImage = context.makeImage() else { return nil }

return UIImage(cgImage: cgImage)
}

警告:此功能非常昂贵。每一帧都从 Metal 纹理创建图像几乎不是您想要做的。

关于ios - 如何将 bgra8Unorm iOS-Metal 纹理转换为 rgba8Unorm 纹理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48008714/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com