¿Cómo voltear UIImage horizontalmente?

111

Cómo voltear UIImagehorizontalmente, encontré el UIImageOrientationUpMirroredvalor de enumeración en la UIImagereferencia de la clase, cómo hacer uso de esta propiedad para voltear UIImage.

pradeepa
fuente
Para agregar a la excelente respuesta de Aroth, Apple explica muy bien los otros tipos de orientaciones de imagen en este enlace
coco
Como lo aceptado no me funcionaba, encontré esta categoría . Funciona de maravilla.
dwbrito

Respuestas:

237

C objetivo

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

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

Rápido

let flippedImage = myImage.withHorizontallyFlippedOrientation()
aroth
fuente
14
Hay dos problemas con esta respuesta: la escala no es 1.0 en las imágenes de la competencia de retina y, por alguna razón, UIImageOrientationUpfuncionó mientras UIImageOrientationUpMirroredno la invertía. Esto funcionó -image = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationUp]
Kof
1
@Kof, como noté, el parámetro de orientación que pasas se usa para determinar 'cuál es la orientación de sourceImage ya' en lugar de 'dame esta imagen con esta orientación específica'. Por lo tanto, puede inspeccionar el parámetro sourceImage.imageOrientation y pasar una orientación diferente para engañar al método para que le dé lo que desea
Ege Akpinar
6
Sería mejor utilizarlo sourceImage.scalepara la escala.
Sam Soffes
¿Cómo hacer esto en Swift? [UIImage imageWithCGImage ...] no está disponible allí.
Lim Thye Chean
3
Esto parece romperse por completo cuando intento hacerlo [flippedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]. ¿Alguna idea de por qué?
devios1
70

Una forma muy sencilla de lograr esto es creando un UIImageView en lugar de un UIImage y hacer la transformación en UIImageView.

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

Espero que esto ayude.

A. Adam
fuente
2
Esto terminó funcionando mucho mejor para mí que la UIImagemanipulación, que descubrí que tenía efectos secundarios cuando se combinaba con el UIImageRenderingModeAlwaysTemplatemodo de renderizado.
devios1
2
Gracias por compartir esto. No tuve suerte con la "respuesta" a este acertijo asociado con esta publicación, pero su respuesta funcionó fenomenalmente bien y fue solo una línea de código.
Adrian
¡Funciona genial! iOS 9+ ahora también incluye flipsForRightToLeftLayoutDirection, pero aún no funcionará para las aplicaciones iOS 8+.
3
Si desea restablecer el volteo, useyourImageView.transform = CGAffineTransformIdentity
chanil
Tenga en cuenta que este método se 'transforma' en UIImageView. No cambia el UIImage real.
lento
36

A menudo se requiere un giro vertical para inicializar la textura OpenGL usando glTexImage2d(...). Los trucos propuestos anteriormente no modifican realmente los datos de la imagen y no funcionarán en este caso. Aquí hay un código para hacer el cambio de datos real inspirado en 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
fuente
1
¿Cómo cambia esta imagen? Parece que vuelve a dibujar la imagen.
Jonathan.
@Jonathan. Creo que cambia debido a diferentes sistemas de coordenadas (es decir, dirección del eje Y) mientras dibuja.
Alexey Podlasov
¿Hay alguna forma de usar esto para voltear la imagen verticalmente?
Praxiteles
Este método admite muy bien también el procesamiento de imágenes - siempre plantilla
Peter Stajger
3
Para solucionar el problema de calidad, use UIGraphicsBeginImageContextWithOptions (image.size, NO, image.scale); en lugar.
Nick Lockwood
14

He intentado con imageFlippedForRightToLeftLayoutDirection y creando un nuevo UIImage con diferentes orientaciones, pero al menos esta es la única solución que encontré para voltear mi imagen

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

Como pueden ver en mi patio de recreo funcionó !! :) ingrese la descripción de la imagen aquí

Y, por supuesto, deje finalImage = UIImage (CIImage: rotada3)

abanet
fuente
Lo siento, pero parece que esto ya no funciona, al menos con las fotos tomadas con la cámara ...
Oni_01
12

Como define la orientación de la imagen:

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

Hice algunas mejoras para más circunstancias como manejar 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];
Enrique
fuente
9

aquí está la versión rápida: (Vi esta pregunta en los comentarios)

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

iOS 10+

[myImage imageWithHorizontallyFlippedOrientation];

Rápido 4:

let flippedImage = myImage.withHorizontallyFlippedOrientation()
Roman Solodyashkin
fuente
7

Esta es una implementación sólida para reflejar / voltear un UIImage horizontalmente, y se puede aplicar a la imagen hacia adelante y hacia atrás. Dado que cambia los datos de la imagen subyacente, el dibujo (como una captura de pantalla) también cambiará. Probado para funcionar, sin pérdida de calidad.

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

Puede ser que esto sea de utilidad para algunos:

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

Para Swift 3/4:

imageView.transform = CGAffineTransform(scaleX: -1, y: 1)
Shaked Sayag
fuente
Esto es para un UIImageView, el OP está buscando un UIImage
Shizam
2

Una simple extensión.

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
fuente
Las extensiones son una de las mejores características de Swift. Me sorprende que las respuestas originales anteriores no lo recomienden. Me gusta mucho más esta versión.
DS.
1

Esta es una versión compatible con iOS8 / 9 que funciona:

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
fuente
No creo que esta sea la mejor idea. Esto imageFlippedForRightToLeftLayoutDirection está destinado a utilizarse con direcciones de diseño invertidas, por ejemplo, para países árabes. Por lo tanto, es posible que usar esto no siempre funcione como se desea.
Peter Stajger
1
Sí, tienes razón, en mi caso fue exactamente para soporte RTL. Todos sabemos que el código en SO es para referencia y la gente no solo copia / pega sin entenderlo primero, ¿verdad?
capikaw
1

Probado en Swift 3 y superior

Aquí está la solución simple para lograr este problema con extensiones. Lo probé y funcionó. Puede reflejar en cualquier dirección.

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 de este código

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

Así sucesivamente, puede utilizar otras funciones.

Rehan Ali
fuente
0

Aquí está una de las respuestas anteriores modificadas y en Swift 3 que encontré particularmente útil cuando tiene un botón que necesita mover la imagen hacia adelante y hacia atrá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)

    }

Utilizar:

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

La respuesta de aroth en SWIFT 3:

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

Rápido 4

yourImage.transform = CGAffineTransform(scaleX: -1, y: 1)
Faris
fuente
3
Las respuestas de solo código generalmente se consideran de baja calidad. Además de su código, explique cómo / por qué funciona, soluciona el problema o responde la pregunta.
chharvey
1
Además, esto no funciona para la pregunta de OP, ya que está pidiendo voltear la imagen. El código aquí cambia la vista de la imagen. Ambos son muy diferentes en términos de dónde se pueden usar. por ejemplo, un botón toma una imagen, no una vista de imagen.
DS.
Además, acabas de copiar mi respuesta y escribiste rápido 4
Shaked Sayag
0

Para desenvolverlo, haga lo siguiente:

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

puedes rotar la imagen como quieras 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
fuente
0

Swift 5 - Xcode 11.5

La mejor solución para rotaciones horizontales: vea este video:

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

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

}

Puede usar cualquier interfaz de usuario (botón o etiqueta o vista de vista o imagen) en esta animación.

OliaPh
fuente
1
No se recomienda publicar un enlace como respuesta. El enlace podría dejar de ser válido algún día. Si cree que el método es útil, ¿podría publicarlo aquí?
Christopher