Эквивалент MPSImageLanczosScale до MacOS 10.13

Я использую MPSImageLanczosScale для масштабирования текстуры изображения (инициированной из CVPixelBufferRef) с использованием Metal framework. Проблема в том, что MPSImageLanczosScale доступен только с 10.13. Но мое приложение поддерживает с 10.11. Я не могу перестать поддерживать более ранние версии ОС, так как многие пользователи все еще используют эти версии. Есть ли альтернативный способ масштабирования изображения с помощью Metal (или любым другим способом)?

Примечание. Я использую Metal, так как мне нужно масштабирование изображения на основе графического процессора, чтобы избежать использования процессора. Поэтому я ищу решение для масштабирования изображения на основе графического процессора.

Включая текущую реализацию для справки.

-(CVImageBufferRef)rescaleGPU:(CVImageBufferRef)sourceImageBuffer {
    CVReturn error;

    CGFloat backingScaleFactor = [[NSScreen mainScreen] backingScaleFactor];

    CVMetalTextureRef textureRef;
    error = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _videoTextureCache, sourceImageBuffer, NULL, MTLPixelFormatBGRA8Unorm, g_screenWidth * backingScaleFactor, g_screenHeight * backingScaleFactor, 0, &textureRef);

    id <MTLTexture> _metalTexture = CVMetalTextureGetTexture(textureRef);

    id<MTLTexture> _destinationTexture = [_device newTextureWithDescriptor:self.textureDescriptor];

    id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
    [self.scaleFilter encodeToCommandBuffer:commandBuffer sourceTexture:_metalTexture destinationTexture:_destinationTexture];

    id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];
    [blitEncoder synchronizeTexture:_destinationTexture slice:0 level:0];
    [blitEncoder endEncoding];

    [commandBuffer commit];
    [commandBuffer waitUntilCompleted];
    

    void* destData = malloc(scaleHeight * scaleWidth * 4);

    [_destinationTexture getBytes:destData bytesPerRow:scaleWidth * 4 fromRegion:self.destinationRegion mipmapLevel:0];
    
    CVPixelBufferCreateWithBytes(kCFAllocatorDefault, scaleWidth, scaleHeight, kCVPixelFormatType_32BGRA, destData, scaleWidth * 4, NULL, NULL, NULL, &finalBuffer);

    CVBufferRelease(textureRef);
    [_destinationTexture release];
    free(destData);
    
    return finalBuffer;
}

person prabhu    schedule 28.01.2021    source источник


Ответы (1)


Вы можете вернуться к MPSImageBilinearScale для пользователей, использующих версии, нет MPSImageLanczosScale. Это будет более низкое качество, но вам не придется накатывать собственный размер, а также не придется отказываться от существующих пользователей, которые не обновили свою ОС.

Сделайте scaleFilter членом вашего класса типа MPSImageScale*

if (@available(macOS 10.13, *))
{
    self.scaleFilter = [[MPSImageLanczosScale alloc] initWithDevice:device];
}
else 
{
    self.scaleFilter = [[MPSImageBilinearScale alloc] initWithDevice:device];
}

У них одинаковый базовый интерфейс MPSUnaryImageKernel, так что вам не придется менять другие части кода, по крайней мере, насколько я могу судить.

person JustSomeGuy    schedule 09.02.2021