使用偏移缩放 vImage_Buffer - Cocoa Objective C

Scale vImage_Buffer with offset - Cocoa Objective C

我正在尝试使用 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);

No pun intended, but you should really read Accelerate.framework documentation.

malloc替换为calloc ...

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

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

vImage_Buffer.rowBytes 文档说了什么?

The distance, in bytes, between the start of one pixel row and the next in an image, including any unused space between them.

The rowBytes value must be at least the width multiplied by the pixel size, where the pixel size depends on the image format. You can provide a larger value, in which case the extra bytes will extend beyond the end of each row of pixels. You may want to do so either to improve performance, or to describe an image within a larger image without copying the data. The extra bytes aren't considered part of the image represented by the vImage buffer. When allocating floating-point data for images, keep the data 4-byte aligned by allocating bytes as integer multiples of 4. For best performance, allocate bytes as integer multiples of 16.

看下图:

红圈(top/left角)从缓冲区开始offset,我们计算一下(假设每个像素4字节):

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

图像中一个像素行的开始与下一个像素行之间的距离(以字节为单位),包括它们之间任何未使用的 spacefinalWidth * 4(另外两个圆圈之间的红线)。

让我们修复 destBuffer:

vImage_Buffer destBuffer = {
    (void *)destData+offset,
    aspectRect.size.height,
    aspectRect.size.width,
    finalWidth * 4
};