如何使用Swift水平翻转UIImage?

45

UIImage翻转的解决方案是使用Objective-C代码:

[UIImage imageWithCGImage:img.CGImage scale:1.0 orientation: UIImageOrientationDownMirrored]

不过,在Swift中无法使用imageWithCGImage!有没有在Swift中水平翻转图像的解决方案?谢谢!

9个回答

50

对我来说,最简单的方法是使用UIImage.withHorizontallyFlippedOrientation()实例方法,如下所示:

let flippedImage = straightImage.withHorizontallyFlippedOrientation()

简单的一行代码总是让我感到高兴 :)


2
优秀,但不尊重从AVFoundation捕获的图像的垂直方向-翻转图像颠倒。 - Alex Stone
也许在 withHorizontallyFlippedOrientation() 之后有一种调整的方法? - Francesco D.M.
3
可用(iOS 10.0, *) - Yaroslav Dukal
这似乎在我的MacOS上会有明显的性能损失。如果我的图片很小,或者我只是偶尔这样做,那还好。但如果需要响应式的话,可能就不太合适了。 - undefined

36

大多数工厂方法在 Swift 中被转换为初始化器。只要有可能,即使类方法仍然可用,也会优先使用它们。你可以使用:

大多数工厂方法在Swift中被转换为初始化器。只要有可能,即使类方法仍然可用,也会优先使用它们。你可以使用:

    init(CGImage cgImage: CGImage!, scale: CGFloat, orientation: UIImageOrientation)

使用方法如下:

var image = UIImage(CGImage: img.CGImage, scale: 1.0, orientation: .DownMirrored)

Swift 5

->

Swift 5

var image = UIImage(cgImage: img.cgImage!, scale: 1.0, orientation: .downMirrored)

11
尝试过这个方法,但似乎不能翻转图像。在渲染时是否有一种方式可以保持方向?public extension UIImage { var flippedHorizontally: UIImage { return UIImage(CGImage: self.CGImage!, scale: self.scale, orientation: .UpMirrored) } } - Kudit
哦...我在自拍照片中使用了.LeftMirrored选项。它可以很好地显示翻转后的照片。然而,保存到相册后,照片是倒置的。有什么想法吗? - RainCast
1
@Gujamin,那个扩展完美地工作了。我将它转换为Swift 3语法,并且能够轻松地交换UIButton的图像。谢谢。 - liquidki
答案是错误的。当我使用原始图像创建 UIBarButtonItem 时,其比例尺寸是正常的。但是当我使用您的方法时,图像变得巨大!注意:除了您的方法之外,我不对图像应用任何转换 - 只是将其分配给工具栏按钮项。 - Gargo

33

在 Swift 中.... (6.3.1)

YourUIImage.transform = CGAffineTransformMakeScale(-1, 1)

这也适用于UIView


57
这不是为了翻转一张 UIImage,而是为了翻转 UIImageView - Léo Natan
2
这不是翻转UIImage的问题。但它解决了我的UI问题。 - AechoLiu
并非所有的UI元素都是从UIView派生而来,因此它们没有transform属性(例如UIBarButtonItem)。 - Gargo

18

更改图像方向参数并不总是翻转图像。在某些情况下,必须以某种方式重新绘制图像...例如:

Swift 3


Swift 3

func flipImageLeftRight(_ image: UIImage) -> UIImage? {

    UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
    let context = UIGraphicsGetCurrentContext()!
    context.translateBy(x: image.size.width, y: image.size.height)
    context.scaleBy(x: -image.scale, y: -image.scale)

    context.draw(image.cgImage!, in: CGRect(origin:CGPoint.zero, size: image.size))

    let newImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return newImage
}

  1. 为什么要同时按比例缩放x和y?
  2. 当我从您的函数中分配图像结果到UIBarButtonItem时,它会消失。
- Gargo

14

Swift 5 解决方案

这是实际翻转图像的最简解决方案。

extension UIImage {
    func flipHorizontally() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        let context = UIGraphicsGetCurrentContext()!
        
        context.translateBy(x: self.size.width/2, y: self.size.height/2)
        context.scaleBy(x: -1.0, y: 1.0)
        context.translateBy(x: -self.size.width/2, y: -self.size.height/2)
        
        self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
        
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return newImage
    }
}

使用此解决方案,您可以执行以下操作:

let image = UIImage(named: "image.png")!
let newImage = image.flipHorizontally()

这会创建黑色背景图像而不是透明的。请注意。 - Jeff Bootsholz
@RajuyourPepe,我已经更新了答案以允许透明度。谢谢! - Josh Bernfeld
1
非常好的答案!如果有人想要垂直翻转图像,只需将 context.scaleBy(x: -1.0, y: 1.0) 更改为 context.scaleBy(x: 1.0, y: -1.0) 即可。 - Ali Pacman

10

Swift 4

YOURIMAGEVIEW.transform = CGAffineTransform(scaleX: -1, y: 1)

这也许会很方便:

YOURIMAGE.imageFlippedForRightToLeftLayoutDirection()

14
问题涉及UIImage,不是UIImageView。 - Andrei A.
2
这不是正确的答案,但在其他情况下它对我有用,谢谢。 - Patel Jigar

2

Swift 5

如果您的用例需要在转换后保存UIImage,则需要将其绘制到新的CGContext中。

extension UIImage {
  
  enum Axis {
    case horizontal, vertical
  }
  
  func flipped(_ axis: Axis) -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: size)
    
    return renderer.image {
      let context = $0.cgContext
      context.translateBy(x: size.width / 2, y: size.height / 2)
      
      switch axis {
      case .horizontal:
        context.scaleBy(x: -1, y: 1)
      case .vertical:
        context.scaleBy(x: 1, y: -1)
      }
      
      context.translateBy(x: -size.width / 2, y: -size.height / 2)
      
      draw(at: .zero)
    }
  }
}

使用方法:imgClone.image = pickedImage.flipped(.vertical) - M Hamayun zeb

2

在Swift 4中翻转图像

class ViewController: UIViewController {
var first = 1
var second = 1

@IBOutlet weak var img: UIImageView!
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

@IBAction func flip1(_ sender: Any) {

    if first == 1 {
        img.transform = CGAffineTransform(scaleX: -1, y: 1)
        first = 2
    }
    else if first == 2
    {
        img.transform = CGAffineTransform(scaleX: +1, y: 1)
        first = 1
    }

}


}

0

在SO上有几个类似的问题。我相信在这里也值得使用CoreImage发布解决方案。

请注意:在获取最终的UIImage时,必须先转换为CGImage以尊重CIImage的范围。

extension UIImage {
    func imageRotated(by degrees: CGFloat) -> UIImage {

        let orientation = CGImagePropertyOrientation(imageOrientation)
        // Create CIImage respecting image's orientation 
        guard let inputImage = CIImage(image: self)?.oriented(orientation) 
            else { return self }

        // Flip the image itself
        let flip = CGAffineTransform(scaleX: 1, y: -1)
        let outputImage = inputImage.transformed(by: flip)

        // Create CGImage first
        guard let cgImage = CIContext().createCGImage(outputImage, from: outputImage.extent) 
            else { return self }

        // Create output UIImage from CGImage
        return UIImage(cgImage: cgImage)
    }
}

Cannot convert value of type 'UIImage.Orientation' to expected argument type 'UInt32' - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接