45

The solution to do UIImage flipping is with the Objective-C code:

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

However, imageWithCGImage is not available in Swift! Is there a solution for flipping image horizontally with Swift? Thanks!

Shruti Thombre
  • 989
  • 4
  • 11
  • 27
Lim Thye Chean
  • 8,704
  • 9
  • 49
  • 88

9 Answers9

49

For me the simplest way was to use the .withHorizontallyFlippedOrientation() instance method of UIImage as follows:

let flippedImage = straightImage.withHorizontallyFlippedOrientation()

Simple one-liners always make me happy :)

Francesco D.M.
  • 2,129
  • 20
  • 27
35

Most factory methods are converted to initializers in swift. Whenever available, even if the class method is still available, they are preferred. You can use:

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

The usage would look like this:

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

Swift 5

var image = UIImage(cgImage: img.cgImage!, scale: 1.0, orientation: .downMirrored)
Khaled Annajar
  • 15,542
  • 5
  • 34
  • 45
drewag
  • 93,393
  • 28
  • 139
  • 128
  • 11
    Tried this and it doesn't seem to flip the image. Is there a way to respect the orientation when rendering? `public extension UIImage { var flippedHorizontally: UIImage { return UIImage(CGImage: self.CGImage!, scale: self.scale, orientation: .UpMirrored) } }` – Kudit Feb 09 '16 at 04:17
  • Oh... I was using the .LeftMirrored option for selfie photos. It works well to display the photo after the flipping. However, the photo is upside down after saving to photo album. Any ideas? – RainCast Jul 15 '16 at 03:16
  • 1
    @Gujamin, that extension worked perfectly. I converted it into Swift 3 syntax and was able to swap the image of a UIButton with no problem. Thanks. – liquidki Aug 02 '16 at 21:52
  • The answer is wrong. When I create `UIBarButtonItem` with the original image its scale is normal. But when I use your method image becomes huge! Note: I don't apply any transformations to an image other than your one - just assign it to bar button item – Gargo Feb 22 '23 at 06:04
34

In Swift.... (6.3.1)

YourUIImage.transform = CGAffineTransformMakeScale(-1, 1)

This also works with a UIView

duyn9uyen
  • 9,585
  • 12
  • 43
  • 54
19

Changing image orientation parameter is not actually flipping the image in all cases. Image must be redrawn somehow... For example like this:

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
}
Alex Shubin
  • 3,549
  • 1
  • 27
  • 32
  • 1)why do you scale by x and y simultaneously? 2)when I assign the image result from your function it disappears in `UIBarButtonItem` – Gargo Feb 22 '23 at 06:18
13

Swift 5 Solution

Here is the simplest solution for actually flipping the image

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

and to use this solution you can do the following

let image = UIImage(named: "image.png")!
let newImage = image.flipHorizontally()
Josh Bernfeld
  • 4,246
  • 2
  • 32
  • 35
10

Swift 4

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

This might also be handy:

YOURIMAGE.imageFlippedForRightToLeftLayoutDirection()
Ahmadreza
  • 6,950
  • 5
  • 50
  • 69
2

To flip image in 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
    }

}


}
2

Swift 5

If your use case requires saving the UIImage after transforming, it will need to be drawn into a new 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)
    }
  }
}
jimj
  • 1,005
  • 2
  • 11
  • 22
0

There is couple of similar questions on SO. And I believe it's worth to post solution using CoreImage here too.

Please note: when getting final UIImage, it's necessary to convert to CGImage first to respect extent of 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)
    }
}
Martin Pilch
  • 3,245
  • 3
  • 38
  • 61