2016-10-08 3 views
0

Я собираюсь применить матрицу к CGImage, используя фреймворк Accelerate.Как использовать vImageMatrixMultiply в Swift 3?

Во-первых, я преобразовал 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 в Суданских Красном Полумесяце и dests аргументов, и я получил ошибку компиляции с описанием:

Невозможно преобразовать значение типа «vImage_Buffer» к ожидаемому типу аргумента «UnsafePointer < vImage_Buffer >?»

Я искал о преобразовании "vImage_Buffer" в "UnsafePointer < vImage_Buffer>?" но не нашли ответа.

Так что я хотел бы знать, как преобразовать "vImage_Buffer" в "UnsafePointer < vImage_Buffer>?", Или как непосредственно создавать "UnsafePointer < vImage_Buffer>?" из CGImage или любые другие способы правильного использования vImageMatrixMultiply.

ответ

0

Я не использовал vImageMatrixMultiply_PlanarF, но в соответствии с Документами заголовка и подписи функции, вам необходимо передать указатели на нескольких vImage_Buffer с для первых двух параметров, 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) 
      ) 
     } 
    } 
+0

Большое спасибо за код. Это намного сложнее, чем я думал ... – rdeepy

+0

@rdeepy, на самом деле, я использовал очень небольшую часть ракурса Accelerate, но это сложнее, чем любой другой, который я испытал. И если вы действительно примете некоторые части кода выше, пожалуйста, скажите мне. Вам понадобится код завершения после использования ... – OOPer

+0

Спасибо. Я использовал vDSP, но я впервые использовал vImage. Я начал проверять Core Image, и теперь я думаю, что CIColorMatrix удовлетворит мое требование более легко. – rdeepy

Смежные вопросы