Como virar o UIImage horizontalmente?

111

Como inverter UIImagehorizontalmente, encontrei o UIImageOrientationUpMirroredvalor de enumeração na UIImagereferência de classe, como usar essa propriedade para inverter UIImage.

pradeepa
fonte
Para adicionar à bela resposta de Aroth, a Apple explica os outros tipos de orientações de imagem muito bem neste link
coco,
Como o aceito não estava funcionando para mim, encontrei essa categoria . Funciona como um encanto.
dwbrito

Respostas:

238

Objective-C

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

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

Rápido

let flippedImage = myImage.withHorizontallyFlippedOrientation()
aroth
fonte
14
Há dois problemas com essa resposta - a escala não é 1,0 em imagens competíveis de retina e por algum motivo UIImageOrientationUpfuncionou enquanto UIImageOrientationUpMirrorednão girava . Isso funcionou -image = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationUp]
Kof
1
@Kof como notei, o parâmetro de orientação que você passa é usado para determinar 'qual a orientação da sourceImage já é' em oposição a 'me dê esta imagem com esta orientação específica'. Portanto, você pode inspecionar o parâmetro sourceImage.imageOrientation e passar em uma orientação diferente para enganar o método e fornecer o que você deseja
Ege Akpinar
6
Seria melhor usar sourceImage.scalepara a escala.
Sam Soffes
Como fazer isso no Swift? [UIImage imageWithCGImage ...] não está disponível lá.
Lim Thye Chean
3
Isso parece quebrar completamente quando tento fazer [flippedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]. Alguma ideia do porquê?
devios1
70

Uma maneira muito simples de conseguir isso é criando um UIImageView em vez de um UIImage e fazer a transformação em UIImageView.

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

Espero que isto ajude.

A. Adam
fonte
2
Isso acabou funcionando muito melhor para mim do que a UIImagemanipulação, que descobri que tinha efeitos colaterais quando combinada com o UIImageRenderingModeAlwaysTemplatemodo de renderização.
devios1 01 de
2
Obrigado por compartilhar isso. Não tive sorte com a "resposta" para este quebra-cabeça associado a este post, mas sua resposta funcionou incrivelmente bem e foi apenas 1 linha de código.
Adrian
Funciona bem! iOS 9+ agora também inclui flipsForRightToLeftLayoutDirection, mas ainda não funciona para aplicativos iOS 8+.
3
Se você deseja redefinir a inversão, useyourImageView.transform = CGAffineTransformIdentity
chanil
Observe este método 'transforma' em UIImageView. Ele não inverte o UIImage real.
lento
36

A inversão vertical geralmente é necessária para inicializar a textura OpenGL usando glTexImage2d(...). Os truques propostos acima não modificam os dados da imagem e não funcionarão neste caso. Aqui está um código para fazer a inversão de dados real inspirado em 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
fonte
1
Como esta imagem inverte? Parece que desenhou a imagem novamente.
Jonathan.
@Jonathan. Acho que muda devido a diferentes sistemas de coordenadas (ou seja, direção do eixo Y) durante o desenho.
Alexey Podlasov
Existe uma maneira de usar isso para virar a imagem verticalmente?
Praxiteles
este método também suporta renderização de imagem - sempre modelo
Peter Stajger
3
Para corrigir o problema de qualidade, use UIGraphicsBeginImageContextWithOptions (image.size, NO, image.scale); em vez de.
Nick Lockwood
14

Eu tentei com imageFlippedForRightToLeftLayoutDirection e criei um novo UIImage com orientações diferentes, mas pelo menos esta é a única solução que encontrei para inverter minha imagem

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

Como vocês podem ver no meu playground funcionou !! :) insira a descrição da imagem aqui

E, é claro, vamos finalImage = UIImage (CIImage: rotada3)

abanet
fonte
Desculpe, mas isso parece que não está funcionando mais, pelo menos com fotos tiradas com a câmera ...
Oni_01
12

Como a orientação da imagem define:

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

Fiz algumas melhorias para mais circunstâncias, como lidar com UIImage de 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
fonte
9

aqui está a versão rápida: (eu vi essa pergunta nos comentários)

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

iOS 10+

[myImage imageWithHorizontallyFlippedOrientation];

Swift 4:

let flippedImage = myImage.withHorizontallyFlippedOrientation()
Solodyashkin romano
fonte
7

Esta é uma implementação sólida para espelhar / virar um UIImage horizontalmente e pode ser aplicada à imagem para frente e para trás. Uma vez que altera os dados da imagem subjacente, o desenho (como captura de tela) também será alterado. Testado para funcionar, sem perda de qualidade.

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
fonte
5

Pode ser que isso seja útil para alguns:

    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
fonte
5

Para Swift 3/4:

imageView.transform = CGAffineTransform(scaleX: -1, y: 1)
Shaked Sayag
fonte
Isto é para um UIImageView, o OP está procurando por um UIImage
Shizam
2

Uma extensão simples.

extension UIImage {

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

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

Uso:

let image = #imageLiteral(resourceName: "imageName")
let imageView = UIImageView(image: image.flipped)
Eric Armstrong
fonte
As extensões são um dos melhores recursos do Swift. Estou surpreso que as respostas originais acima não recomendaram isso. Gosto muito mais desta versão.
DS.
1

Esta é uma versão funcional compatível com 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
fonte
Não acho que seja a melhor ideia. Isso imageFlippedForRightToLeftLayoutDirection deve ser usado com instruções de layout invertidas - por exemplo, para países árabes. Portanto, usar isso pode nem sempre funcionar como desejado.
Peter Stajger
1
Sim, você está correto - no meu caso foi exatamente para suporte RTL. Todos nós sabemos que o código no SO é para referência e as pessoas realmente não apenas copiam / colam sem entender primeiro, certo?
capikaw
1

Testado em Swift 3 e superior

Aqui está a solução simples para resolver esse problema com extensões. Eu testei e funcionou. Você pode espelhar em qualquer direção.

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

Uso para este código

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

Assim por diante, você pode usar outras funções.

Rehan Ali
fonte
0

Aqui está uma das respostas acima modificadas e no Swift 3 que achei particularmente útil quando você tem um botão que precisa ficar virando a imagem para frente e para trás.

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)

    }

Usar:

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

A resposta de Aroth em SWIFT 3:

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

Swift 4

yourImage.transform = CGAffineTransform(scaleX: -1, y: 1)
Faris
fonte
3
As respostas apenas em código são geralmente consideradas de baixa qualidade. Além de seu código, explique como / por que ele funciona, corrige o problema ou responde à pergunta.
chharvey
1
Além disso, isso não funciona para a pergunta de OPs, pois ele está pedindo para inverter a imagem. O código aqui inverte a visualização da imagem. Ambos são muito diferentes em termos de onde podem ser usados. por exemplo, um botão obtém uma imagem, não uma visualização da imagem.
DS.
Além disso, você acabou de copiar minha resposta e escreveu swift 4
Shaked Sayag
0

Devido ao desembrulhar, faça o seguinte:

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

você pode girar a imagem como quiser usando este

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
fonte
0

Swift 5 - Xcode 11.5

A melhor solução para rotação horizontal: Assista a este vídeo:

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

Ou use este código:

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

}

Você pode usar qualquer ui (botão ou rótulo ou uiview ou imagem) nesta animação.

OliaPh
fonte
1
Não é recomendado postar um link como resposta. O link pode se tornar inválido algum dia. Se você acredita que o método é útil, você poderia publicá-lo aqui?
Christopher