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.


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

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.


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

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)


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

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)

8

iOS 10+

[myImage imageWithHorizontallyFlippedOrientation];

Swift 4:

let flippedImage = myImage.withHorizontallyFlippedOrientation()

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

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

5

Dla Swift 3/4:

imageView.transform = CGAffineTransform(scaleX: -1, y: 1)

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)

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;

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.


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)

0

odpowiedź arotha w SWIFT 3:

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

0

Szybki 4

yourImage.transform = CGAffineTransform(scaleX: -1, y: 1)

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)

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
}

}


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


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.