How to rotate image in Swift?

后端 未结 13 1215
萌比男神i
萌比男神i 2020-11-30 03:55

I am unable to rotate the image by 90 degrees in swift. I have written below code but there is an error and doesn\'t compile

  func imageRotatedByDegrees(old         


        
相关标签:
13条回答
  • 2020-11-30 03:58

    This is an extension of UIImage that targets Swift 4.0 and can rotate just the image without the need for a UIImageView. Tested successfully that the image was rotated, and not just had its exif data changed.

    import UIKit
    
    extension UIImage {
        func rotate(radians: CGFloat) -> UIImage {
            let rotatedSize = CGRect(origin: .zero, size: size)
                .applying(CGAffineTransform(rotationAngle: CGFloat(radians)))
                .integral.size
            UIGraphicsBeginImageContext(rotatedSize)
            if let context = UIGraphicsGetCurrentContext() {
                let origin = CGPoint(x: rotatedSize.width / 2.0,
                                     y: rotatedSize.height / 2.0)
                context.translateBy(x: origin.x, y: origin.y)
                context.rotate(by: radians)
                draw(in: CGRect(x: -origin.y, y: -origin.x,
                                width: size.width, height: size.height))
                let rotatedImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
    
                return rotatedImage ?? self
            }
    
            return self
        }
    }
    

    To perform a 180 degree rotation, you can call it like this:

    let rotatedImage = image.rotate(radians: .pi)
    

    If for whatever reason it fails to rotate, the original image will then be returned.

    0 讨论(0)
  • 2020-11-30 04:02

    Rotate image via UIGraphics Context is comparatively heavy operation. The problems you may seen loosing quality and memory increase.

    I suggest you should try to rotate the layer or view itself.

    extension UIView {
    
    
        func rotate(degrees: CGFloat) {
    
            let degreesToRadians: (CGFloat) -> CGFloat = { (degrees: CGFloat) in
                return degrees / 180.0 * CGFloat.pi
            }
            self.transform =  CGAffineTransform(rotationAngle: degreesToRadians(degrees))
    
            // If you like to use layer you can uncomment the following line 
            //layer.transform = CATransform3DMakeRotation(degreesToRadians(degrees), 0.0, 0.0, 1.0)
        }
    }
    

    How to use

    yourImageView.rotate(degrees: 40)
    
    0 讨论(0)
  • 2020-11-30 04:06
     let angle =  CGFloat(M_PI_2)
      let tr = CGAffineTransform.identity.rotated(by: angle)
      ImageView.transform = tr
    
    0 讨论(0)
  • 2020-11-30 04:06

    Your code is not that far off from functional. You can apply the transform as you are doing directly to the bitmap, you don't need an intermediate view:

    func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage {
        let size = oldImage.size
    
        UIGraphicsBeginImageContext(size)
    
        let bitmap: CGContext = UIGraphicsGetCurrentContext()!
        //Move the origin to the middle of the image so we will rotate and scale around the center.
        bitmap.translateBy(x: size.width / 2, y: size.height / 2)
        //Rotate the image context
        bitmap.rotate(by: (degrees * CGFloat(M_PI / 180)))
        //Now, draw the rotated/scaled image into the context
        bitmap.scaleBy(x: 1.0, y: -1.0)
    
        let origin = CGPoint(x: -size.width / 2, y: -size.width / 2)
    
        bitmap.draw(oldImage.cgImage!, in: CGRect(origin: origin, size: size))
    
        let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }
    

    Also, if you're going to create a function that rotates an image, it is typically good form to include a clockwise: Bool parameter that will interpret the degrees argument as rotating clockwise or not. The implementation and appropriate conversion to radians I leave to you.

    Also note that it's a bit hand-wavy on my part to assume that oldImage.size is non-zero. If it is, force-unwrapping UIGraphicsGetCurrentContext()! will probably crash. You should validate the oldImage's size and if it's invalid just return oldImage.

    0 讨论(0)
  • 2020-11-30 04:06

    Your problem is that you use non-existing initializer for CGRect. If you want to use CGRect(origin:size:), then create origin properly, without width and height parameters. Or remove size parameter and use CGRect(x:y:width:height:).

    Just replace this line

    bitmap.draw(oldImage, in:  CGRect(origin: (x: -oldImage.size.width / 2,  y: -oldImage.size.height / 2, width:  oldImage.size.width, height: oldImage.size.height), size: oldImage.cgImage))
    

    with this one:

    let rect = CGRect(origin: CGPoint(x: -oldImage.size.width / 2,  y: -oldImage.size.height / 2), size: oldImage.size)
    bitmap.draw(oldImage.cgImage!, in: rect)
    
    0 讨论(0)
  • 2020-11-30 04:10
    ImageView?.transform = transform.rotated(by: (CGFloat(Double.pi / 2)))
    

    Swift 4.2

    Rotation - right. Works fine.

    0 讨论(0)
提交回复
热议问题