简体   繁体   English

UIGraphicsGetImageFromCurrentContext并保留宽高比

[英]UIGraphicsGetImageFromCurrentContext and preserve aspect ratio

I'm trying to implement a UIImageView subclass that will allow a user to draw in the image view using their fingers. 我正在尝试实现UIImageView子类,该子类将允许用户使用其手指在图像视图中进行绘制。 The contentMode of my UIImageView is set to Aspect Fill . 我的UIImageView的contentMode设置为Aspect Fill I noticed that when my draw code executes and the resulting image is extracted from the graphics context it is being scaled in a Scale to Fill type format which is not something I want. 我注意到执行绘图代码并将结果图像从图形上下文中提取时,它正以“ Scale to Fill类型的格式进行缩放,这不是我想要的。 I was wondering if anyone knows how to achieve extracting this image and maintaining the aspect ratio of the image. 我想知道是否有人知道如何实现提取此图像并保持图像的纵横比。

class DrawImageView : UIImageView {

    var lastTouchPoint = CGPoint.zero
    var isSwiping = false

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        isSwiping = false 
        if let touchPoint = touches.first {
            lastTouchPoint = touchPoint.location(in: self)
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        isSwiping = true

        if let touchPoint = touches.first {
            let currentPoint = touchPoint.location(in: self)
            UIGraphicsBeginImageContext(frame.size)

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

            if let context = UIGraphicsGetCurrentContext() {
                context.move(to: lastTouchPoint)
                context.addLine(to: currentPoint)
                context.setLineCap(CGLineCap.round)
                context.setLineWidth(9.0)
                context.setStrokeColor(red: 0/255.0, green: 0/255.0, blue: 0/255.0, alpha: 1.0)
                context.strokePath()
                image = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                lastTouchPoint = currentPoint
            }
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if(!isSwiping) {

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


            if let context = UIGraphicsGetCurrentContext() {
                context.setLineCap(CGLineCap.round)
                context.setLineWidth(9.0)
                context.setStrokeColor(red: 0/255.0, green: 0/255.0, blue: 0/255.0, alpha: 1.0)
                context.move(to: lastTouchPoint)
                context.addLine(to: lastTouchPoint)
                context.strokePath()
                image = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
            }
        }
    }
}

With this code: 使用此代码:

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

you are saying "draw this full image - regardless of size or aspect ratio - into a rectangle of width x height dimensions." 您说的是“将完整的图像-不论大小或宽高比-都绘制成宽度x高度尺寸的矩形”。 So, if image has a "native" size of, say, 300 x 200, and your frame is 200 x 200, that's where the image is going to be drawn. 因此,如果image的“原始”尺寸为300 x 200,而您的frame为200 x 200,则将在此处绘制图像。

To avoid that, you need to calculate the proper rect to draw into. 为了避免这种情况,您需要计算要吸收的适当矩形。 Using those sizes, you'd want to do (for aspect-fill): 使用这些尺寸,您要进行以下操作(用于宽高比填充):

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

Of course, instead of hard-coded values, you'd run quick calculations to determine the actual numbers. 当然,您可以运行快速计算来确定实际数字,而不是硬编码值。

The functions I ended up discovering and using to provide both an aspect fill rect and a aspect fit rect is as follows: 我最终发现并用于提供宽高比填充rect和宽高比拟合rect的功能如下:

 func getAspectFillFrame(sizeImageView : CGSize, sizeImage: CGSize) -> CGRect {

        let aspect = sizeImage.width / sizeImage.height
        let rect: CGRect

        if sizeImageView.width / aspect > sizeImageView.height {

            let height = sizeImageView.width / aspect

            rect = CGRect(x: 0, y: (sizeImageView.height - height) / 2,
                          width: sizeImageView.width, height: height)

        } else {
            let width = sizeImageView.height * aspect
            rect = CGRect(x: (sizeImageView.width - width) / 2, y: 0,
                          width: width, height: sizeImageView.height)
        }

        return rect

    }

    func getAspectFitFrame(sizeImgView:CGSize, sizeImage:CGSize) -> CGRect {

        let imageSize:CGSize  = sizeImage
        let viewSize:CGSize = sizeImgView

        let hfactor : CGFloat = imageSize.width/viewSize.width
        let vfactor : CGFloat = imageSize.height/viewSize.height

        let factor : CGFloat = max(hfactor, vfactor)

        // Divide the size by the greater of the vertical or horizontal shrinkage factor
        let newWidth : CGFloat = imageSize.width / factor
        let newHeight : CGFloat = imageSize.height / factor

        var x:CGFloat = 0.0
        var y:CGFloat = 0.0
        if newWidth > newHeight{
            y = (sizeImgView.height - newHeight)/2
        }
        if newHeight > newWidth{
            x = (sizeImgView.width - newWidth)/2
        }
        let newRect:CGRect = CGRect(x: x, y: y, width: newWidth, height: newHeight)

        return newRect

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM