Rotate UIImage in swift

后端 未结 8 1458
一整个雨季
一整个雨季 2021-02-04 10:35

I want to rotate UIImage in clockwise direction. But my current code do not perform function accurate some time it rotate and some time its skip rotation. I want my UIImage will

相关标签:
8条回答
  • 2021-02-04 10:40

    You can create a function like this to make your image rotate in clockwise forever:

    override func viewDidLoad() {
            super.viewDidLoad()
    
            let kRotationAnimationKey = "com.myapplication.rotationanimationkey"
    
            func rotateView(view: UIView, duration: Double = 1) {
                if view.layer.animationForKey(kRotationAnimationKey) == nil {
                    let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
    
                    rotationAnimation.fromValue = 0.0
                    rotationAnimation.toValue = Float(M_PI * 2.0)
                    rotationAnimation.duration = duration
                    rotationAnimation.repeatCount = Float.infinity
    
                    view.layer.addAnimation(rotationAnimation, forKey: kRotationAnimationKey)
                }
            }
          rotateView(self.imageView)
    }
    

    Result is:

    0 讨论(0)
  • 2021-02-04 10:46

    I fixed first function of @gleb's answer little bit. Size calculation is not necessary there. We simply should do it with reverse. Because if you do it size of 1149 x 356 with @gleb's function then you will get image sized 357 x 1149.

        extension UIImage {
    
            public func imageRotatedByDegrees(degrees: CGFloat) -> UIImage {
                let rotatedSize: CGSize = CGRect(x: 0, y: 0, width: self.size.height, height: self.size.width).size
    
                //Create the bitmap context
                UIGraphicsBeginImageContext(rotatedSize)
                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: rotatedSize.width / 2, y: rotatedSize.height / 2)
                //Rotate the image context
                bitmap.rotate(by: (degrees * CGFloat.pi / 180))
                //Now, draw the rotated/scaled image into the context
                bitmap.scaleBy(x: 1.0, y: -1.0)
                bitmap.draw(self.cgImage!, in: CGRect(x: -self.size.width / 2, y: -self.size.height / 2, width: self.size.width, height: self.size.height))
    
                let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    
                UIGraphicsEndImageContext()
                return newImage
            }
        }
    
    0 讨论(0)
  • 2021-02-04 10:51
    extension UIImage {
        public func imageRotatedByDegrees(degrees: CGFloat) -> UIImage {
            //Calculate the size of the rotated view's containing box for our drawing space
            let rotatedViewBox: UIView = UIView(frame: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
            let t: CGAffineTransform = CGAffineTransform(rotationAngle: degrees * CGFloat.pi / 180)
            rotatedViewBox.transform = t
            let rotatedSize: CGSize = rotatedViewBox.frame.size
            //Create the bitmap context
            UIGraphicsBeginImageContext(rotatedSize)
            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: rotatedSize.width / 2, y: rotatedSize.height / 2)
            //Rotate the image context
            bitmap.rotate(by: (degrees * CGFloat.pi / 180))
            //Now, draw the rotated/scaled image into the context
            bitmap.scaleBy(x: 1.0, y: -1.0)
            bitmap.draw(self.cgImage!, in: CGRect(x: -self.size.width / 2, y: -self.size.height / 2, width: self.size.width, height: self.size.height))
            let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
            return newImage
        }
    
    
        public func fixedOrientation() -> UIImage {
            if imageOrientation == UIImageOrientation.up {
                return self
            }
    
            var transform: CGAffineTransform = CGAffineTransform.identity
    
            switch imageOrientation {
            case UIImageOrientation.down, UIImageOrientation.downMirrored:
                transform = transform.translatedBy(x: size.width, y: size.height)
                transform = transform.rotated(by: CGFloat.pi)
                break
            case UIImageOrientation.left, UIImageOrientation.leftMirrored:
                transform = transform.translatedBy(x: size.width, y: 0)
                transform = transform.rotated(by: CGFloat.pi/2)
                break
            case UIImageOrientation.right, UIImageOrientation.rightMirrored:
                transform = transform.translatedBy(x: 0, y: size.height)
                transform = transform.rotated(by: -CGFloat.pi/2)
                break
            case UIImageOrientation.up, UIImageOrientation.upMirrored:
                break
            }
    
            switch imageOrientation {
            case UIImageOrientation.upMirrored, UIImageOrientation.downMirrored:
                transform.translatedBy(x: size.width, y: 0)
                transform.scaledBy(x: -1, y: 1)
                break
            case UIImageOrientation.leftMirrored, UIImageOrientation.rightMirrored:
                transform.translatedBy(x: size.height, y: 0)
                transform.scaledBy(x: -1, y: 1)
            case UIImageOrientation.up, UIImageOrientation.down, UIImageOrientation.left, UIImageOrientation.right:
                break
            }
    
            let ctx: CGContext = CGContext(data: nil,
                                           width: Int(size.width),
                                           height: Int(size.height),
                                           bitsPerComponent: self.cgImage!.bitsPerComponent,
                                           bytesPerRow: 0,
                                           space: self.cgImage!.colorSpace!,
                                           bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)!
    
            ctx.concatenate(transform)
    
            switch imageOrientation {
            case UIImageOrientation.left, UIImageOrientation.leftMirrored, UIImageOrientation.right, UIImageOrientation.rightMirrored:
                ctx.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
            default:
                ctx.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
                break
            }
    
            let cgImage: CGImage = ctx.makeImage()!
    
            return UIImage(cgImage: cgImage)
        }
    }
    

    @Jason, You should fix orientation of image before rotation.

    let image = oldimage.fixedOrientation().imageRotatedByDegrees(90.0)
    
    0 讨论(0)
  • 2021-02-04 10:51

    This s probably easier and it is Swift 5 syntax:

    // MARK: Rotate
    extension UIImage {
        func rotate(radians: Float) -> UIImage? {
            var newSize = CGRect(origin: CGPoint.zero, size: self.size).applying(CGAffineTransform(rotationAngle: CGFloat(radians))).size
            // Trim off the extremely small float value to prevent core graphics from rounding it up
            newSize.width = floor(newSize.width)
            newSize.height = floor(newSize.height)
    
            UIGraphicsBeginImageContextWithOptions(newSize, false, self.scale)
            let context = UIGraphicsGetCurrentContext()!
    
            // Move origin to middle
            context.translateBy(x: newSize.width/2, y: newSize.height/2)
            // Rotate around middle
            context.rotate(by: CGFloat(radians))
            // Draw the image at its center
            self.draw(in: CGRect(x: -self.size.width/2, y: -self.size.height/2, width: self.size.width, height: self.size.height))
    
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            return newImage
        }
    }
    
    0 讨论(0)
  • 2021-02-04 10:58

    @Jason Chitla, I cant comment yet, so Im posting it as a new answer. The above solution from @Albert works, but only for square images. The problem is, that

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

    is still using the original size, so if you rotate it 90 degrees, aspect is wrong.

    What works for me is to use the new rotatedSize, like this:

    func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage {
        //Calculate the size of the rotated view's containing box for our drawing space
        let rotatedViewBox: UIView = UIView(frame: CGRect(x: 0, y: 0, width: oldImage.size.width, height: oldImage.size.height))
        let t: CGAffineTransform = CGAffineTransform(rotationAngle: degrees * CGFloat(M_PI / 180))
        rotatedViewBox.transform = t
        let rotatedSize: CGSize = rotatedViewBox.frame.size
        //Create the bitmap context
        UIGraphicsBeginImageContext(rotatedSize)
        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: rotatedSize.width / 2, y: rotatedSize.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)
        bitmap.draw(self.cgImage!, in: CGRect(x: -rotatedSize.width / 2, y: -rotatedSize.height / 2, width: rotatedSize.width, height: rotatedSize.height))
        let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }
    
    0 讨论(0)
  • 2021-02-04 10:59

    For those who need the code from @Mughees in Swift 3:

    func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage {
        //Calculate the size of the rotated view's containing box for our drawing space
        let rotatedViewBox: UIView = UIView(frame: CGRect(x: 0, y: 0, width: oldImage.size.width, height: oldImage.size.height))
        let t: CGAffineTransform = CGAffineTransform(rotationAngle: degrees * CGFloat(M_PI / 180))
        rotatedViewBox.transform = t
        let rotatedSize: CGSize = rotatedViewBox.frame.size
        //Create the bitmap context
        UIGraphicsBeginImageContext(rotatedSize)
        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: rotatedSize.width / 2, y: rotatedSize.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)
        bitmap.draw(oldImage.cgImage!, in: CGRect(x: -oldImage.size.width / 2, y: -oldImage.size.height / 2, width: oldImage.size.width, height: oldImage.size.height))
        let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }
    
    0 讨论(0)
提交回复
热议问题