首页 > 解决方案 > 如何在渲染新图像时修复 MTKView 随机填充颜色

问题描述

我正在开发照片编辑器,出于性能原因,我刚刚从UIImageView切换到MTKView 。它工作得很好,除了某些图像上的某些原因有一个红色框。显示新图像时,图像大小发生变化,红色框变大。

我正在使用 Mac Catalyst

这是我的MTKView代码

    public let colorSpace = CGColorSpaceCreateDeviceRGB()

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

        if self.device == nil {
            self.device = MTLCreateSystemDefaultDevice()
        }

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

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

        if self.device == nil {
            self.device = MTLCreateSystemDefaultDevice()
        }

        let context = CIContext(mtlDevice: self.device!, options: [CIContextOption.highQualityDownsample: true, CIContextOption.priorityRequestLow: false])

        return context
        }()

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

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

        self.framebufferOnly = false
    }

    required public init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        self.framebufferOnly = false

        self.device = MTLCreateSystemDefaultDevice()
    }

    /// The image to display
    public var image: CIImage?
    {
        didSet
        {

            renderImage()
        }
    }

    public var orientation: CGImagePropertyOrientation? {
        didSet {

            renderImage()
        }
    }

    func renderImage()
    {

        guard var
            image = self.image,
            let targetTexture = self.currentDrawable?.texture else
        {
            print("No texture/image")
            return
        }

        self.drawableSize = image.extent.size

        if let orientation = orientation {
            image = image.oriented(orientation)
        }

        let commandBuffer = self.commandQueue.makeCommandBuffer()

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

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

        let scaleX = self.drawableSize.width / image.extent.width
        let scaleY = self.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))

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

        commandBuffer?.present(self.currentDrawable!)

        commandBuffer?.commit()

        self.draw()

        self.releaseDrawables()
    }

标签: swiftmetalcore-image

解决方案


推荐阅读