Масштабированный MTKView показывает пробелы при присоединении к CIImages - PullRequest
0 голосов
/ 09 октября 2018

Я использую MTKView, написанный Саймоном Гладманом, который «предоставляет тип свойства изображения« CIImage »для упрощения рендеринга фильтров Core Image на основе Metal».Это было немного изменено для производительности.Я пропустил дополнительную операцию масштабирования, поскольку она не имеет ничего общего с проблемой здесь.

Проблема: При создании композита из меньших изображений CII в большее, они выровнены по пикселям.Свойство изображения MTKView установлено в этот композит CIImage.Тем не менее, для этого изображения сделана шкала, которая подходит для всего MTKView, что делает промежутки между объединенными изображениями видимыми.Это делается путем деления drawableSize width / height на экстент ширины / высоты CIImage.

Это заставляет меня задуматься, нужно ли что-то делать со стороны CIImage, чтобы фактически соединить эти пиксели.Сохранение этого изображения на рулоне камеры не показывает разделения между объединенными изображениями.Это видно только тогда, когда MTKView масштабируется.Кроме того, все, что нужно сделать, должно практически не влиять на производительность, так как эти рендеринг изображений выполняется в режиме реального времени через выход камеры.(MTKView - это предварительный просмотр выполняемого эффекта)

Вот MTKView, который я использую для рендеринга:

class MetalImageView: MTKView
{
    let colorSpace = CGColorSpaceCreateDeviceRGB()

var textureCache: CVMetalTextureCache?

var sourceTexture: MTLTexture!

lazy var commandQueue: MTLCommandQueue =
    {
        [unowned self] in

        return self.device!.makeCommandQueue()
        }()!

lazy var ciContext: CIContext =
    {
        [unowned self] in

        //cacheIntermediates

        return CIContext(mtlDevice: self.device!, options:[.cacheIntermediates:false])
        //return CIContext(mtlDevice: self.device!)
        }()

override init(frame frameRect: CGRect, device: MTLDevice?)
{
    super.init(frame: frameRect,
               device: device ?? MTLCreateSystemDefaultDevice())



    if super.device == nil
    {
        fatalError("Device doesn't support Metal")
    }

    CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, self.device!, nil, &textureCache)

    framebufferOnly = false

    enableSetNeedsDisplay = true

    isPaused = true

    preferredFramesPerSecond = 30

}

required init(coder: NSCoder)
{
    fatalError("init(coder:) has not been implemented")
}

/// The image to display
var image: CIImage?
{
    didSet
    {
        //renderImage()
        //draw()
        setNeedsDisplay()
    }
}

override func draw(_ rect: CGRect)
{
    guard let
        image = image,
        let targetTexture = currentDrawable?.texture else
    {
        return
    }

    let commandBuffer = commandQueue.makeCommandBuffer()

    let bounds = CGRect(origin: CGPoint.zero, size: drawableSize)

    let originX = image.extent.origin.x
    let originY = image.extent.origin.y

    let scaleX = drawableSize.width / image.extent.width
    let scaleY = drawableSize.height / image.extent.height
    let scale = min(scaleX, scaleY)
    let scaledImage = image
        .transformed(by: CGAffineTransform(translationX: -originX, y: -originY))
        .transformed(by: CGAffineTransform(scaleX: scale, y: scale))

    ciContext.render(scaledImage,
                     to: targetTexture,
                     commandBuffer: commandBuffer,
                     bounds: bounds,
                     colorSpace: colorSpace)


    commandBuffer?.present(currentDrawable!)

    commandBuffer?.commit()

}

}

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

    var scaledImageTransform = CGAffineTransform.identity

    scaledImageTransform = scaledImageTransform.translatedBy(x:0, y:sourceCore.extent.height)

    scaledImageTransform = scaledImageTransform.scaledBy(x:1.0, y:-1.0)
    alphaMaskBlend2 = alphaMaskBlend2?.applyingFilter("CISourceAtopCompositing",
                                                      parameters: [kCIInputImageKey: alphaMaskBlend2!,
                                                                   kCIInputBackgroundImageKey: sourceCore])

    alphaMaskBlend2 = alphaMaskBlend2?.applyingFilter("CISourceAtopCompositing",
                                                      parameters: [kCIInputImageKey: (alphaMaskBlend2?.cropped(to: cropRect).transformed(by: scaledImageTransform))!,
                                                                   kCIInputBackgroundImageKey: alphaMaskBlend2!])

sourceCore - исходное изображение, которое прошло через камеру.alphaMaskBlend2 - это последний CIImage, которому я назначаю MTKView.Параметр cropRect правильно обрезает зеркальную часть изображения.В увеличенном MTKView есть видимый разрыв между этими двумя объединенными изображениями.Что можно сделать, чтобы изображение отображалось в виде непрерывных пикселей независимо от масштаба MTKView, как и любое другое изображение?

...