Avviso
Recentemente ho bisogno di scrivere di nuovo questa funzione, e ha scoperto che questo metodo non sembra più funzionare (almeno io non sono riuscito a farlo funzionare su iOS 10.3.1). L'immagine di output non si allineava. Suppongo che sia a causa del torto bytesPerRow
.
risposta originale
Il buffer è semplicemente una matrice di pixel, quindi in realtà è possibile elaborare il buffer direttamente senza utilizzare vimage. Il codice è scritto in Swift, ma penso che sia facile trovare l'equivalente Objective-C.
Swift 3
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
CVPixelBufferLockBaseAddress(imageBuffer, .readOnly)
let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
let cropWidth = 640
let cropHeight = 640
let colorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGContext(data: baseAddress, width: cropWidth, height: cropHeight, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue)
CVPixelBufferUnlockBaseAddress(imageBuffer, .readOnly)
// create image
let cgImage: CGImage = context!.makeImage()!
let image = UIImage(cgImage: cgImage)
Swift 2
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
CVPixelBufferLockBaseAddress(imageBuffer, 0)
let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
let cropWidth = 640
let cropHeight = 640
let colorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGBitmapContextCreate(baseAddress, cropWidth, cropHeight, 8, bytesPerRow, colorSpace, CGImageAlphaInfo.NoneSkipFirst.rawValue | CGBitmapInfo.ByteOrder32Little.rawValue)
// create image
let cgImage: CGImageRef = CGBitmapContextCreateImage(context)!
let image = UIImage(CGImage: cgImage)
Se si vuole ritagliare da qualche specifica posizione, aggiungere il seguente codice:
// calculate start position
let bytesPerPixel = 4
let startPoint = [ "x": 10, "y": 10 ]
let startAddress = baseAddress + startPoint["y"]! * bytesPerRow + startPoint["x"]! * bytesPerPixel
e il cambiamento lo baseAddress
in CGBitmapContextCreate
in startAddress
. Assicurati di non superare la larghezza e l'altezza dell'immagine di origine.
Hi Sten, ho cercato nella guida un esempio di ritaglio ma non è stato possibile correggerne uno, puoi dare un esempio su come ritagliare il buffer direttamente? – Eyal
v L'immagine non ha funzionalità di ritaglio – AlexeyVMP
È corretto che vimage non abbia una funzione di ritaglio dedicata. Ma impostando la dimensione del buffer è possibile applicare un ritaglio insieme essenzialmente a qualsiasi funzione, ad es. una scala. Ho aggiornato la mia risposta con un esempio – Sten