Как использовать vImageMatrixMultiply в Swift 3?
Я собираюсь применить матрицу к CGImage, используя Accelerate Framework.
Сначала я конвертировал CGImage в vImage_Buffer,
let bitmapInfo: CGBitmapInfo = [ .floatComponents,
CGBitmapInfo( rawValue: CGImageAlphaInfo.none.rawValue ),
.byteOrder32Little ]
var format = vImage_CGImageFormat( bitsPerComponent: 32,
bitsPerPixel: 32 * 3,
colorSpace: nil,
bitmapInfo: FloatBitmapInfo,
version: 0,
decode: nil,
renderingIntent: .defaultIntent )
var inputBuffer = vImage_Buffer()
vImageBuffer_InitWithCGImage( &inputBuffer,
&format,
nil,
aCGImage, // input CGImage
UInt32( kvImageNoFlags ) )
затем попытался применить vImageMatrixMultiply.
vImageMatrixMultiply_PlanarF( &inputBuffer, // srcs
&outputBuffer, // dests
3, // src_planes
3, // dest_planes
aMatrix, // applying matrix
&preBias, // pre_bias
&postBias, // post_bias
UInt32( kvImageNoFlags ) )
Но vImageMatrixMultiply не принимает vImage_Buffer в качестве аргументов srcs и dests, и я получил ошибку компиляции, описывающую:
Невозможно преобразовать значение типа "vImage_Buffer" в ожидаемый тип аргумента "UnsafePointer
?"
Я искал о преобразовании "vImage_Buffer" в "UnsafePointer
Поэтому я хотел бы знать, как преобразовать "vImage_Buffer" в "UnsafePointer
1 ответ
Я не использовал vImageMatrixMultiply_PlanarF
, но в соответствии с документами заголовка и сигнатурой функции, вам нужно передать указатели на несколько vImage_Buffer
s для первых двух параметров, srcs
а также dests
,
Когда вам нужно передать несколько значений через UnsafeMutablePointer<T>
вы обычно объявляете переменную [T]
и передать его в качестве аргумента inout.
В твоем случае T
знак равноUnsafePointer<vImage_Buffer>?
, поэтому вам нужно объявить переменную типа [UnsafePointer<vImage_Buffer>?]
, И каждый указатель, содержащийся в массиве, должен указывать на vImage_Buffer
,
ОБНОВЛЕНО Старый код в этом ответе использовался with...
методы в плохой манере. Пожалуйста, попробуйте с обновленным кодом.
Таким образом, вам может понадобиться написать что-то вроде этого:
//Prepare 3 vImage_Buffers for source planes
//(vImageConvert_RGBFFFtoPlanarF)
//You are responsible for filling out the height, width, and rowBytes fields of this structure, and for allocating a data buffer of the appropriate size.
let inputBuffers: [vImage_Buffer] = (0...2).map {_ in
var imageBuf = vImage_Buffer()
imageBuf.width = inputBuffer.width
imageBuf.height = inputBuffer.height
imageBuf.rowBytes = Int(imageBuf.width) * MemoryLayout<Float>.size
imageBuf.data = malloc(imageBuf.rowBytes * Int(imageBuf.height))
return imageBuf
}
//Prepare 3 vImage_Buffers for destination planes
//(vImageMatrixMultiply_PlanarF)
//You are responsible for filling out the height, width, and rowBytes fields of these structures, and for allocating data buffers of the appropriate size.
let outputBuffers: [vImage_Buffer] = (0...2).map {_ in
var imageBuf = vImage_Buffer()
imageBuf.width = inputBuffer.width
imageBuf.height = inputBuffer.height
imageBuf.rowBytes = Int(imageBuf.width) * MemoryLayout<Float>.size
imageBuf.data = malloc(imageBuf.rowBytes * Int(imageBuf.height))
return imageBuf
}
//`aMatrix` needs to hold `src_planes`x`dest_planes` elements
let aMatrix: [Float] = [0.5, 0.25, 0.25, 0.25, 0.5, 0.25, 0.25, 0.25, 0.5]
var preBias: Float = 0.0
var postBias: Float = 0.0
//You need to use pointers or BufferPointers inside the closure, should not take them out of the closure
inputBuffers.withUnsafeBufferPointer {inputBuffersBP in
outputBuffers.withUnsafeBufferPointer {outputBuffersBP in
//Prepare pointer array pointing each vImage_Buffer
var inputBufferPointers: [UnsafePointer<vImage_Buffer>?] =
inputBuffers.withUnsafeBufferPointer {inputBuffersBP in
(0...2).map{inputBuffersBP.baseAddress! + $0}
}
//If you want to use PlanarF format, you need to split RGB into distict vImage_Buffers
vImageConvert_RGBFFFtoPlanarF(
&inputBuffer,
inputBufferPointers[0]!,
inputBufferPointers[1]!,
inputBufferPointers[2]!,
UInt32(kvImageNoFlags)
)
//Prepare pointer array pointing each vImage_Buffer
var outputBufferPointers: [UnsafePointer<vImage_Buffer>?] =
outputBuffers.withUnsafeBufferPointer {outputBuffersBP in
(0...2).map{outputBuffersBP.baseAddress! + $0}
}
//All these things prepared properly, you can call `vImageMatrixMultiply_PlanarF` like this...
vImageMatrixMultiply_PlanarF(
&inputBufferPointers, // srcs
&outputBufferPointers, // dests
3, // src_planes
3, // dest_planes
aMatrix, // applying matrix
&preBias, // pre_bias
&postBias, // post_bias
UInt32(kvImageNoFlags)
)
}
}