简体   繁体   English

Swift-图像旋转度数-变形结果

[英]Swift - Image rotation in degrees - deformed result

I found several methods to rotate image by degrees in Swift but noone that works allright all the time. 我发现有几种方法可以在Swift中按度旋转图像,但是没有一种方法可以一直正常工作。 I want to rotate image by 90 degrees left or right. 我想向左或向右旋转图像90度。 I think the best one is this: 我认为最好的是:

  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
  }

It works and do what I want but there are few times when it deformes result so it's not rotated and just image size is changed or it's rotated by 180 degrees and image size is changed. 它可以正常工作并执行我想要的操作,但是变形的结果很少,因此它不会旋转,只是图像大小发生了改变,或者旋转了180度而图像大小发生了改变。

Before rotation: 轮换之前:

旋转前的图像

Afteer rotation (menu is missing because it's automatically hidden): 后续旋转(缺少菜单,因为它已自动隐藏):

旋转后的图像

What's weird is that this happens when I take photo in portrait. 奇怪的是,当我用人像拍照时会发生这种情况。 When I take photo in landscape the rotation works fine (even if I try to rotate several times and even if I rotate from landscape to portrait and than again to landscape, it's still works fine). 当我在横向拍照时,旋转效果很好(即使我尝试旋转几次,即使我从横向旋转到肖像,然后再旋转到横向,它仍然可以正常工作)。

I saw some discussion about auto layout constraints problem but I am not sure if it's my problem and why it would for some cases work and for some won't. 我看到了一些有关自动布局约束问题的讨论,但我不确定这是否是我的问题,以及为什么在某些情况下会起作用而在某些情况下不会起作用。 I have photos in collection cells and each cell has first UIScrollView and than in UIScrollView there is UIImageView with photo. 我在集合单元格中有照片,每个单元格都有第一个UIScrollView,然后在UIScrollView中有带照片的UIImageView。 All constraints are set to bounds. 所有约束均设置为界限。

If it helps I want only rotate by 90 or -90 degrees. 如果有帮助,我只想旋转90或-90度。 This could maybe make method more simple andn fix easier. 这可能会使方法更简单,并且修复起来更容易。

Thanks for any help. 谢谢你的帮助。

Actually the easiest and probably the best way is to create a view, put an image view on it, rotate the image view, resize the superview and create a screenshot of that view. 实际上,最简单且可能最好的方法是创建视图,在其上放置图像视图,旋转图像视图,调整超级视图的大小并创建该视图的屏幕快照。

You do not actually add these views in the view hierarchy, you just use them to easily generate an image. 您实际上并没有在视图层次结构中添加这些视图,而只是使用它们来轻松生成图像。

Why this is a good procedure is because the UIView already has all the code written in it to fully support the core graphics. 之所以这样做是一个好程序,是因为UIView已经编写了所有代码来完全支持核心图形。 So there is no downside at all and you can be sure these procedures have already been polished by Apple. 因此,没有任何弊端,您可以确定这些步骤已经被Apple完善了。

So try this: 所以试试这个:

    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
        }

    }

As for issue in your procedure it is most likely because you discard the transform from the UIImage . 至于过程中的问题,很可能是因为您放弃了UIImage的转换。 The CGImage is basically a raw image representation and it has no idea about the rotations. CGImage基本上是原始图像表示,并且对旋转没有任何想法。 The UIImage does have imageOrientation though. UIImage确实具有imageOrientation So what you would need to do to fix that is you need to generate the transformation matrix from the image orientation and use it. 因此,您需要解决的问题是需要从图像方向生成转换矩阵并使用它。

So when you take an image with your device the CGImage will always have the same orientation (landscape left or right). 因此,当您使用设备拍摄图像时, CGImage将始终具有相同的方向(左或右横向)。 But the UIImage will change the image orientation which is then used for representation. 但是, UIImage将更改图像方向,然后将其用于表示。

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

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