Как перевернуть UIImage по горизонтали?


111

Как перевернуть по UIImageгоризонтали, я нашел UIImageOrientationUpMirroredзначение перечисления в UIImageссылке на класс, как использовать это свойство для переворота UIImage.


Чтобы добавить к прекрасному ответу Арота, Apple очень хорошо объясняет другие типы ориентации изображений по этой ссылке
coco

Поскольку принятое не работало для меня, я нашла эту категорию . Работает как шарм.
dwbrito

Ответы:


238

Objective-C

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

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

Swift

let flippedImage = myImage.withHorizontallyFlippedOrientation()

14
Есть две проблемы с этим ответом - масштаб не равен 1.0 на изображениях, пригодных для сетчатки, и по какой-то причине UIImageOrientationUpработал, пока UIImageOrientationUpMirroredне переворачивал его. Это сработало -image = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationUp]
Коф

1
@Kof, как я заметил, параметр ориентации, который вы передаете, используется для определения того, «какая ориентация исходного изображения уже является», а не для того, чтобы «дать мне это изображение с этой конкретной ориентацией». Следовательно, вы можете проверить параметр sourceImage.imageOrientation и передать его в другой ориентации, чтобы обмануть метод и дать вам то, что вы хотите
Эге Акпинар,

6
Лучше бы использовать sourceImage.scaleмасштаб.
Сэм Софс,

Как это сделать в Swift? [UIImage imageWithCGImage ...] там недоступен.
Лим Тай Чин

3
Кажется, что это полностью ломается, когда я пытаюсь это сделать [flippedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]. Есть идеи, почему?
devios1

70

Очень простой способ добиться этого - создать UIImageView вместо UIImage и выполнить преобразование в UIImageView.

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

Надеюсь это поможет.


2
В итоге это сработало для меня намного лучше, чем UIImageманипуляция, которая, как я обнаружил, имела побочные эффекты в сочетании с UIImageRenderingModeAlwaysTemplateрежимом рендеринга.
devios1 01

2
Спасибо за то, что поделился этим. Мне не повезло с «ответом» на эту загадку, связанную с этим постом, но ваш ответ сработал феноменально хорошо и состоял всего из одной строки кода.
Адриан

Прекрасно работает! iOS 9+ теперь также включает flipsForRightToLeftLayoutDirection, но пока не работает для приложений iOS 8+.

3
Если вы хотите сбросить переворачивание, то используйтеyourImageView.transform = CGAffineTransformIdentity
chanil

Обратите внимание, что этот метод «трансформируется» в UIImageView. Это не переворачивает фактический UIImage.
медленно,

36

Вертикальный переворот часто требуется для инициализации текстуры OpenGL с помощью glTexImage2d(...). Предложенные выше приемы на самом деле не изменяют данные изображения и не будут работать в этом случае. Вот код для фактического переворота данных, вдохновленный 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
Как это перевернуть изображение? Просто похоже, что он снова рисует изображение.
Джонатан.

@Джонатан. Я думаю, что он переворачивается из-за разных систем координат (то есть направления оси Y) во время рисования.
Алексей Подласов

Есть ли способ использовать это, чтобы перевернуть изображение по вертикали?
Praxiteles

этот метод прекрасно поддерживает также рендеринг изображений - всегда шаблон
Питер Штайгер

3
Чтобы устранить проблему с качеством, используйте UIGraphicsBeginImageContextWithOptions (image.size, NO, image.scale); вместо.
Ник Локвуд

14

Я пробовал использовать imageFlippedForRightToLeftLayoutDirection и создавал новый UIImage с разными ориентациями, но, по крайней мере, это единственное решение, которое я нашел для переворота моего изображения.

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

Как видите, на моей детской площадке это сработало !! :) введите описание изображения здесь

И, конечно, пусть finalImage = UIImage (CIImage: rotada3)


Извините, но похоже, что это больше не работает, по крайней мере, со снимками, сделанными камерой ...
Oni_01

12

Ориентация изображения определяет:

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

Я сделал некоторые улучшения для большего количества обстоятельств, таких как обработка UIImage из 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

вот быстрая версия: (я видел этот вопрос в комментариях)

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


7

Это надежная реализация для зеркального отображения / отражения UIImage по горизонтали и может применяться к изображению вперед и назад. Поскольку он изменяет базовые данные изображения, рисунок (например, снимок экрана) также изменится. Проверено на работу, без потери качества.

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

Может быть, это пригодится некоторым:

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


2

Простое расширение.

extension UIImage {

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

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

Использование:

let image = #imageLiteral(resourceName: "imageName")
let imageView = UIImageView(image: image.flipped)

Расширения - одна из лучших особенностей Swift. Я удивлен, что исходные ответы выше не рекомендовали это. Мне эта версия нравится намного больше.
ДС.

1

Это рабочая версия, совместимая с 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;

Не думаю, что это лучшая идея. Это imageFlippedForRightToLeftLayoutDirection предназначено для использования с перевернутыми направлениями макета - например, для арабских стран. Поэтому использование этого может не всегда работать должным образом.
Peter Stajger

1
Да, вы правы - в моем случае это было именно для поддержки RTL. Мы все знаем, что код на SO предназначен для справки, и люди на самом деле не просто копируют / вставляют, не понимая его, верно?
capikaw

1

Протестировано в Swift 3 и выше

Вот простое решение этой проблемы с помощью расширений. Я тестирую, и он работает. Вы можете отзеркаливать в любом направлении.

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

Использование этого кода

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

Итак, вы можете использовать другие функции.


0

Вот один из ответов, измененных выше и в Swift 3, который я нашел особенно полезным, когда у вас есть кнопка, которая должна постоянно переворачивать изображение вперед и назад.

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)

    }

Использование:

imageToFlip: UIImage = flipImage(sourceImage: imageToFlip, orientation: imageToFlip.imageOrientation)

0

Ответ Арота в SWIFT 3:

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

0

Swift 4

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

3
Ответы, содержащие только код, обычно считаются низкокачественными. В дополнение к вашему коду, объясните, как / почему он работает, устраняет проблему или отвечает на вопрос.
chharvey

1
Кроме того, это не работает для вопроса OP, поскольку он просит перевернуть изображение. Код здесь переворачивает представление изображения. Оба очень разные с точки зрения того, где их можно использовать. например, кнопка принимает изображение, а не просмотр изображения.
ДС.

Кроме того, вы просто скопировали мой ответ и написали
Swift

0

После разворачивания выполните следующие действия:

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

0

вы можете повернуть изображение, как хотите, используя это

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

Лучшее решение для поворота по горизонтали: посмотрите это видео:

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

Или используйте этот код:

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

}

В этой анимации можно использовать любой пользовательский интерфейс (кнопку, метку, пользовательский интерфейс или изображение).


1
Не рекомендуется размещать ссылку в качестве ответа. Когда-нибудь ссылка может стать недействительной. Если вы считаете, что метод полезен, не могли бы вы опубликовать его здесь?
Кристофер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.