iOS相机默认输出是个横向图,需要将其转为竖向,网上试了一些方法效率都不是很高,因为在做实时的图像算法,所以对FPS要求很高,用accelerate框架自己写了一个转竖向图的方法
基于CVPixelBuffer
写了一个extension
extension CVPixelBuffer {
public func ro() -> CVPixelBuffer? {
let size = CGRect(origin: CGPoint(x: 0, y: 0), size: self.size)
let inputImageRowBytes = CVPixelBufferGetBytesPerRow(self)
let imageChannels = 4
CVPixelBufferLockBaseAddress(self, CVPixelBufferLockFlags(rawValue: 0))
defer { CVPixelBufferUnlockBaseAddress(self, CVPixelBufferLockFlags(rawValue: 0)) }
// Finds the address of the upper leftmost pixel of the source area.
guard
let inputBaseAddress = CVPixelBufferGetBaseAddress(self)?.advanced(
by: Int(size.minY) * inputImageRowBytes + Int(size.minX) * imageChannels)
else {
return nil
}
// Crops given area as vImage Buffer.
var croppedImage = vImage_Buffer(
data: inputBaseAddress, height: UInt(self.size.height), width: UInt(self.size.width),
rowBytes: inputImageRowBytes)
// ======
let paddedRotatedRowBytes = Int(size.height) * imageChannels
guard let paddedRotatedAddress = malloc(Int(size.width) * paddedRotatedRowBytes) else {
return nil
}
// Allocates a vacant vImage buffer for resized image.
var paddedRotatedImage = vImage_Buffer(
data: paddedRotatedAddress,
height: UInt(size.width), width: UInt(size.height),
rowBytes: paddedRotatedRowBytes
)
var cg_transform = vImage_CGAffineTransform(a: 0.0, b: -1, c: 1, d: 0.0, tx: Double(0), ty: Double(size.width))
guard vImageAffineWarpCG_ARGB8888(&croppedImage, &paddedRotatedImage, nil, &cg_transform, clear_color, vImage_Flags(0)) == kvImageNoError else {
free(paddedRotatedAddress)
return nil
}
let releaseCallBack: CVPixelBufferReleaseBytesCallback = { mutablePointer, pointer in
if let pointer = pointer {
free(UnsafeMutableRawPointer(mutating: pointer))
}
}
var result: CVPixelBuffer?
// Converts the thumbnail vImage buffer to CVPixelBuffer
let conversionStatus = CVPixelBufferCreateWithBytes(
nil,
Int(size.height), Int(size.width),
CVPixelBufferGetPixelFormatType(self),
paddedRotatedAddress,
paddedRotatedRowBytes,
releaseCallBack,
nil,
nil,
&result
)
guard conversionStatus == kCVReturnSuccess else {
free(paddedRotatedAddress)
return nil
}
return result
}
}
调用方法也很简单,只需要直接.ro
即可
guard let rPixelBuffer = oPixelBuffer.ro() else {
return nil
}
viencoding.com版权所有,允许转载,但转载请注明出处和原文链接: https://viencoding.com/article/266