【问题标题】:Swift - Image rotation in degrees - deformed resultSwift - 以度为单位的图像旋转 - 变形结果
【发布时间】:2017-02-23 10:41:39
【问题描述】:

我发现了几种在 Swift 中按度旋转图像的方法,但没有一种方法可以一直正常工作。我想将图像向左或向右旋转 90 度。我认为最好的是:

  class func imageRotated(_ oldImage: UIImage, byDegrees 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
  }

它可以工作并做我想做的事,但有几次它会变形结果,所以它没有旋转,只是改变了图像大小,或者旋转了 180 度并改变了图像大小。

旋转前:

旋转后(菜单因自动隐藏而丢失):

奇怪的是,当我拍摄肖像照片时会发生这种情况。当我在横向拍摄照片时,旋转效果很好(即使我尝试旋转几次,即使我从横向旋转到纵向,然后再旋转到横向,它仍然可以正常工作)。

我看到一些关于自动布局约束问题的讨论,但我不确定这是否是我的问题,以及为什么它在某些情况下有效而在某些情况下无效。我在集合单元格中有照片,每个单元格都有第一个 UIScrollView,而在 UIScrollView 中有带有照片的 UIImageView。所有约束都设置为边界。

如果有帮助,我只想旋转 90 或 -90 度。这可能会使方法更简单,更容易修复。

感谢您的帮助。

【问题讨论】:

  • 尝试使用self.imageview.transform = CGAffineTransformMakeRotation(M_PI_2);
  • @tejas 问题不是关于旋转UIImageView,而是UIImage 本身
  • @Libor 请展示您如何使用此方法并仔细检查您的imageView 中的contentMode。好像是ScaleToFill,假设失真

标签: ios swift image rotation uigraphicscontext


【解决方案1】:

实际上最简单也可能是最好的方法是创建一个视图,在其上放置一个图像视图,旋转图像视图,调整超级视图的大小并创建该视图的屏幕截图。

您实际上并没有在视图层次结构中添加这些视图,您只是使用它们轻松生成图像。

为什么这是一个好的程序是因为UIView 已经编写了所有代码以完全支持核心图形。所以完全没有缺点,你可以确定这些程序已经被 Apple 完善了。

所以试试这个:

    func transformImage(image: UIImage?, transform: CGAffineTransform) -> UIImage? {

        guard let image = image else {
            return nil
        }

        let view = UIView(frame: CGRect.zero)
        let imageView = UIImageView(image: image)
        imageView.transform = transform
        view.addSubview(imageView)
        imageView.frame.origin = CGPoint.zero
        view.frame = CGRect(x: 0.0, y: 0.0, width: imageView.frame.size.width, height: imageView.frame.size.height)


        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        if let cgImage = newImage?.cgImage {
            return UIImage(cgImage: cgImage)
        } else {
            return nil
        }

    }

至于您的过程中的问题,很可能是因为您丢弃了来自UIImage 的转换。 CGImage 基本上是原始图像表示,它不知道旋转。 UIImage 确实有 imageOrientation。所以你需要做的是解决这个问题,你需要从图像方向生成转换矩阵并使用它。

因此,当您使用设备拍摄图像时,CGImage 将始终具有相同的方向(横向或横向)。但是UIImage 会改变图像方向,然后用于表示。

【讨论】:

  • @LiborZapletal 我希望你明白你的问题出在哪里。尝试纵向拍照并检查 UIImage 的大小和 CGI​​mage 的大小。它们与 CGImage 仍处于横向状态时不同,而 UIImage 包含需要旋转的信息并为您提供纵向尺寸。
  • 是的,它也对我有帮助。我在想可能是这样的问题。但我不确定问题出在哪里以及如何解决。使用您的解决方案会更容易,而且看起来不会降低性能。
  • 在某些情况下,您可能仍需要手动执行此操作。这意味着为所有 8 种情况创建 UIImage 方向的 switch 语句(是的,由于前置摄像头的镜像,其中有 8 种情况)。无论如何,对于其中的一半,您需要交换上下文的宽度和高度,对于其中的 6 个,您需要使用额外的转换矩阵。在这些情况下,我通常会采用试错法。因此,如果您可以使用视图执行此操作,然后使用该过程,它甚至可以用于调整大小、使用 fit、fill... 它也应该在后台线程上工作。
猜你喜欢
  • 2017-11-22
  • 2020-07-15
  • 2018-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多