Анимация CIFilter CIPerspectiveCorrection - PullRequest
0 голосов
/ 03 мая 2019

Я пытаюсь сделать функцию обрезки изображения с коррекцией перспективы. Я успешно использовал CIFilter CIPerspectiveCorrection.

У меня вопрос: как анимировать исходное изображение на обрезанное (с коррекцией)?

layer.filters не поддерживается для iOS согласно документации. Я думаю, что, возможно, CATransform3D - это путь, но я не знаком с преобразованиями и матрицами.

Я ищу ту же анимацию, что и кадрирование в приложении CamScanner.

Sample

1 Ответ

0 голосов
/ 06 мая 2019

Нашел способ, но довольно грубый способ пойти на это. Я создал несколько изображений, интерполированных из исходного и конечного изображений, а затем добавил CAKeyFrameAnimation.

let points: [CGFloat] = [0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0]
    for i in points {
        let TLx = originalQuad.topLeft.x + i * (cartesianScaledQuad.topLeft.x - originalQuad.topLeft.x)
        let TLy = originalQuad.topLeft.y + i * (cartesianScaledQuad.topLeft.y - originalQuad.topLeft.y)
        let TL = CGPoint(x: TLx, y: TLy)

        let TRx = originalQuad.topRight.x + i * (cartesianScaledQuad.topRight.x - originalQuad.topRight.x)
        let TRy = originalQuad.topRight.y + i * (cartesianScaledQuad.topRight.y - originalQuad.topRight.y)
        let TR = CGPoint(x: TRx, y: TRy)

        let BLx = originalQuad.bottomLeft.x + i * (cartesianScaledQuad.bottomLeft.x - originalQuad.bottomLeft.x)
        let BLy = originalQuad.bottomLeft.y + i * (cartesianScaledQuad.bottomLeft.y - originalQuad.bottomLeft.y)
        let BL = CGPoint(x: BLx, y: BLy)

        let BRx = originalQuad.bottomRight.x + i * (cartesianScaledQuad.bottomRight.x - originalQuad.bottomRight.x)
        let BRy = originalQuad.bottomRight.y + i * (cartesianScaledQuad.bottomRight.y - originalQuad.bottomRight.y)
        let BR = CGPoint(x: BRx, y: BRy)

        let filteredImage = ciImage.applyingFilter("CIPerspectiveCorrection", parameters: [
            "inputTopLeft": CIVector(cgPoint: BL),
            "inputTopRight": CIVector(cgPoint: BR),
            "inputBottomLeft": CIVector(cgPoint: TL),
            "inputBottomRight": CIVector(cgPoint: TR)
            ])

        if let image = CIContext(options: nil).createCGImage(filteredImage, from: filteredImage.extent) {
            images.append(image)
        }
    }

    let anim:CAKeyframeAnimation = CAKeyframeAnimation(keyPath: "contents")
    anim.duration = 0.5
    anim.values = images
    anim.delegate = self

    imageView.layer.add(anim, forKey: "contents");
    imageView.layer.contents = images.last!

Возникла проблема с приращением значений, поэтому мне пришлось жестко кодировать каждую точку. Работает нормально, и выглядел хорошо. Хотя накладные расходы при создании CGImage s заметны, особенно если генерируется больше кадров.

Надеемся, что в будущем Apple поддержит layer.filters на iOS.

...