Comment retourner UIImage horizontalement?

111

Comment retourner UIImagehorizontalement, j'ai trouvé la UIImageOrientationUpMirroredvaleur d'énumération dans la UIImageréférence de classe, comment utiliser cette propriété pour retourner UIImage.

Pradepa
la source
Pour ajouter à la bonne réponse d'aroth, Apple explique très bien les autres types d'orientations d'image sur ce lien
coco
Comme l'accepté ne fonctionnait pas pour moi, j'ai trouvé cette catégorie . Fonctionne comme un charme.
dwbrito

Réponses:

238

Objectif c

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

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

Rapide

let flippedImage = myImage.withHorizontallyFlippedOrientation()
aroth
la source
14
Il y a deux problèmes avec cette réponse - l'échelle n'est pas de 1.0 pour les images compatibles avec la rétine et pour une raison quelconque, elle a UIImageOrientationUpfonctionné UIImageOrientationUpMirroredsans la retourner. Cela a fonctionné -image = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationUp]
Kof
1
@Kof comme je l'ai remarqué, le paramètre d'orientation que vous passez est utilisé pour déterminer «quelle est déjà l'orientation de sourceImage» par opposition à «donnez-moi cette image avec cette orientation spécifique». Par conséquent, vous pouvez inspecter le paramètre sourceImage.imageOrientation et passer dans une orientation différente pour tromper la méthode et vous donner ce que vous voulez
Ege Akpinar
6
Il serait préférable de l'utiliser sourceImage.scalepour l'échelle.
Sam Soffes
Comment faire cela dans Swift? [UIImage imageWithCGImage ...] n'y est pas disponible.
Lim Thye Chean
3
Cela semble complètement casser lorsque j'essaye de le faire [flippedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]. Une idée pourquoi?
devios1
70

Un moyen très simple d'y parvenir est de créer une UIImageView au lieu d'une UIImage et d'effectuer la transformation sur UIImageView.

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

J'espère que cela t'aides.

A. Adam
la source
2
Cela a fini par fonctionner beaucoup mieux pour moi que la UIImagemanipulation, qui, selon moi, avait des effets secondaires lorsqu'elle était combinée avec le UIImageRenderingModeAlwaysTemplatemode de rendu.
devios1
2
Merci de partager ceci. Je n'ai pas eu de chance avec la "réponse" à ce casse-tête associé à ce message, mais votre réponse a fonctionné de manière phénoménale et n'était qu'une ligne de code.
Adrian
Fonctionne très bien! iOS 9+ inclut désormais également flipsForRightToLeftLayoutDirection, mais cela ne fonctionnera pas encore pour les applications iOS 8+.
3
Si vous voulez réinitialiser le retournement, utilisezyourImageView.transform = CGAffineTransformIdentity
chanil
Notez cette méthode «transforme» sur UIImageView. Il ne retourne pas la véritable UIImage.
lent
36

Un retournement vertical est souvent nécessaire pour initialiser la texture OpenGL à l'aide de glTexImage2d(...). Les astuces proposées ci-dessus ne modifient pas réellement les données d'image et ne fonctionneront pas dans ce cas. Voici un code pour faire le flip de données réel inspiré par 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;
}
Alexey Podlasov
la source
1
Comment cette image flip? On dirait simplement qu'il dessine à nouveau l'image.
Jonathan.
@Jonathan. Je pense qu'il bascule en raison de différents systèmes de coordonnées (c'est-à-dire la direction de l'axe Y) lors du dessin.
Alexey Podlasov
Y a-t-il un moyen d'utiliser cela pour retourner l'image verticalement?
Praxiteles
cette méthode prend également en charge le rendu d'image - toujours modèle
Peter Stajger
3
Pour résoudre le problème de qualité, utilisez UIGraphicsBeginImageContextWithOptions (image.size, NO, image.scale); au lieu.
Nick Lockwood
14

J'ai essayé avec imageFlippedForRightToLeftLayoutDirection, et j'ai créé une nouvelle UIImage avec différentes orientations, mais au moins c'est la seule solution que j'ai trouvée pour retourner mon image

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

Comme vous pouvez le voir dans mon terrain de jeu, cela a fonctionné !! :) entrez la description de l'image ici

Et, bien sûr, laissez finalImage = UIImage (CIImage: rotada3)

abanet
la source
Désolé mais cela semble ne plus fonctionner, du moins avec des photos prises par la caméra ...
Oni_01
12

Tel que défini par l'orientation de l'image:

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

J'ai apporté quelques améliorations pour plus de circonstances comme la gestion de UIImage à partir d'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];
Henri
la source
9

voici la version rapide: (j'ai vu cette question dans les commentaires)

let srcImage = UIImage(named: "imageName")
let flippedImage = UIImage(CGImage: srcImage.CGImage, scale: srcImage.scale, orientation: UIImageOrientation.UpMirrored)
RomanTsopin
la source
8

iOS 10+

[myImage imageWithHorizontallyFlippedOrientation];

Swift 4:

let flippedImage = myImage.withHorizontallyFlippedOrientation()
Romain Solodyashkin
la source
7

Il s'agit d'une implémentation solide pour refléter / retourner une UIImage horizontalement et peut s'appliquer à l'image dans les deux sens. Puisqu'il change les données d'image sous-jacentes, le dessin (comme, capture d'écran) changera également. Testé pour fonctionner, aucune perte de qualité.

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
la source
5

Peut-être que cela sera utile pour certains:

    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
la source
5

Pour Swift 3/4:

imageView.transform = CGAffineTransform(scaleX: -1, y: 1)
Shaked Sayag
la source
Ceci est pour une UIImageView, l'OP recherche une UIImage
Shizam
2

Une 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
la source
Les extensions sont l'une des meilleures fonctionnalités de Swift. Je suis surpris que les réponses originales ci-dessus ne le recommandent pas. J'aime beaucoup mieux cette version.
DS.
1

Ceci est une version compatible iOS8 / 9:

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
la source
Je ne pense pas que ce soit la meilleure idée. Ceci imageFlippedForRightToLeftLayoutDirection est destiné à être utilisé avec des directions de mise en page inversées - par exemple pour les pays arabes. Donc, utiliser cela peut ne pas toujours fonctionner comme vous le souhaitez.
Peter Stajger
1
Oui, vous avez raison - dans mon cas, c'était exactement pour le support RTL. Nous savons tous que le code sur SO est pour référence et que les gens ne se contentent pas de copier / coller sans le comprendre d'abord, non?
capikaw
1

Testé dans Swift 3 et supérieur

Voici la solution simple pour résoudre ce problème avec les extensions. Je l'ai testé et cela a fonctionné. Vous pouvez refléter dans n'importe quelle 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)
    }
}

Utilisation de ce code

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

Ainsi de suite, vous pouvez utiliser d'autres fonctions.

Rehan Ali
la source
0

Voici l'une des réponses ci-dessus modifiées et dans Swift 3 que j'ai trouvée particulièrement utile lorsque vous avez un bouton qui doit continuer à faire pivoter l'image d'avant en arrière.

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)

    }

Utilisation:

imageToFlip: UIImage = flipImage(sourceImage: imageToFlip, orientation: imageToFlip.imageOrientation)
Sam Bing
la source
0

réponse d'aroth dans SWIFT 3:

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

Swift 4

yourImage.transform = CGAffineTransform(scaleX: -1, y: 1)
Faris
la source
3
Les réponses au code uniquement sont généralement considérées comme de mauvaise qualité. En plus de votre code, expliquez comment / pourquoi cela fonctionne, corrige le problème ou répond à la question.
chharvey
1
De plus, cela ne fonctionne pas pour la question OP, car il demande de retourner l'image. Le code ici bascule la vue de l'image. Les deux sont très différents quant à l'endroit où ils peuvent être utilisés. par exemple, un bouton prend une image et non une vue d'image.
DS.
De plus, vous venez de copier ma réponse et d'écrire swift 4
Shaked Sayag
0

En raison du déballage, procédez comme suit:

let srcImage = UIImage(named: "myimage")!
let flippedImage = UIImage(cgImage: srcImage.cgImage!, 
                   scale: srcImage.scale, orientation: UIImage.Orientation.upMirrored)
Mike Zriel
la source
0

vous pouvez faire pivoter l'image comme vous le souhaitez en utilisant ceci

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
}

}

Momen Shaheen
la source
0

Swift 5 - Xcode 11.5

La meilleure solution pour une rotation horizontale: regardez cette vidéo:

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

Ou utilisez ce 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)
    }

}

Vous pouvez utiliser n'importe quelle interface utilisateur (bouton ou étiquette ou uiview ou image) dans cette animation.

OliaPh
la source
1
Il n'est pas recommandé de publier un lien comme réponse. Le lien pourrait devenir invalide un jour. Si vous pensez que la méthode est utile, pourriez-vous la publier ici?
Christopher