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.