How to flip UIImage horizontally?
Asked Answered
A

19

119

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.

Arawak answered 23/3, 2011 at 11:43 Comment(3)
To add to aroth's fine answer, Apple explains the other types of image orientations very well at this linkUsurious
As the accepted wasn't working for me, I found this category. Works like a charm.Valrievalry
If your app needs to support LTR and RTL, check out this question and its answers: #20354998Birgitbirgitta
H
255

Objective-C

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

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

Swift

let flippedImage = myImage.withHorizontallyFlippedOrientation()
Hartal answered 23/3, 2011 at 11:50 Comment(9)
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]Wenona
@Wenona 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 wantStoddard
It would be better to use sourceImage.scale for the scale.Hyrcania
How to do this in Swift? [UIImage imageWithCGImage...] is not available there.Pellicle
@LimThyeChean UIImage(CGImage: CGImage!, scale: CGFloat, orientation: UIImageOrientation)Crinoid
This seems to completely break when I try to do [flippedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]. Any idea why?Gymnasium
@EgeAkpinar, That is incorrect. Using UIImageOrientationDownMirrored, flips the passed image over the horizontal axis.Qualification
This doesn't work for landscape and looks more like a hackParodist
image disappears after withHorizontallyFlippedOrientationFreehand
P
78

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.

Postscript answered 30/12, 2014 at 9:34 Comment(7)
This ended up working much better for me than the UIImage manipulation, which I found had side effects when combined with UIImageRenderingModeAlwaysTemplate rendering mode.Gymnasium
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.Permeable
Works great! iOS 9+ now also includes flipsForRightToLeftLayoutDirection, but it won't work for iOS 8+ apps yet.Tyronetyrosinase
If you want to reset flipping, then use yourImageView.transform = CGAffineTransformIdentityContradict
Note this method 'transforms' on UIImageView. It doesn't flip the actual UIImage.Dilatant
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...Jaffna
Xcode doesn't even recognize this: CGAffineTransform(scaleX: -1, y: 1)Smoothshaven
A
35

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;
}
Ambidexterity answered 17/7, 2014 at 9:7 Comment(5)
How does this flip image? It just looks like it draws the image again.Extension
@Extension I think it flips due to different coordinate systems (i.e. Y axis direction) while drawing.Ambidexterity
Is there a way to use this to flip the image vertically?Claiborn
this method nicely supports also image rendering - always templateLdopa
To fix the quality issue, use UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale); instead.Dilisio
O
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)

Occam answered 21/10, 2015 at 9:38 Comment(1)
Sorry but this looks like not working anymore, at least with camera taken pictures...Jaffna
E
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];
Eyler answered 26/11, 2013 at 15:21 Comment(0)
A
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?
}
Abrogate answered 23/3, 2017 at 19:5 Comment(1)
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!Unman
C
11

iOS 10+

[myImage imageWithHorizontallyFlippedOrientation];

Swift 4:

let flippedImage = myImage.withHorizontallyFlippedOrientation()
Cruzcruzado answered 4/12, 2017 at 19:5 Comment(1)
Banging my head against the wall that imageWithHorizontallyFlippedOrientation is supported but not imageWithVerticallyFlippedOrientationKlusek
F
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)
Faludi answered 8/10, 2014 at 9:25 Comment(0)
W
6

For Swift 3/4:

imageView.transform = CGAffineTransform(scaleX: -1, y: 1)
Whitman answered 15/12, 2016 at 13:45 Comment(1)
This is for a UIImageView, the OP is looking for a UIImageVaccaro
K
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];
Kendrakendrah answered 23/1, 2014 at 5:7 Comment(0)
F
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)
Fleet answered 2/10, 2017 at 19:38 Comment(1)
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.Quietude
A
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;
Aleman answered 16/11, 2015 at 21:12 Comment(2)
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.Ldopa
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?Aleman
C
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.

Chemoreceptor answered 10/5, 2018 at 6:14 Comment(0)
B
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)
Bucharest answered 10/4, 2017 at 13:18 Comment(0)
E
0

aroth's answer in SWIFT 3:

let sourceImage = UIImage(named: "whatever.png")!
let flippedImage = UIImage(cgImage: sourceImage.cgImage!, scale: sourceImage.scale, orientation: .upMirrored)
Erik answered 3/10, 2017 at 7:1 Comment(0)
P
0

Swift 4

yourImage.transform = CGAffineTransform(scaleX: -1, y: 1)
Phelips answered 13/12, 2017 at 20:58 Comment(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.Britnibrito
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.Quietude
Also, you just copied my answer and wrote swift 4Whitman
B
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)
Brushwood answered 23/3, 2019 at 10:35 Comment(0)
N
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
}

}

Noahnoak answered 1/4, 2019 at 18:13 Comment(0)
C
-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.

Coneflower answered 15/7, 2020 at 11:47 Comment(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?Spinney

© 2022 - 2024 — McMap. All rights reserved.