Примечание: я не заметил, что исходный вопрос также требовал масштабирования. Но в любом случае, для тех, кому просто нужно обрезать CMSampleBuffer, вот решение.
Буфер - это просто массив пикселей, так что вы можете непосредственно обработать буфер без использования vImage. Код написан на Swift, но я думаю, что легко найти эквивалент Objective-C.
Сначала убедитесь, что ваш CMSampleBuffer имеет формат BGRA. Если нет, то предустановка, которую вы используете, - это, вероятно, YUV, и испортит количество байтов в строках, которые позже будут использованы.
dataOutput = AVCaptureVideoDataOutput()
dataOutput.videoSettings = [
String(kCVPixelBufferPixelFormatTypeKey):
NSNumber(value: kCVPixelFormatType_32BGRA)
]
Затем, когда вы получите буфер сэмпла:
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)
// now the cropped image is inside the context.
// you can convert it back to CVPixelBuffer
// using CVPixelBufferCreateWithBytes if you want.
CVPixelBufferUnlockBaseAddress(imageBuffer, .readOnly)
// create image
let cgImage: CGImage = context!.makeImage()!
let image = UIImage(cgImage: cgImage)
Если вы хотите обрезать из определенной позиции, добавьте следующий код:
// calculate start position
let bytesPerPixel = 4
let startPoint = [ "x": 10, "y": 10 ]
let startAddress = baseAddress + startPoint["y"]! * bytesPerRow + startPoint["x"]! * bytesPerPixel
и измените baseAddress
в CGBitmapContextCreate
на startAddress
. Убедитесь, что ширина и высота исходного изображения не превышают
.