Swift: коэффициент потери изображения при начале рисования - PullRequest
0 голосов
/ 02 сентября 2018

Я пытаюсь создать VC для редактирования изображений для моего приложения и столкнулся с вышеуказанной проблемой. Всякий раз, когда я начинаю рисовать на своем изображении, изображение деформируется, а затем теряет соотношение сторон.

GIF как таковой:

enter image description here

Мой полный код как таковой:

class DrawImageController: UIViewController {

    var canvasImageView: UIImageView = {
        let iv = UIImageView()
        iv.translatesAutoresizingMaskIntoConstraints = false
        iv.backgroundColor = .yellow
        iv.contentMode = .scaleAspectFit
        return iv
    }()

    var lastTouch = CGPoint.zero

    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
    }

    func setupViews() {
        view.backgroundColor = .black

        view.addSubview(canvasImageView)

        canvasImageView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        canvasImageView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
        canvasImageView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
        canvasImageView.heightAnchor.constraint(equalToConstant: 300).isActive = true

        canvasImageView.image = UIImage(named: "testImage")
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let firstTouch = touches.first {
            lastTouch = firstTouch.location(in: canvasImageView)
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let firstTouch = touches.first {
            let touchLocation = firstTouch.location(in: canvasImageView)
            drawLine(from: lastTouch, to: touchLocation)
            lastTouch = touchLocation
        }
    }

    func drawLine(from: CGPoint, to: CGPoint) {
        UIGraphicsBeginImageContext(canvasImageView.frame.size)

        if let context = UIGraphicsGetCurrentContext() {
            canvasImageView.image?.draw(in: CGRect(x: 0, y: 0, width: canvasImageView.frame.size.width, height: canvasImageView.frame.size.height))

            context.move(to: from)
            context.addLine(to: to)

            context.setLineCap(.round)
            context.setLineWidth(5.0)
            context.setStrokeColor(UIColor.blue.cgColor)

            context.strokePath()

            let image = UIGraphicsGetImageFromCurrentImageContext()
            canvasImageView.image = image
            UIGraphicsEndImageContext()
        }          
    }
}

Я адаптировал свой метод отрисовки из различных уроков на YouTube, GitHub и SO. Кто-нибудь посоветует, где я мог пойти не так, пожалуйста? Спасибо.

РЕШИТЬ: По совету @Sweeper я изменил свой код в setupViews() и drawLine, чтобы учесть соотношение сторон изображения и imageView.

func setupViews() {
    view.backgroundColor = .black

    view.addSubview(canvasImageView)

    canvasImageView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    canvasImageView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
    canvasImageView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true

    let aspectRatio = getImageAspectRatio(image: UIImage(named: "testImage")!)
    let screenWidth = UIScreen.main.bounds.width
    let height = CGFloat(1.0) / aspectRatio * screenWidth
    canvasImageView.heightAnchor.constraint(equalToConstant: height).isActive = true

    canvasImageView.image = UIImage(named: "testImage")
}

func drawLine(from: CGPoint, to: CGPoint) {

    UIGraphicsBeginImageContext(canvasImageView.frame.size)

    guard let context = UIGraphicsGetCurrentContext() else {return}

    if let canvasImage = canvasImageView.image {
        let imageViewAspectRatio = getAspectRatio(frame: canvasImageView.frame)
        let imageAspectRatio = getImageAspectRatio(image: canvasImage)

        if imageViewAspectRatio > imageAspectRatio {
            canvasImageView.image?.draw(in: CGRect(x: 0, y: 0, width: imageAspectRatio * canvasImageView.frame.size.height, height: canvasImageView.frame.size.height))
        } else if imageViewAspectRatio < imageAspectRatio {
            canvasImageView.image?.draw(in: CGRect(x: 0, y: 0, width: canvasImageView.frame.size.width, height: CGFloat(1.0) / imageAspectRatio * canvasImageView.frame.size.width))
        } else {
            canvasImageView.image?.draw(in: CGRect(x: 0, y: 0, width: canvasImageView.frame.size.width, height: canvasImageView.frame.size.height))
        }

        context.move(to: from)
        context.addLine(to: to)

        context.setLineCap(.round)
        context.setLineWidth(5.0)
        context.setStrokeColor(UIColor.blue.cgColor)

        context.strokePath()

        let image = UIGraphicsGetImageFromCurrentImageContext()
        canvasImageView.image = image
        UIGraphicsEndImageContext()
    }
}

1 Ответ

0 голосов
/ 02 сентября 2018

Проблема здесь:

canvasImageView.image?.draw(in: CGRect(x: 0, y: 0, width: canvasImageView.frame.size.width, height: canvasImageView.frame.size.height))

Вы рисуете изображение, используя рамку просмотра изображения. Это растягивает изображение.

Вам нужно нарисовать изображение , как если бы contentMode было .scaleAspectFit.

Для этого сначала определите соотношение сторон изображения (W: H). Вы можете сделать это, обратившись к свойству size UIImage. Сравните это соотношение с форматом изображения.

Если соотношение изображения меньше, чем у вида, то это означает, что высота, на которой вы рисуете изображение, может быть такой же, как высота представления изображения, а ширина изображения может быть рассчитана с использованием соотношения сторон изображения.

Если отношение изображения больше, чем у вида, то это означает, что ширина, на которой вы рисуете изображение, может быть такой же, как ширина представления изображения, и высоту изображения можно рассчитать,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...