Search code examples
iosaccelerate-framework

Artifacts when scaling Ycbcr (420f) with Accelerate


I cannot find any documentation or example on how to resize Ycbcr biplanar, supposedly the main format you should use on iOS according to Apple. I tried to resize the two planes like this:

    // resize luma
    vImage_Buffer originalYBuffer = { CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0), CVPixelBufferGetHeightOfPlane(pixelBuffer, 0), CVPixelBufferGetWidthOfPlane(pixelBuffer, 0), CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0) };
    vImage_Buffer resizedYBuffer;
    vImageBuffer_Init(&resizedYBuffer, IMAGE_HEIGHT, IMAGE_WIDTH, 8 * sizeof(Pixel_8), kvImageNoFlags);
    error = vImageScale_Planar8(&originalYBuffer, &resizedYBuffer, NULL, kvImageNoFlags);
    assert(!error);
    cv::Mat grey(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1, resizedYBuffer.data);

    // resize chroma
    vImage_Buffer originalUVBuffer = { CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1), CVPixelBufferGetHeightOfPlane(pixelBuffer, 1), CVPixelBufferGetWidthOfPlane(pixelBuffer, 1), CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1) };
    vImage_Buffer resizedUVBuffer;
    vImageBuffer_Init(&resizedUVBuffer, IMAGE_HEIGHT / 2, IMAGE_WIDTH / 2, 8 * sizeof(Pixel_16U), kvImageNoFlags);
    error = vImageScale_Planar8(&originalUVBuffer, &resizedUVBuffer, NULL, kvImageNoFlags);
    assert(!error);

But the colors are totally borked. The luma channel works by itself, so it's a problem with the chroma. This format is supposed to use 2 bytes for chroma, although not totally sure. If I use vImageScale_Planar8 I get half of the screen green, else if I use vImageScale_Planar16U I get blue/yellow noise all over the image.


Solution

  • Got the andwer from Apple guys: vImageScale_Planar8 cannot operate on the UV plane, because it is interleaved. The only solution is to split into two independent planes.