首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >iOS缩放和裁剪CMSampleBufferRef/CVImageBufferRef

iOS缩放和裁剪CMSampleBufferRef/CVImageBufferRef
EN

Stack Overflow用户
提问于 2011-12-14 01:35:30
回答 5查看 24.5K关注 0票数 26

我正在使用AVFoundation并从AVCaptureVideoDataOutput获取样本缓冲区,我可以使用以下命令将其直接写入videoWriter:

代码语言:javascript
运行
复制
- (void)writeBufferFrame:(CMSampleBufferRef)sampleBuffer {
    CMTime lastSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);    
    if(self.videoWriter.status != AVAssetWriterStatusWriting)
    {
        [self.videoWriter startWriting];
        [self.videoWriter startSessionAtSourceTime:lastSampleTime];
    }

    [self.videoWriterInput appendSampleBuffer:sampleBuffer];

}

我现在想做的是裁剪和缩放CMSampleBufferRef中的图像,而不是将其转换为UIImage或CGImageRef,因为这会降低性能。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-04-08 21:02:36

如果您使用vimage,您可以直接处理缓冲区数据,而无需将其转换为任何图像格式。

outImg包含裁剪和缩放的图像数据。outWidthcropWidth之间的关系设置缩放。

代码语言:javascript
运行
复制
int cropX0, cropY0, cropHeight, cropWidth, outWidth, outHeight;

CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);                   
CVPixelBufferLockBaseAddress(imageBuffer,0);
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
                                    
vImage_Buffer inBuff;                       
inBuff.height = cropHeight;
inBuff.width = cropWidth;
inBuff.rowBytes = bytesPerRow;

int startpos = cropY0*bytesPerRow+4*cropX0;
inBuff.data = baseAddress+startpos;

unsigned char *outImg= (unsigned char*)malloc(4*outWidth*outHeight);
vImage_Buffer outBuff = {outImg, outHeight, outWidth, 4*outWidth};

vImage_Error err = vImageScale_ARGB8888(&inBuff, &outBuff, NULL, 0);
if (err != kvImageNoError) NSLog(@" error %ld", err);

因此,将cropX0 = 0cropY0 = 0以及cropWidthcropHeight设置为原始大小意味着没有裁剪(使用整个原始图像)。设置outWidth = cropWidthoutHeight = cropHeight将导致不缩放。请注意,inBuff.rowBytes应该始终是整个源代码缓冲区的长度,而不是裁剪后的长度。

票数 35
EN

Stack Overflow用户

发布于 2015-07-29 01:45:02

注意:我没有注意到原始问题也要求缩放。但不管怎样,对于那些只需要裁剪CMSampleBuffer的人,这里有一个解决方案。

缓冲区只是一个像素数组,因此您实际上可以直接处理缓冲区,而无需使用vImage。代码是用Swift编写的,但我认为很容易找到Objective-C的等价物。

首先,确保您的CMSampleBuffer是BGRA格式。如果不是,您使用的预设可能是YUV,并破坏稍后将使用的每行字节数。

代码语言:javascript
运行
复制
dataOutput = AVCaptureVideoDataOutput()
dataOutput.videoSettings = [
    String(kCVPixelBufferPixelFormatTypeKey): 
    NSNumber(value: kCVPixelFormatType_32BGRA)
]

然后,当您获得样本缓冲区时:

代码语言:javascript
运行
复制
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)

如果要从某个特定位置裁剪,请添加以下代码:

代码语言:javascript
运行
复制
// calculate start position
let bytesPerPixel = 4
let startPoint = [ "x": 10, "y": 10 ]
let startAddress = baseAddress + startPoint["y"]! * bytesPerRow + startPoint["x"]! * bytesPerPixel

并将CGContext()中的baseAddress更改为startAddress。请确保不超过原始图像的宽度和高度。

票数 10
EN

Stack Overflow用户

发布于 2011-12-14 02:32:28

您可以考虑使用CoreImage (5.0+)。

代码语言:javascript
运行
复制
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:CMSampleBufferGetImageBuffer(sampleBuffer)
                                           options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNull null], kCIImageColorSpace, nil]];
ciImage = [[ciImage imageByApplyingTransform:myScaleTransform] imageByCroppingToRect:myRect];
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8493583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档