1

我正在尝试使用 vImage_Buffer 缩放图像,下面的代码对我有用。我的麻烦是我想保持源图像的纵横比,所以我可能需要添加一个xOffsetor yOffset。以下代码仅适用于yOffset. 我如何也可以缩放图像xOffset。我无法进行缩放,CGContext因为这会影响性能。

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    
    size_t finalWidth = 1080;
    size_t finalHeight = 720;
    
    size_t sourceWidth = CVPixelBufferGetWidth(imageBuffer);
    size_t sourceHeight = CVPixelBufferGetHeight(imageBuffer);
    
    CGRect aspectRect = AVMakeRectWithAspectRatioInsideRect(CGSizeMake(sourceWidth, sourceHeight), CGRectMake(0, 0, finalWidth, finalHeight));
    
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);

    size_t startY = aspectRect.origin.y;
    size_t yOffSet = (finalWidth*startY*4);
    CVPixelBufferLockBaseAddress(imageBuffer, 0);
    
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
    
    void* destData = malloc(finalHeight * finalWidth * 4);
    
    vImage_Buffer srcBuffer = { (void *)baseAddress, sourceHeight, sourceWidth, bytesPerRow};
    vImage_Buffer destBuffer = { (void *)destData+yOffSet, aspectRect.size.height, aspectRect.size.width, aspectRect.size.width * 4};
    
    vImage_Error err = vImageScale_ARGB8888(&srcBuffer, &destBuffer, NULL, 0);
4

1 回答 1

2

没有双关语的意思,但你真的应该阅读 Accelerate.framework 文档。

替换malloccalloc...

void *destData = calloc(finalHeight * finalWidth * 4);

...将所有字节归零(或使用任何其他方式)。

文档是怎么vImage_Buffer.rowBytes说的?

图像中一个像素行的开头和下一个像素行之间的距离(以字节为单位),包括它们之间的任何未使用空间。

rowBytes 值必须至少是宽度乘以像素大小,其中像素大小取决于图像格式。您可以提供更大的值,在这种情况下,额外的字节将超出每行像素的末尾。您可能希望这样做是为了提高性能,或者在不复制数据的情况下在更大的图像中描述图像。额外的字节不被视为由 vImage 缓冲区表示的图像的一部分。为图像分配浮点数据时,通过将字节分配为 4 的整数倍来保持数据 4 字节对齐。为获得最佳性能,请将字节分配为 16 的整数倍。

看下图:

在此处输入图像描述

红色圆圈(上/左角)是offset从缓冲区开始的,让我们计算一下(假设每个像素 4 个字节):

size_t startY = aspectRect.origin.y;
size_t startX = aspectRect.origin.x;
size_t offset = 4 * (finalWidth * startY + startX);

图像中一个像素行的开头和下一个像素行之间的距离(以字节为单位),包括它们之间的任何未使用空间finalWidth * 4其他两个圆圈之间的红线)。

让我们修复destBuffer

vImage_Buffer destBuffer = {
    (void *)destData+offset,
    aspectRect.size.height,
    aspectRect.size.width,
    finalWidth * 4
};
于 2020-08-07T14:18:48.317 回答