使用偏移量缩放 vImage_Buffer - Cocoa Objective C

Posted

技术标签:

【中文标题】使用偏移量缩放 vImage_Buffer - Cocoa Objective C【英文标题】:Scale vImage_Buffer with offset - Cocoa Objective C 【发布时间】:2020-08-07 13:40:04 【问题描述】:

我正在尝试使用 vImage_Buffer 缩放图像,下面的代码对我有用。我的麻烦是我想保持源图像的纵横比,所以我可能需要添加xOffsetyOffset。下面的代码仅适用于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);

【问题讨论】:

【参考方案1】:

没有双关语,但您确实应该阅读 Accelerate.framework 文档。

malloc 替换为calloc ...

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
;

【讨论】:

非常感谢。它就像一个魅力。当我从目标缓冲区创建 CVImagebufferRef 时,x0ffset 的图像的颜色空间不同。它非常适合yOffset 的图像。你有什么想法吗? 我找到了原因。这是因为原始值是浮点数,我们需要将其转换为size_t,因为我们正在处理内存。用相同的方式更新了答案。

以上是关于使用偏移量缩放 vImage_Buffer - Cocoa Objective C的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 滑动、缩放控件

Canvas自定义文字旋转缩放渲染

如何使用加速框架(vImage)缩放灰度图像

如何计算偏移量以绘制到画布中应用了比例变换的最近像素?

C 语言结构体 ( 结构体偏移量计算 | 代码示例 )

如果数组大小发生变化以及定义的宏如何在此处计算偏移量,为啥 C 结构中的字符数组的偏移量会有所不同? [复制]