【问题标题】:How to rotate image in Swift?如何在 Swift 中旋转图像?
【发布时间】:2017-04-14 10:18:12
【问题描述】:

我无法将图像快速旋转 90 度。我已经写了下面的代码,但是有一个错误并且没有编译

  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, in:  CGRect(origin: (x: -oldImage.size.width / 2,  y: -oldImage.size.height / 2, width:  oldImage.size.width, height: oldImage.size.height), size: oldImage.cgImage))

    let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()

    return newImage

  }

下面是我不确定的代码

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))

【问题讨论】:

标签: ios swift animation uiview uiviewanimation


【解决方案1】:
 let angle =  CGFloat(M_PI_2)
  let tr = CGAffineTransform.identity.rotated(by: angle)
  ImageView.transform = tr

【讨论】:

  • 我想旋转一个不在 imageview 上的 UIImage
【解决方案2】:

设置 ImageView 图片

ImageView.transform = ImageView.transform.rotated(by: CGFloat(M_PI_2))

斯威夫特 5

ImageView.transform = ImageView.transform.rotated(by: .pi)        // 180˚

ImageView.transform = ImageView.transform.rotated(by: .pi / 2)    // 90˚

ImageView.transform = ImageView.transform.rotated(by: .pi * 1.5)  // 270˚

【讨论】:

  • 为什么选择 M_PI_4? 90 度 = M_PI_2
  • @JayeshMiruliya,在 Swift 3 中你也可以使用 CGFloat.pi 常量(除以 2 ofc)
  • 对于 Swift 4 使用:.pi/1 用于 180°,.pi/2 用于 90°
  • 要旋转 UIImage,你可以查看这个 GitHub 链接。为 Swift3 工作。根据上述评论,您可以使用“.pi/1 for 180˚ 和 .pi/2 for 90˚”作为弧度参数。 gist.github.com/norsez/e318d68f6a48786d35b3e7fd3b3a32ae
  • 动画 - UIView.animate(withDuration: 3) { self.needleImageView.transform = self.needleImageView.transform.rotated(by: CGFloat(Double.pi/2)) }
【解决方案3】:

您的代码与功能相差不远。您可以像直接对位图一样应用变换,不需要中间视图:

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
}

另外,如果您要创建一个旋转图像的函数,包含clockwise: Bool 参数通常是一种很好的形式,它将解释degrees 参数是否顺时针旋转。我把实现和适当的弧度转换留给你。

还请注意,假设oldImage.size 不为零,这对我来说有点不自然。如果是这样,强制展开 UIGraphicsGetCurrentContext()! 可能会崩溃。您应该验证oldImage 的大小,如果它无效,则返回oldImage

【讨论】:

  • 虽然功能正常,但此代码不会围绕中心旋转图像,除非在图像是正方形的独特场景中。我使用了中间方法,它产生了绕中心旋转。
【解决方案4】:

您的问题是您对 CGRect 使用了不存在的初始化程序。如果你想使用 CGRect(origin:size:),那么请正确创建原点,不带宽度和高度参数。或者删除大小参数并使用 CGRect(x:y:width:height:)

只需替换这一行

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))

用这个:

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

【讨论】:

    【解决方案5】:

    您可以将以下代码用于 Swift 3:

    extension UIImage {
    
    func fixImageOrientation() -> UIImage? {
        var flip:Bool = false //used to see if the image is mirrored
        var isRotatedBy90:Bool = false // used to check whether aspect ratio is to be changed or not
    
        var transform = CGAffineTransform.identity
    
        //check current orientation of original image
        switch self.imageOrientation {
        case .down, .downMirrored:
            transform = transform.rotated(by: CGFloat(M_PI));
    
        case .left, .leftMirrored:
            transform = transform.rotated(by: CGFloat(M_PI_2));
            isRotatedBy90 = true
        case .right, .rightMirrored:
            transform = transform.rotated(by: CGFloat(-M_PI_2));
            isRotatedBy90 = true
        case .up, .upMirrored:
            break
        }
    
        switch self.imageOrientation {
    
        case .upMirrored, .downMirrored:
            transform = transform.translatedBy(x: self.size.width, y: 0)
            flip = true
    
        case .leftMirrored, .rightMirrored:
            transform = transform.translatedBy(x: self.size.height, y: 0)
            flip = true
        default:
            break;
        }
    
        // calculate the size of the rotated view's containing box for our drawing space
        let rotatedViewBox = UIView(frame: CGRect(origin: CGPoint(x:0, y:0), size: size))
        rotatedViewBox.transform = transform
        let rotatedSize = rotatedViewBox.frame.size
    
        // Create the bitmap context
        UIGraphicsBeginImageContext(rotatedSize)
        let bitmap = 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.0, y: rotatedSize.height / 2.0);
    
        // Now, draw the rotated/scaled image into the context
        var yFlip: CGFloat
    
        if(flip){
            yFlip = CGFloat(-1.0)
        } else {
            yFlip = CGFloat(1.0)
        }
    
        bitmap!.scaleBy(x: yFlip, y: -1.0)
    
        //check if we have to fix the aspect ratio
        if isRotatedBy90 {
            bitmap?.draw(self.cgImage!, in: CGRect(x: -size.width / 2, y: -size.height / 2, width: size.height,height: size.width))
        } else {
            bitmap?.draw(self.cgImage!, in: CGRect(x: -size.width / 2, y: -size.height / 2, width: size.width,height: size.height))
        }
    
        let fixedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    
        return fixedImage
    }
    

    【讨论】:

      【解决方案6】:

      您可以先在 imageView 中设置图像,然后在 imageView 中旋转获取图像

      这里:

      let customImageView = UIImageView()
      customImageView.frame = CGRect.init(x: 0, y: 0, w: 250, h: 250)
      customImageView.image = UIImage(named: "yourImage")
      
      customImageView .transform = customImageView .transform.rotated(by: CGFloat.init(M_PI_2))
      var rotatedImage = UIImage()
      rotatedImage = customImageView.image!
      

      【讨论】:

        【解决方案7】:

        这是UIImage 的扩展,它以Swift 4.0 为目标,可以只旋转图像而无需UIImageView。测试成功,图像被旋转,而不仅仅是其 exif 数据发生变化。

        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
            }
        }
        

        要执行 180 度旋转,您可以这样称呼它:

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

        如果由于某种原因无法旋转,则会返回原始图像。

        【讨论】:

        • 这行得通,但是翻译/来源似乎是错误的。旋转后的图像向上和向左移动:-/
        • @lenooh 您能否发布有关您如何称呼它的详细信息以及图像的一些一般细节?
        • CodeBender:我用let rotatedImage = image.rotate(radians: .pi) 调用它。图片是 1433 × 2099。然后我找到了另一个完美的解决方案:stackoverflow.com/a/47402811/529663
        • 正如@lenooh 指出的那样。接受的解决方案有几个翻译问题,似乎对每个人都有效的解决方案发布在他的评论中。再次为您提供方便:stackoverflow.com/a/47402811/529663
        【解决方案8】:

        一行:

        rotatedViewBox.transform = CGAffineTransform(rotationAngle: CGFloat.pi/2)
        

        【讨论】:

        • 这应该是最好的解决方案
        【解决方案9】:

        在 Swift 4.2 和 Xcode 10.0 中

        dropDownImageView.transform = dropDownImageView.transform.rotated(by: CGFloat(Double.pi / 2))
        

        如果要添加动画...

        UIView.animate(withDuration: 2.0, animations: {
           self.dropDownImageView.transform = self.dropDownImageView.transform.rotated(by: CGFloat(Double.pi / 2))
        })
        

        【讨论】:

          【解决方案10】:

          通过 UIGraphics Context 旋转图像是比较繁重的操作。您可能会看到质量下降和内存增加的问题。

          我建议你应该尝试旋转图层或视图本身。

          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)
              }
          }
          

          如何使用

          yourImageView.rotate(degrees: 40)
          

          【讨论】:

            【解决方案11】:
            ImageView?.transform = transform.rotated(by: (CGFloat(Double.pi / 2)))
            

            斯威夫特 4.2

            旋转 - 正确。工作正常。

            【讨论】:

              【解决方案12】:

              如果您只是不想要特定的旋转并且喜欢一一使用所有方向。

              func rotateImage() -> UIImage {
                  let newOrientation = Orientation(rawValue: self.imageOrientation.rawValue + 1) ?? UIImage.Orientation(rawValue: 0)
                  return UIImage(cgImage: self.cgImage!, scale: self.scale, orientation: newOrientation!)
              }
              

              【讨论】:

                【解决方案13】:
                UIGraphicsBeginImageContext(CGSize(width: bitmap.width, height: bitmap.height))
                UIImage(cgImage: oldImage.cgImage, scale: 1, orientation: .leftMirrored).draw(at: .zero)
                let image = UIGraphicsGetImageFromCurrentImageContext()!
                

                短得多。

                【讨论】:

                  【解决方案14】:

                  开始旋转图像视图:

                  func startSpinning()  {
                      UIView.animate(withDuration: 0.5, delay: 0, options: .repeat, animations: { () -> Void in
                          self.gearImageView!.transform = self.gearImageView!.transform.rotated(by: .pi / 2)
                      })
                  }
                  

                  停止旋转:

                  func stopSpinning()  {
                      self.gearImageView.layer.removeAllAnimations()
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-09-03
                    • 2016-02-04
                    • 2015-04-04
                    • 2011-06-25
                    • 2016-07-20
                    相关资源
                    最近更新 更多