Jak obrócić UIImage w poziomie?

111

Jak odwrócić UIImagepoziomo, znalazłem UIImageOrientationUpMirroredwartość wyliczenia w UIImageodwołaniu do klasy, jak wykorzystać tę właściwość do odwrócenia UIImage.

pradeepa
źródło
Aby dodać do dobrej odpowiedzi arotha, Apple bardzo dobrze wyjaśnia inne typy orientacji obrazu pod tym linkiem
coco
Ponieważ zaakceptowany nie działał dla mnie, znalazłem tę kategorię . Działa jak marzenie.
dwbrito

Odpowiedzi:

238

Cel C

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

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

Szybki

let flippedImage = myImage.withHorizontallyFlippedOrientation()
aroth
źródło
14
Z tą odpowiedzią wiążą się dwa problemy - skala nie jest równa 1,0 na obrazach zgodnych z siatkówką iz jakiegoś powodu UIImageOrientationUpdziałała, UIImageOrientationUpMirroredale jej nie odwróciła . To zadziałało -image = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationUp]
Kof
1
@Kof, jak zauważyłem, parametr orientacji, który podajesz, służy do określenia `` jaka jest już orientacja sourceImage '' w przeciwieństwie do `` daj mi ten obraz z tą konkretną orientacją ''. Dlatego możesz sprawdzić parametr sourceImage.imageOrientation i przekazać w innej orientacji, aby oszukać metodę, aby dała ci to, czego chcesz
Ege Akpinar
6
Lepiej byłoby użyć sourceImage.scaleskali.
Sam Soffes
Jak to zrobić w Swift? [UIImage imageWithCGImage ...] nie jest tam dostępne.
Lim Thye Chean
3
Wydaje się, że to całkowicie się psuje, kiedy próbuję to zrobić [flippedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]. Każdy pomysł, dlaczego?
devios 1
70

Bardzo prostym sposobem osiągnięcia tego jest utworzenie UIImageView zamiast UIImage i wykonanie transformacji w UIImageView.

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

Mam nadzieję że to pomoże.

A. Adam
źródło
2
Skończyło się na tym, że działało to dla mnie znacznie lepiej niż UIImagemanipulacja, która miała efekty uboczne w połączeniu z UIImageRenderingModeAlwaysTemplatetrybem renderowania.
devios1
2
Dziękuję za udostępnienie tego. Nie miałem szczęścia z „odpowiedzią” na tę zagadkę związaną z tym postem, ale Twoja odpowiedź zadziałała fenomenalnie i zawierała tylko 1 linijkę kodu.
Adrian
Działa świetnie! iOS 9+ zawiera teraz również flipsForRightToLeftLayoutDirection, ale nie będzie jeszcze działać w aplikacjach iOS 8+.
3
Jeśli chcesz zresetować przerzucanie, użyjyourImageView.transform = CGAffineTransformIdentity
chanil
Zwróć uwagę, że ta metoda „przekształca” w UIImageView. Nie odwraca rzeczywistego UIImage.
wolne
36

Do zainicjowania tekstury OpenGL przy użyciu często wymagane jest odwrócenie w pionie glTexImage2d(...). Powyższe proponowane sztuczki w rzeczywistości nie modyfikują danych obrazu i nie będą działać w tym przypadku. Oto kod do rzeczywistego odwrócenia danych zainspirowany 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
źródło
1
Jak wygląda ten odwrócony obraz? Wygląda na to, że ponownie rysuje obraz.
Jonathan.
@Jonathan. Myślę, że odwraca się z powodu różnych układów współrzędnych (tj. Kierunku osi Y) podczas rysowania.
Alexey Podlasov
Czy istnieje sposób, aby użyć tego do odwrócenia obrazu w pionie?
Praxiteles
ta metoda ładnie obsługuje również renderowanie obrazu - zawsze szablon
Peter Stajger
3
Aby rozwiązać problem z jakością, użyj UIGraphicsBeginImageContextWithOptions (image.size, NO, image.scale); zamiast.
Nick Lockwood
14

Próbowałem z imageFlippedForRightToLeftLayoutDirection i tworząc nowy UIImage z różnymi orientacjami, ale przynajmniej jest to jedyne rozwiązanie, które znalazłem, aby odwrócić mój obraz

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

Jak widać na moim placu zabaw zadziałało !! :) wprowadź opis obrazu tutaj

I oczywiście niech finalImage = UIImage (CIImage: rotada3)

abanet
źródło
Przepraszamy, ale wygląda na to, że już nie działa, przynajmniej ze zdjęciami zrobionymi aparatem ...
Oni_01
12

Jak definiuje orientacja obrazu:

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

Wprowadziłem kilka ulepszeń dla większej liczby okoliczności, takich jak obsługa UIImage z 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];
Henz
źródło
9

oto szybka wersja: (widziałem to pytanie w komentarzach)

let srcImage = UIImage(named: "imageName")
let flippedImage = UIImage(CGImage: srcImage.CGImage, scale: srcImage.scale, orientation: UIImageOrientation.UpMirrored)
RomanTsopin
źródło
8

iOS 10+

[myImage imageWithHorizontallyFlippedOrientation];

Swift 4:

let flippedImage = myImage.withHorizontallyFlippedOrientation()
Roman Solodyashkin
źródło
7

Jest to solidna implementacja do odbicia lustrzanego / odwrócenia UIImage w poziomie i może być stosowana do obrazu w tę iz powrotem. Ponieważ zmienia podstawowe dane obrazu, rysunek (taki jak zrzut ekranu) również się zmieni. Przetestowane pod kątem działania, bez utraty jakości.

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
źródło
5

Być może przyda się to niektórym:

    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
źródło
5

Dla Swift 3/4:

imageView.transform = CGAffineTransform(scaleX: -1, y: 1)
Shaked Sayag
źródło
To jest dla UIImageView, OP szuka UIImage
Shizam
2

Proste rozszerzenie.

extension UIImage {

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

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

Stosowanie:

let image = #imageLiteral(resourceName: "imageName")
let imageView = UIImageView(image: image.flipped)
Eric Armstrong
źródło
Rozszerzenia to jedna z najlepszych funkcji Swift. Dziwię się, że powyższe odpowiedzi nie zalecały tego. O wiele bardziej mi się podoba ta wersja.
DS.
1

To jest działająca wersja kompatybilna z 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
źródło
Nie sądzę, żeby to był najlepszy pomysł. Ma imageFlippedForRightToLeftLayoutDirection to być używane z odwróconymi kierunkami układu - na przykład dla krajów arabskich. Więc używanie tego może nie zawsze działać zgodnie z oczekiwaniami.
Peter Stajger,
1
Tak, masz rację - w moim przypadku chodziło dokładnie o obsługę RTL. Wszyscy wiemy, że kod w SO służy jako odniesienie, a ludzie tak naprawdę nie kopiują / wklejają bez uprzedniego zrozumienia, prawda?
capikaw
1

Testowane w wersji Swift 3 i nowszych

Oto proste rozwiązanie tego problemu dzięki rozszerzeniom. Testuję to i zadziałało. Możesz odbić w dowolnym kierunku.

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

Wykorzystanie tego kodu

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

Tak dalej, możesz korzystać z innych funkcji.

Rehan Ali
źródło
0

Oto jedna z odpowiedzi powyżej, zmodyfikowana iw Swift 3, która jest szczególnie przydatna, gdy masz przycisk, który musi ciągle obracać obraz w tę iz powrotem.

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)

    }

Posługiwać się:

imageToFlip: UIImage = flipImage(sourceImage: imageToFlip, orientation: imageToFlip.imageOrientation)
Sam Bing
źródło
0

odpowiedź arotha w SWIFT 3:

let sourceImage = UIImage(named: "whatever.png")!
let flippedImage = UIImage(cgImage: sourceImage.cgImage!, scale: sourceImage.scale, orientation: .upMirrored)
maniarali
źródło
0

Szybki 4

yourImage.transform = CGAffineTransform(scaleX: -1, y: 1)
Faris
źródło
3
Odpowiedzi zawierające tylko kod są ogólnie uważane za niskiej jakości. Oprócz kodu wyjaśnij, jak / dlaczego działa, rozwiązuje problem lub odpowiedz na pytanie.
chharvey
1
Również to nie działa w przypadku pytania PO, ponieważ prosi o odwrócenie obrazu. Kod tutaj odwraca widok obrazu. Oba różnią się bardzo pod względem miejsca, w którym można ich użyć. np. przycisk robi zdjęcie, a nie widok obrazu.
DS.
Ponadto, właśnie skopiowałeś moją odpowiedź i napisałeś szybko 4
Shaked Sayag,
0

Ze względu na rozpakowanie wykonaj następujące czynności:

let srcImage = UIImage(named: "myimage")!
let flippedImage = UIImage(cgImage: srcImage.cgImage!, 
                   scale: srcImage.scale, orientation: UIImage.Orientation.upMirrored)
Mike Zriel
źródło
0

możesz obracać obraz, jak chcesz, używając tego

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
źródło
0

Swift 5 - Xcode 11.5

Najlepsze rozwiązanie do obracania w poziomie: obejrzyj ten film:

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

Lub użyj tego kodu:

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

}

W tej animacji możesz użyć dowolnego interfejsu użytkownika (przycisku lub etykiety, widoku lub obrazu).

OliaPh
źródło
1
Nie zaleca się umieszczania linku jako odpowiedzi. Link może pewnego dnia stracić ważność. Jeśli uważasz, że ta metoda jest pomocna, czy możesz opublikować ją tutaj?
Christopher,