จะพลิก UIImage ในแนวนอนได้อย่างไร?


111

วิธีการพลิกUIImageแนวนอนผมพบว่าUIImageOrientationUpMirroredมูลค่าการแจงนับในการอ้างอิงระดับวิธีการที่จะทำให้การใช้คุณสมบัตินี้เพื่อพลิกUIImageUIImage


เพื่อเพิ่มคำตอบที่ดีของ aroth Apple อธิบายการวางแนวภาพประเภทอื่น ๆ ได้เป็นอย่างดีที่ลิงค์นี้
coco

เนื่องจากการยอมรับไม่ได้ผลสำหรับฉันฉันจึงพบหมวดหมู่นี้ ใช้งานได้เหมือนมีเสน่ห์
dwbrito

คำตอบ:


238

วัตถุประสงค์ -C

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

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

รวดเร็ว

let flippedImage = myImage.withHorizontallyFlippedOrientation()

14
มีปัญหาสองประการกับคำตอบนี้ - สเกลไม่ใช่ 1.0 ที่ภาพที่สามารถใช้เรติน่าได้และด้วยเหตุผลบางประการที่ใช้UIImageOrientationUpงานได้ในขณะที่UIImageOrientationUpMirroredไม่ได้พลิกมัน สิ่งนี้ได้ผล -image = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationUp]
Kof

1
@Kof ตามที่ฉันสังเกตเห็นพารามิเตอร์การวางแนวที่คุณส่งผ่านถูกใช้เพื่อกำหนดว่า 'การวางแนวของ sourceImage เป็นอย่างไร' ซึ่งตรงข้ามกับ 'ให้ภาพนี้กับฉันด้วยการวางแนวเฉพาะนี้' ดังนั้นคุณสามารถตรวจสอบพารามิเตอร์ sourceImage.imageOrientation และส่งไปในทิศทางที่แตกต่างกันเพื่อหลอกให้เมธอดให้สิ่งที่คุณต้องการ
Ege Akpinar

6
จะดีกว่าถ้าใช้sourceImage.scaleสำหรับเครื่องชั่ง
Sam Soffes

วิธีทำใน Swift [UIImage imageWithCGImage ... ] ไม่มีให้ใช้ที่นั่น
Lim Thye Chean

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

2
ขอบคุณสำหรับการแบ่งปันสิ่งนี้ ฉันไม่มีโชคกับ "คำตอบ" ของปริศนานี้ที่เกี่ยวข้องกับโพสต์นี้ แต่คำตอบของคุณใช้งานได้ดีและเป็นรหัสเพียง 1 บรรทัด
Adrian

ใช้งานได้ดี! iOS 9+ ตอนนี้ยังมี flipsForRightToLeftLayoutDirection ด้วย แต่ยังใช้ไม่ได้กับแอพ iOS 8+

3
หากคุณต้องการรีเซ็ตการพลิกให้ใช้yourImageView.transform = CGAffineTransformIdentity
chanil

สังเกตวิธีนี้ 'transforms' บน 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) ขณะวาด
Alexey Podlasov

มีวิธีใช้วิธีนี้เพื่อพลิกภาพในแนวตั้งหรือไม่?
Praxiteles

วิธีนี้รองรับการเรนเดอร์ภาพได้เป็นอย่างดี - เทมเพลตเสมอ
Peter Stajger

3
ในการแก้ไขปัญหาคุณภาพให้ใช้ UIGraphicsBeginImageContextWithOptions (image.size, NO, image.scale); แทน.
Nick Lockwood

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 ฉันแปลกใจที่คำตอบเดิมข้างต้นไม่สามารถแนะนำได้ฉันชอบเวอร์ชันนี้มากขึ้น
DS

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

คำตอบของ aroth ในSWIFT 3:

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

0

สวิฟต์ 4

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

3
คำตอบที่ใช้รหัสเท่านั้นโดยทั่วไปถือว่ามีคุณภาพต่ำ นอกเหนือจากรหัสของคุณแล้วให้อธิบายวิธีการทำงานแก้ไขปัญหาหรือตอบคำถาม
chharvey

1
นอกจากนี้ยังใช้ไม่ได้กับคำถาม OP เนื่องจากเขากำลังขอให้พลิกภาพ รหัสที่นี่จะพลิกมุมมองภาพ ทั้งสองอย่างมีความแตกต่างกันมากในแง่ของที่ที่สามารถใช้ เช่นปุ่มถ่ายภาพไม่ใช่มุมมองภาพ
DS.

นอกจากนี้คุณเพิ่งคัดลอกคำตอบของฉันและเขียนอย่างรวดเร็ว 4
Shaked Sayag

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

}

คุณสามารถใช้ UI (ปุ่มหรือป้ายกำกับหรือ uiview หรือรูปภาพ) ในภาพเคลื่อนไหวนี้ได้


1
ไม่แนะนำให้โพสต์ลิงค์เป็นคำตอบ ลิงก์อาจไม่ถูกต้องในบางวัน หากคุณเชื่อว่าวิธีนี้มีประโยชน์โปรดโพสต์ที่นี่ได้ไหม
Christopher
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.