Ios 转换为纹理时缺少UIImage的透明度
我将UIImage转换为纹理,然后将该纹理转换为UIImage。透明区域将替换为黑色 我用于将UIImage转换为纹理的函数Ios 转换为纹理时缺少UIImage的透明度,ios,swift,metal,metalkit,Ios,Swift,Metal,Metalkit,我将UIImage转换为纹理,然后将该纹理转换为UIImage。透明区域将替换为黑色 我用于将UIImage转换为纹理的函数 func imageToTexture(imageNamed: String, device: MTLDevice) -> MTLTexture { let bytesPerPixel = 4 let bitsPerComponent = 8 var image = UIImage(named: imageNamed)! let
func imageToTexture(imageNamed: String, device: MTLDevice) -> MTLTexture {
let bytesPerPixel = 4
let bitsPerComponent = 8
var image = UIImage(named: imageNamed)!
let width = Int(image.size.width)
let height = Int(image.size.height)
let bounds = CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height))
var rowBytes = width * bytesPerPixel
var colorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: rowBytes, space: colorSpace, bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue).rawValue)
context!.clear(bounds)
context?.translateBy(x: CGFloat(width), y: CGFloat(height))
// CGContextTranslateCTM(context!, CGFloat(width), CGFloat(height))
context?.scaleBy(x: -1.0, y: -1.0)
// CGContextScaleCTM(context!, -1.0, -1.0)
context?.draw(image.cgImage!, in: bounds)
// CGContextDrawImage(context, bounds, image.CGImage)
var texDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .bgra8Unorm , width: width, height: height, mipmapped: true)
var texture = device.makeTexture(descriptor: texDescriptor)
texture?.label = imageNamed
// var pixelsData = CGBitmapContextGetData(context!)
var pixelsData = context?.data
var region = MTLRegionMake2D(0, 0, width, height)
texture?.replace(region: region, mipmapLevel: 0, withBytes: pixelsData!, bytesPerRow: rowBytes)
makeImage(from: texture!)
return texture!
}
将纹理转换为图像的函数。将UIImage更改为纹理后,我正在调用将其转换回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 }
let x = UIImage(cgImage: cgImage)
return x;
}
此处,输出图像在透明区域为黑色。我不知道我哪里搞砸了。您正在使用
CGImageAlphaInfo.noneSkipLast
创建位图上下文。您明确告诉它忽略数据中的alpha分量。此外,您可能应该直接从数据创建CGImage
,而不是通过位图上下文。Ken所说的是最可能的原因。要扩展它,我觉得imageToTexture
函数很好,请尝试在makeImage
中使用CGImageAlphaInfo.premultipledLast
来匹配imageToTexture
。旁注:如果您只是在进行原型设计,您可能需要考虑使用CoreImage将UIImage
渲染为CVPixelBuffer
,将CVPixelBufferMetalCompatibilityKey
设置为true时从CVPixelBuffer池
生成的。您可以使用CVMetalTextureCacheCreateTextureFromImage()
获取映射绑定到与该像素缓冲区相同内存的MTLTexture
。“以我的经验来说,这让事情变得更容易了。”肯特·霍马斯说,谢谢