Swift 5
I had the same problem and ended up with the following solution. My CVPixelBuffer
had dimensionality 68 x 68
, which can be inspected by
CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
print(CVPixelBufferGetWidth(pixelBuffer))
print(CVPixelBufferGetHeight(pixelBuffer))
You also have to know the bytes per row:
print(CVPixelBufferGetBytesPerRow(pixelBuffer))
which in my case was 320.
Furthermore, you need to know the data type of your pixel buffer, which was Float32
for me.
I then constructed a byte buffer and read the bytes consecutively as follows (remember to lock the base address as shown above):
var byteBuffer = unsafeBitCast(CVPixelBufferGetBaseAddress(pixelBuffer), to: UnsafeMutablePointer<Float32>.self)
var pixelArray: Array<Array<Float>> = Array(repeating: Array(repeating: 0, count: 68), count: 68)
for row in 0...67{
for col in 0...67{
pixelArray[row][col] = byteBuffer.pointee
byteBuffer = byteBuffer.successor()
}
byteBuffer = byteBuffer.advanced(by: 12)
}
CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
You might wonder about the part byteBuffer = byteBuffer.advanced(by: 12)
. The reason why we have to do this is as follows.
We know that we have 320 bytes per row. However, our buffer has width 68 and the data type is Float32
, e.g. 4 bytes per value. That means that we virtually only have 272
bytes per row, followed by zero-padding. This zero-padding probably has memory layout reasons.
We, therefore, have to skip the last 48 bytes in each row which is done by byteBuffer = byteBuffer.advanced(by: 12)
(12*4 = 48
).
This approach is somewhat different from other solutions as we use pointers to the next byteBuffer
. However, I find this easier and more intuitive.