我已经创建了一个GLKView子类来显示CIImage,以获得更好的性能,以显示CIFilter链的输出图像。

但是,似乎我需要实现contentMode逻辑,以便在inRect调用中为drawImage(image: CIImage, inRect: CGRect, fromRect: CGRect)提供正确的drawRect(rect: CGRect)

任何人都知道如何实现这种逻辑以便与UIImageView的contentMode行为保持一致吗?

最佳答案

用于使contentMode以类似于UIView的方式工作。我有以下 class 。

final class ContenModeEnforcer {
    static func rectFor(contentMode: UIViewContentMode, fromRect: CGRect, toRect: CGRect) -> CGRect {
        switch contentMode {
        case .scaleToFill:
            return toRect

        case .scaleAspectFit:
            return aspectFit(fromRect, toRect: toRect)

        case .scaleAspectFill:
            return aspectFill(fromRect, toRect: toRect)

        case .redraw:
            return fromRect

        case .center:
            let origin = CGPoint(
                x: (toRect.size.width - fromRect.size.width) / 2,
                y: (toRect.size.height - fromRect.size.height) / 2)
            return CGRect(origin: origin, size: fromRect.size)

        case .top:
            let origin = CGPoint(
                x: (toRect.size.width - fromRect.size.width) / 2,
                y: 0.0)
            return CGRect(origin: origin, size: fromRect.size)

        case .bottom:
            let origin = CGPoint(
                x: (toRect.size.width - fromRect.size.width) / 2,
                y: toRect.size.height - fromRect.size.height)
            return CGRect(origin: origin, size: fromRect.size)

        case .left:
            let origin = CGPoint(
                x: 0.0,
                y: (toRect.size.height - fromRect.size.height) / 2)
            return CGRect(origin: origin, size: fromRect.size)

        case .right:
            let origin = CGPoint(
                x: toRect.size.width - fromRect.size.width,
                y: (toRect.size.height - fromRect.size.height) / 2)
            return CGRect(origin: origin, size: fromRect.size)


        case .topLeft:
            let origin = CGPoint(
                x: 0.0,
                y: 0.0)
            return CGRect(origin: origin, size: fromRect.size)

        case .topRight:
            let origin = CGPoint(
                x: toRect.size.width - fromRect.size.width,
                y: 0.0)
            return CGRect(origin: origin, size: fromRect.size)

        case .bottomLeft:
            let origin = CGPoint(
                x: 0.0,
                y: toRect.size.height - fromRect.size.height)
            return CGRect(origin: origin, size: fromRect.size)

        case .bottomRight:
            let origin = CGPoint(
                x: toRect.size.width - fromRect.size.width,
                y: toRect.size.height - fromRect.size.height)
            return CGRect(origin: origin, size: fromRect.size)
        }
    }

    static fileprivate func aspectFit(_ fromRect: CGRect, toRect: CGRect) -> CGRect {
        let fromAspectRatio = fromRect.size.width / fromRect.size.height;
        let toAspectRatio = toRect.size.width / toRect.size.height;

        var fitRect = toRect

        if (fromAspectRatio > toAspectRatio) {
            fitRect.size.height = toRect.size.width / fromAspectRatio;
            fitRect.origin.y += (toRect.size.height - fitRect.size.height) * 0.5;
        } else {
            fitRect.size.width = toRect.size.height  * fromAspectRatio;
            fitRect.origin.x += (toRect.size.width - fitRect.size.width) * 0.5;
        }

        return fitRect.integral
    }

    static fileprivate func aspectFill(_ fromRect: CGRect, toRect: CGRect) -> CGRect {
        let fromAspectRatio = fromRect.size.width / fromRect.size.height;
        let toAspectRatio = toRect.size.width / toRect.size.height;

        var fitRect = toRect

        if (fromAspectRatio > toAspectRatio) {
            fitRect.size.width = toRect.size.height  * fromAspectRatio;
            fitRect.origin.x += (toRect.size.width - fitRect.size.width) * 0.5;
        } else {
            fitRect.size.height = toRect.size.width / fromAspectRatio;
            fitRect.origin.y += (toRect.size.height - fitRect.size.height) * 0.5;
        }

        return fitRect.integral
    }
}

在draw(_:CGRect)中。
let inputBounds = image.extent
let drawableBounds = CGRect(x: 0, y: 0, width: self.drawableWidth, height: self.drawableHeight)
let targetBounds = ContenModeEnforcer.rectFor(contentMode: contentMode, fromRect: inputBounds, toRect: drawableBounds)
ciContext.draw(image, in: targetBounds, from: inputBounds)

关于ios - 如何为显示CIImage的GLKView实现contentMode?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35592768/

10-11 14:55