【发布时间】:2019-08-12 16:53:42
【问题描述】:
我正在制作一个快速的视频应用程序。
在我的应用程序中,我需要裁剪和水平翻转 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。
请告诉我该怎么做。
【问题讨论】:
-
我不是专家。 (类似于 IANAL。)话虽如此,这是我的想法 - 仅此而已,想法。 (1) 除非您绝对必须坚持使用 CoreImage。为什么要引入复杂性? (2) 听起来你已经弄清楚了一半 - 裁剪。除非您有任何性能问题,否则请坚持下去。 (3)留下“翻转”,如果我理解你有工作但有“部分黑色”的图像。那么与之合作?从方形图像开始。它会去除黑色吗?如果是这样,则使用非方形图像。我认为你很接近......并且真的认为你想多了。
-
你能解决这个问题吗?
-
你找到解决办法了吗?
标签: swift crop cgimage ciimage cvpixelbuffer