разобрался сам. Я до сих пор не знаю, почему CVPixelBufferCreateWithBytes
не работает, но я смог заставить его работать, создав буфер пикселей с CVPixelBufferCreate
и установив значение каждого адреса RGB один за другим. Это также должно быть лучшим подходом, так как мне не нужно сначала создавать массив.
Вот рабочий код для устройства и симулятора:
private func RGBAImage(width w: Int, height h: Int) -> UIImage? {
let width = w * Int(UIScreen.main.scale)
let height = h * Int(UIScreen.main.scale)
let bytesPerPixel = 4
// Create CVPixelBuffer with artificial data
var pxBuffer: CVPixelBuffer?
CVPixelBufferCreate(
kCFAllocatorDefault,
width,
height,
kCVPixelFormatType_32ARGB,
nil,
&pxBuffer)
guard let cvPxBuffer = pxBuffer else {
return nil
}
CVPixelBufferLockBaseAddress(cvPxBuffer, CVPixelBufferLockFlags(rawValue: 0))
let bufferWidth = Int(CVPixelBufferGetWidth(cvPxBuffer))
let bufferHeight = Int(CVPixelBufferGetHeight(cvPxBuffer))
let bytesPerRow = CVPixelBufferGetBytesPerRow(cvPxBuffer)
guard let baseAddress = CVPixelBufferGetBaseAddress(pxBuffer!) else {
return nil
}
for row in 0..<bufferHeight {
var pixel = baseAddress + row * bytesPerRow
for col in 0..<bufferWidth {
let alpha = pixel
alpha.storeBytes(of: UInt8(sin(Double(col) * 0.01 * .pi / Double(UIScreen.main.scale)) * 127 + 127), as: UInt8.self)
let red = pixel + 1
red.storeBytes(of: 255, as: UInt8.self)
let green = pixel + 2
green.storeBytes(of: 0, as: UInt8.self)
let blue = pixel + 3
blue.storeBytes(of: 0, as: UInt8.self)
pixel += bytesPerPixel;
}
}
CVPixelBufferUnlockBaseAddress(cvPxBuffer, CVPixelBufferLockFlags(rawValue: 0))
// Generate image from CVPixelBuffer
let ciImage = CIImage(cvImageBuffer: cvPxBuffer)
return UIImage(ciImage: ciImage, scale: UIScreen.main.scale, orientation: .up)
}