116

How to flip the UIImage horizontally, I found UIImageOrientationUpMirrored enumeration value in the UIImage class reference, how to make use of this property to flip UIImage.

Bob Gilmore
  • 12,608
  • 13
  • 46
  • 53
pradeepa
  • 4,104
  • 5
  • 31
  • 41
  • To add to aroth's fine answer, Apple explains the other types of image orientations very well at [this link](http://developer.apple.com/library/ios/documentation/uikit/reference/UIImage_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006890-CH3-DontLinkElementID_2) – coco Oct 09 '11 at 16:31
  • As the accepted wasn't working for me, I found [this category](http://www.platinumball.net/blog/2010/01/31/iphone-uiimage-rotation-and-scaling/). Works like a charm. – dwbrito Dec 13 '13 at 12:54
  • If your app needs to support LTR and RTL, check out this question and its answers: https://stackoverflow.com/questions/20354498/flip-uiimageviews-for-right-to-left-languages – Andy Weinstein May 13 '21 at 09:10

19 Answers19

252

Objective-C

UIImage* sourceImage = [UIImage imageNamed:@"whatever.png"];

UIImage* flippedImage = [UIImage imageWithCGImage:sourceImage.CGImage 
                                            scale:sourceImage.scale
                                      orientation:UIImageOrientationUpMirrored];

Swift

let flippedImage = myImage.withHorizontallyFlippedOrientation()
iwasrobbed
  • 46,496
  • 21
  • 150
  • 195
aroth
  • 54,026
  • 20
  • 135
  • 176
  • 14
    There are two problems with this answer - scale isn't 1.0 at retina competible images and for some reason `UIImageOrientationUp` worked while `UIImageOrientationUpMirrored` didn't flip it. This worked - `image = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationUp]` – Kof Jun 03 '13 at 16:56
  • 1
    @Kof as I noticed, the orientation parameter that you pass in is used to determine 'what the sourceImage's orientation is already' as opposed to 'give me this image with this specific orientation'. Hence, you can inspect sourceImage.imageOrientation parameter and pass in a different orientation to trick the method to give you what you want – Ege Akpinar Jun 21 '13 at 10:21
  • 6
    It would be better to use `sourceImage.scale` for the scale. – Sam Soffes Oct 13 '13 at 23:55
  • How to do this in Swift? [UIImage imageWithCGImage...] is not available there. – Lim Thye Chean Jul 25 '14 at 22:46
  • @LimThyeChean `UIImage(CGImage: CGImage!, scale: CGFloat, orientation: UIImageOrientation)` – irmco Oct 24 '14 at 13:56
  • 3
    This seems to completely break when I try to do `[flippedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]`. Any idea why? – devios1 May 29 '15 at 18:54
  • @EgeAkpinar, That is incorrect. Using `UIImageOrientationDownMirrored`, flips the passed image over the horizontal axis. – Iulian Onofrei Sep 01 '17 at 15:11
  • This doesn't work for landscape and looks more like a hack – Nikolai Ischuk Dec 16 '19 at 08:53
76

A very simple way you can achieve this is by creating a UIImageView instead of a UIImage and do the transform on UIImageView.

yourImageView.image =[UIImage imageNamed:@"whatever.png"];
yourImageView.transform = CGAffineTransform(scaleX: -1, y: 1); //Flipped

Hope this helps.

Peter Kreinz
  • 7,979
  • 1
  • 64
  • 49
A. Adam
  • 3,094
  • 1
  • 26
  • 25
  • 2
    This ended up working much better for me than the `UIImage` manipulation, which I found had side effects when combined with `UIImageRenderingModeAlwaysTemplate` rendering mode. – devios1 Jun 01 '15 at 23:57
  • 2
    Thank you for sharing this. I had no luck with the "answer" to this puzzle associated with this post, but your answer worked phenomenally well and was only 1 line of code. – Adrian Jul 17 '15 at 19:52
  • Works great! iOS 9+ now also includes flipsForRightToLeftLayoutDirection, but it won't work for iOS 8+ apps yet. –  Jun 27 '16 at 23:40
  • 3
    If you want to reset flipping, then use `yourImageView.transform = CGAffineTransformIdentity` – chanil Oct 19 '16 at 08:57
  • Note this method 'transforms' on UIImageView. It doesn't flip the actual UIImage. – slow Dec 09 '16 at 08:11
  • If you need to transform the content, transform the container is not a reliable solution. If I need to save or send the image I couldn't just flip all UIImageViews, I need to flip the UImage... – Oni_01 Jun 25 '19 at 14:06
  • 1
    Xcode doesn't even recognize this: `CGAffineTransform(scaleX: -1, y: 1)` – ekashking Oct 16 '21 at 01:37
36

Vertical flip is often required to initialise OpenGL texture using glTexImage2d(...). The above proposed tricks do not actually modify image data and will not work in this case. Here is a code to do the actual data flip inspired by https://stackoverflow.com/a/17909372

- (UIImage *)flipImage:(UIImage *)image
{
    UIGraphicsBeginImageContext(image.size);
    CGContextDrawImage(UIGraphicsGetCurrentContext(),CGRectMake(0.,0., image.size.width, image.size.height),image.CGImage);
    UIImage *i = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return i;
}
Community
  • 1
  • 1
Alexey Podlasov
  • 993
  • 10
  • 18
16

I have tried with imageFlippedForRightToLeftLayoutDirection, and creating a new UIImage with diferent orientations but at least this is the only solution I found for flipping my image

let ciimage: CIImage = CIImage(CGImage: imagenInicial.CGImage!)
let rotada3 = ciimage.imageByApplyingTransform(CGAffineTransformMakeScale(-1, 1))

As you can see in my playground it worked!! :) enter image description here

And the, of course, let finalImage = UIImage(CIImage: rotada3)

abanet
  • 1,327
  • 17
  • 22
12

As it Image Orientation Defines:

typedef NS_ENUM(NSInteger, UIImageOrientation) {
UIImageOrientationUp,            // default orientation
UIImageOrientationDown,          // 180 deg rotation
UIImageOrientationLeft,          // 90 deg CCW
UIImageOrientationRight,         // 90 deg CW
UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip
UIImageOrientationDownMirrored,  // horizontal flip
UIImageOrientationLeftMirrored,  // vertical flip
UIImageOrientationRightMirrored, // vertical flip
};

I made some improvements for more circumstances like handling UIImage from AVCaptureSession.

UIImage* sourceImage = [UIImage imageNamed:@"whatever.png"];
UIImageOrientation flipingOrientation;
if(sourceImage.imageOrientation>=4){
    flippedOrientation = sourceImage.imageOrientation - 4;
}else{
    flippedOrientation = sourceImage.imageOrientation + 4;
}
UIImage* flippedImage = [UIImage imageWithCGImage:sourceImage.CGImage 
                     scale: sourceImage.scale orientation: flipingOrientation];
Henry
  • 481
  • 4
  • 17
11

This is a solid implementation to mirror/flip an UIImage horizontally, and can apply to the image back and forth. Since it changes the underlying image data, the drawing(like, screenshot) will also change. Tested to work, no quality loss.

func flipImage() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        let bitmap = UIGraphicsGetCurrentContext()!

        bitmap.translateBy(x: size.width / 2, y: size.height / 2)
        bitmap.scaleBy(x: -1.0, y: -1.0)

        bitmap.translateBy(x: -size.width / 2, y: -size.height / 2)
        bitmap.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return image?
}
code4latte
  • 560
  • 9
  • 9
  • Worked perfectly! but just wondering, how expensive is this one in terms of memory? Let's say doing this for 5 images a the same time. Thanks! – Joaquin Pereira Jul 11 '22 at 17:23
10

iOS 10+

[myImage imageWithHorizontallyFlippedOrientation];

Swift 4:

let flippedImage = myImage.withHorizontallyFlippedOrientation()
Kheldar
  • 5,361
  • 3
  • 34
  • 63
Roman Solodyashkin
  • 799
  • 12
  • 17
  • 1
    Banging my head against the wall that `imageWithHorizontallyFlippedOrientation` is supported but not `imageWithVerticallyFlippedOrientation` – Albert Renshaw Sep 28 '22 at 04:32
9

here's swift version: (I saw this question in comments)

let srcImage = UIImage(named: "imageName")
let flippedImage = UIImage(CGImage: srcImage.CGImage, scale: srcImage.scale, orientation: UIImageOrientation.UpMirrored)
eis
  • 51,991
  • 13
  • 150
  • 199
rts
  • 359
  • 4
  • 9
6

For Swift 3/4:

imageView.transform = CGAffineTransform(scaleX: -1, y: 1)
Shaked Sayag
  • 5,712
  • 2
  • 31
  • 38
5

May be this will be of use for some:

    UIImageOrientation imageOrientation;

    switch (sourceImage.imageOrientation) {
        case UIImageOrientationDown:
            imageOrientation = UIImageOrientationDownMirrored;
            break;

        case UIImageOrientationDownMirrored:
            imageOrientation = UIImageOrientationDown;
            break;

        case UIImageOrientationLeft:
            imageOrientation = UIImageOrientationLeftMirrored;
            break;

        case UIImageOrientationLeftMirrored:
            imageOrientation = UIImageOrientationLeft;

            break;

        case UIImageOrientationRight:
            imageOrientation = UIImageOrientationRightMirrored;

            break;

        case UIImageOrientationRightMirrored:
            imageOrientation = UIImageOrientationRight;

            break;

        case UIImageOrientationUp:
            imageOrientation = UIImageOrientationUpMirrored;
            break;

        case UIImageOrientationUpMirrored:
            imageOrientation = UIImageOrientationUp;
            break;
        default:
            break;
    }

    resultImage = [UIImage imageWithCGImage:sourceImage.CGImage scale:sourceImage.scale orientation:imageOrientation];
Sathe_Nagaraja
  • 163
  • 1
  • 9
3

A simple extension.

extension UIImage {

    var flipped: UIImage {
        guard let cgImage = cgImage else {
            return self
        }

        return UIImage(cgImage: cgImage, scale: scale, orientation: .upMirrored)
    }
}

Usage:

let image = #imageLiteral(resourceName: "imageName")
let imageView = UIImageView(image: image.flipped)
Eric Armstrong
  • 646
  • 6
  • 17
  • Extensions are one of the best features of Swift. I"m surprised that the original answers above failed to recommend that. I like this version a lot better. – DS. May 10 '18 at 01:59
1

This is a working iOS8/9 compatible version:

UIImage *image = [UIImage imageNamed:name];

if ([[UIApplication sharedApplication] userInterfaceLayoutDirection] == UIUserInterfaceLayoutDirectionRightToLeft) {

    if ([image respondsToSelector:@selector(imageFlippedForRightToLeftLayoutDirection)]) {
        //iOS9
        image = image.imageFlippedForRightToLeftLayoutDirection;
    }
    else {
        //iOS8
        CIImage *coreImage = [CIImage imageWithCGImage:image.CGImage];
        coreImage = [coreImage imageByApplyingTransform:CGAffineTransformMakeScale(-1, 1)];
        image = [UIImage imageWithCIImage:coreImage scale:image.scale orientation:UIImageOrientationUp];
    }
}

return image;
capikaw
  • 12,232
  • 2
  • 43
  • 46
  • I dont think this is the best idea. This `imageFlippedForRightToLeftLayoutDirection ` is meant to be used with flipped layout directions - for example for arabic countries. So using this might not always work as desired. – Tankista Jan 21 '16 at 12:54
  • 1
    Yes, you're correct - in my case it was exactly for RTL support. We all know code on SO is for reference and people don't really just copy/paste without understanding it first, right? – capikaw Jan 21 '16 at 16:12
1

Tested in Swift 3 and above

Here is the simple solution to achieve this problem with extensions. I test it and it worked. You can mirror in any direction.

extension UIImage {

    func imageUpMirror() -> UIImage {
        guard let cgImage = cgImage else { return self }
        return UIImage(cgImage: cgImage, scale: scale, orientation: .upMirrored)
    }

    func imageDownMirror() -> UIImage {
        guard let cgImage = cgImage else { return self }
        return UIImage(cgImage: cgImage, scale: scale, orientation: .downMirrored)
    }

    func imageLeftMirror() -> UIImage {
        guard let cgImage = cgImage else { return self }
        return UIImage(cgImage: cgImage, scale: scale, orientation: .leftMirrored)
    }

    func imageRightMirror() -> UIImage {
        guard let cgImage = cgImage else { return self }
        return UIImage(cgImage: cgImage, scale: scale, orientation: .rightMirrored)
    }
}

Usage for this code

let image = #imageLiteral(resourceName: "imageName")
flipHorizontally = image.imageUpMirror()

So on, You can use other functions.

Rehan Ali
  • 428
  • 4
  • 8
0

Here's one of the answers above modified and in Swift 3 that i found particularly useful when you have a button that needs to keep flipping the image back and forth.

func flipImage(sourceImage: UIImage,orientation: UIImageOrientation) -> UIImage {


        var imageOrientation = orientation

        switch sourceImage.imageOrientation {

        case UIImageOrientation.down:
            imageOrientation = UIImageOrientation.downMirrored;
            break;

        case UIImageOrientation.downMirrored:
            imageOrientation = UIImageOrientation.down;
            break;

        case UIImageOrientation.left:
            imageOrientation = UIImageOrientation.leftMirrored;
            break;

        case UIImageOrientation.leftMirrored:
            imageOrientation = UIImageOrientation.left;

            break;

        case UIImageOrientation.right:
            imageOrientation = UIImageOrientation.rightMirrored;

            break;

        case UIImageOrientation.rightMirrored:
            imageOrientation = UIImageOrientation.right;

            break;

        case UIImageOrientation.up:
            imageOrientation = UIImageOrientation.upMirrored;
            break;

        case UIImageOrientation.upMirrored:
            imageOrientation = UIImageOrientation.up;
            break;


        }


        return UIImage(cgImage: sourceImage.cgImage!, scale: sourceImage.scale, orientation: imageOrientation)

    }

Use:

imageToFlip: UIImage = flipImage(sourceImage: imageToFlip, orientation: imageToFlip.imageOrientation)
Sam Bing
  • 2,794
  • 1
  • 19
  • 29
0

aroth's answer in SWIFT 3:

let sourceImage = UIImage(named: "whatever.png")!
let flippedImage = UIImage(cgImage: sourceImage.cgImage!, scale: sourceImage.scale, orientation: .upMirrored)
maniarali
  • 31
  • 5
0

Swift 4

yourImage.transform = CGAffineTransform(scaleX: -1, y: 1)
Ahmad F
  • 30,560
  • 17
  • 97
  • 143
Faris
  • 1,206
  • 1
  • 12
  • 18
  • 3
    Code-only answers are generally considered low-quality. In addition to your code, explain how/why it works, fixes the problem, or answers the question. – chharvey Dec 13 '17 at 23:51
  • 1
    Also, this doesn't work for the OPs question, as he is asking to flip the image. The code here flips the image view. Both are very different in terms of where they can be used. e.g. a button takes an image not an image view. – DS. May 10 '18 at 01:53
  • Also, you just copied my answer and wrote swift 4 – Shaked Sayag Jul 03 '18 at 15:00
0

Due to unwrapping do the following:

let srcImage = UIImage(named: "myimage")!
let flippedImage = UIImage(cgImage: srcImage.cgImage!, 
                   scale: srcImage.scale, orientation: UIImage.Orientation.upMirrored)
Mike Zriel
  • 1,575
  • 1
  • 17
  • 28
0

you can rotate the image as you want using this

SWIFT 4

extension UIImage {
public func imageRotatedByDegrees(degrees: CGFloat, flip: Bool) -> UIImage {
    let radiansToDegrees: (CGFloat) -> CGFloat = {
        return $0 * (180.0 / CGFloat(M_PI))
    }
    let degreesToRadians: (CGFloat) -> CGFloat = {
        return $0 / 180.0 * CGFloat(M_PI)
    }

    // calculate the size of the rotated view's containing box for our drawing space
    let rotatedViewBox = UIView(frame: CGRect(origin: CGPoint.zero, size: size))
    let t = CGAffineTransform(rotationAngle: degreesToRadians(degrees));
    rotatedViewBox.transform = t
    let rotatedSize = rotatedViewBox.frame.size

    // Create the bitmap context
    UIGraphicsBeginImageContext(rotatedSize)
    let bitmap = UIGraphicsGetCurrentContext()!

    bitmap.translateBy(x: rotatedSize.width / 2.0, y: rotatedSize.height / 2.0)
    // Move the origin to the middle of the image so we will rotate and scale around the center.
    //CGContextTranslateCTM(bitmap, rotatedSize.width / 2.0, rotatedSize.height / 2.0);

    //   // Rotate the image context
    bitmap.rotate(by: degreesToRadians(degrees))
   // CGContextRotateCTM(bitmap, degreesToRadians(degrees));

    // 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)
    //CGContextScaleCTM(bitmap, yFlip, -1.0)
    bitmap.draw(self.cgImage!, in: CGRect.init(x: -size.width / 2, y: -size.height / 2, width: size.width, height: size.height))
   // CGContextDrawImage(bitmap, CGRectMake(-size.width / 2, -size.height / 2, size.width, size.height), CGImage)

    let newImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()

    return newImage
}

}

-2

Swift 5 - Xcode 11.5

The best solution for rotates horizontally: Watch this video:

https://m.youtube.com/watch?v=4kSLbuB-MlU

Or use this code:

    
import UIKit
class FirstViewControl: UIViewController {
    @IBOutlet weak var buttonAnim: UIButton!

    @IBAction func ClickOnButtonAnim(_ sender: UIButton) {    
        UIView.transition(with: buttonAnim, duration: 0.4, options: .transitionFlipFromLeft, animation: nil , completion: nil)
    }

}

You can use any ui(button or label or uiview or image) in this animation.

OliaPh
  • 29
  • 3
  • 1
    It is not recommended to post a link as an answer. The link could become invalid some day. If you believe the method is helpful, could you please post it here? – Christopher Jul 15 '20 at 11:53