Я использую 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, как и любое другое изображение?