Как обрезать и перевернуть CVPixelBuffer и вернуть CVPixelBuffer? - PullRequest
0 голосов
/ 21 марта 2019

Я делаю быстрое видео приложение.

В моем приложении мне нужно обрезать и перевернуть CVPixelBuffer по горизонтали и вернуть результат, тип которого также является CVPixelBuffer.

Я попробовал несколько вещей.

Сначала я использовал 'CVPixelBufferCreateWithBytes'

func resizePixelBuffer(_ pixelBuffer: CVPixelBuffer, destSize: CGSize) 
-> CVPixelBuffer? 
{

  CVPixelBufferLockAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: O))

  let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer)
  let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
  let pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer)
  let width = CVPixelBufferGetWidth(pixelBuffer)
  let height = CVPixelBufferGetHeight(pixelBuffer)

  var destPixelBuffer: CVPixelBuffer?

  let topMargin = (height - destsize.height) / 2
  let leftMargin = (width - destsize.width) / 2 * 4   // bytesPerPixel
  let offset = topMargin * bytesPerRow + leftMargin

  CVPixelBufferCreateWithBytes(kCFAllocatorDefault, 
                               destSize.width, 
                               destSize.height, 
                               pixelFormat, 
                               baseAddress.advanced(by: offset),
                               bytesPerRow, 
                               nil, nil, nil, 
                               &destPixelBuffer)

  CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: O))

  return destPixelBuffer
)

С этим кодом я могу обрезать CVPixelBuffer напрямую и возвращать CVPixelBuffer.Однако я не мог понять, как перевернуть CVPlxelBuffer по горизонтали.

Итак, я попробовал другие решения.

Секунды, я преобразовал CVPixelBuffer в CIImage и затем вернулся в CVPixelBuffer

func resizePixelBuffer(_ pixelBuffer, destSize: CGSize) 
-> CVPixelBuffer?
{
  let bufferWidth = CVPixelBufferGetWidth(pixelBuffer)
  let bufferHeight = CVPixelBufferGetHeight(pixelBuffer)

  let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
  let rect = CGRect(x: (bufferWidth - destSize.width)/2, y: (bufferHeight - destSize.height)/2, width: destSize.width, height: destSize.height)
  let croppedImage = ciImage.cropped(to: rect)

  croppedImage.transformed(by: CGAffineTransform(translateX: -1, y: 0))

  var destPixelBuffer: CVPixelBuffer?
  CVPixelBufferCreate(kCFAllocatorDefault, destSize.width, destSize.height,
                      CVPixelBufferGetPixelFormatType(pixelBuffer), nil, 
                      &destPixelBuffer)

  CIContext().render(croppedImage, to: destPixelBuffer!, bounds: croppedImage.extent, croppedImage.colorSpace)

  return destPixelBuffer
}

Но результат не тот, который я ожидал.часть изображения черная, и я думаю, что CGAffineTransform не работает.

Наконец, я попытался преобразовать в CGImage

func resizePixelBuffer(_ pixelBuffer: CVPixelBuffer, destSize: CGSize)
-> CVPixelBuffer? 
{
  let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
  let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent)
  let rect = CGRect(x: (bufferWidth - destSize.width)/2, y: (bufferHeight - destSize.height)/2, width: destSize.width, height: destSize.height)

  let croppedImage = cgImage.cropping(to: rect)

  let width = croppedImage.width
  let height = croppedImage.height
  let pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer)

  var destPixelBuffer: CVPixelBuffer?
  CVPixelBufferCreate(kCFAllocatorDefault, width, height, pixelFormat, &destPixelBuffer)

  CVPixelBufferLockBaseAddress(destPixelBuffer, CVPixelBufferLockFlags(rawValue: 0))

  let destBaseAddress = CVPixelBufferGetBaseAddress(destPixelBuffer)
  let destBytesPerRow = CVPixelBufferGetBytesPerRow(destPixelBuffer)

  let context = CGContext(data: destBaseAddress, 
                          width: width, 
                          height: height, 
                          bitsPerComponent: 8, 
                          bytesPerRow: destBytesPerRow, 
                          space: croppedImage.colorSpace, 
                          bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue)

  context?.concatenate(__CGAffineTransformMake( 1, 0, 0, -1, 0, CGFloat(height)))

  context?.draw(croppedCgImage, in: CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height)))

  CVPixelBufferUnlockBaseAddress(srcPixelBuffer, CVPixelBufferLockFlags(rawValue: 0))

  return destPixelBuffer
}

В это время выходной пиксельный буфер полностью черный.

Не могувыяснить, как обрезать и перевернуть CVPixelBuffer и вернуть CVPixelBuffer.

Я думаю, что преобразование CIImage или CGImage - лучший способ, потому что есть много вещей, которые я могу сделать с этим форматом.

Но я не знаю, как преобразовать эти форматы обратно в CVPixelBuffer.

Пожалуйста, дайте мне знать, как это сделать.

...