2016-04-15 16 views
6

Chcę obrócić UIImage w kierunku zgodnym z ruchem wskazówek zegara. Ale mój obecny kod nie wykonuje dokładnej funkcji w pewnym momencie, kiedy się obraca, a jakiś czas w swoim pomijaniu. Chcę, aby mój UIImage ciągle obracał się zgodnie z ruchem wskazówek zegara na moim przycisku akcji. Tu jest mój bieżący kod:Obracanie UIImage w szybkim

imageView.image = imageView.image!.imageRotatedByDegrees(angle, flip: false) 
angle = angle + 90 
if angle > 360{ 
    angle = 0 
} 
+0

trzeba użyć imageView.transform = CGAffineTransformMakeRotation (CGFloat (90) * CGFloat (M_PI)/180,0) – SeanLintern88

+0

chcę obrócić UIImage, a nie UIImageView – Mughees

Odpowiedz

15

ten działa dla mnie:

wor KS dzieła :)

func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage { 
    //Calculate the size of the rotated view's containing box for our drawing space 
    let rotatedViewBox: UIView = UIView(frame: CGRectMake(0, 0, oldImage.size.width, oldImage.size.height)) 
    let t: CGAffineTransform = CGAffineTransformMakeRotation(degrees * CGFloat(M_PI/180)) 
    rotatedViewBox.transform = t 
    let rotatedSize: CGSize = rotatedViewBox.frame.size 
    //Create the bitmap context 
    UIGraphicsBeginImageContext(rotatedSize) 
    let bitmap: CGContextRef = UIGraphicsGetCurrentContext()! 
    //Move the origin to the middle of the image so we will rotate and scale around the center. 
    CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2) 
    //Rotate the image context 
    CGContextRotateCTM(bitmap, (degrees * CGFloat(M_PI/180))) 
    //Now, draw the rotated/scaled image into the context 
    CGContextScaleCTM(bitmap, 1.0, -1.0) 
    CGContextDrawImage(bitmap, CGRectMake(-oldImage.size.width/2, -oldImage.size.height/2, oldImage.size.width, oldImage.size.height), oldImage.CGImage) 
    let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 
    return newImage 
} 

Swift 3:

func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage { 
    //Calculate the size of the rotated view's containing box for our drawing space 
    let rotatedViewBox: UIView = UIView(frame: CGRect(x: 0, y: 0, width: oldImage.size.width, height: oldImage.size.height)) 
    let t: CGAffineTransform = CGAffineTransform(rotationAngle: degrees * CGFloat.pi/180) 
    rotatedViewBox.transform = t 
    let rotatedSize: CGSize = rotatedViewBox.frame.size 
    //Create the bitmap context 
    UIGraphicsBeginImageContext(rotatedSize) 
    let bitmap: CGContext = UIGraphicsGetCurrentContext()! 
    //Move the origin to the middle of the image so we will rotate and scale around the center. 
    bitmap.translateBy(x: rotatedSize.width/2, y: rotatedSize.height/2) 
    //Rotate the image context 
    bitmap.rotate(by: (degrees * CGFloat.pi/180)) 
    //Now, draw the rotated/scaled image into the context 
    bitmap.scaleBy(x: 1.0, y: -1.0) 
    bitmap.draw(oldImage.cgImage!, in: CGRect(x: -oldImage.size.width/2, y: -oldImage.size.height/2, width: oldImage.size.width, height: oldImage.size.height)) 
    let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()! 
    UIGraphicsEndImageContext() 
    return newImage 
} 
+0

świetne rozwiązanie, działa jak bułka z masłem – Dari

+0

traci proporcje ... – quemeful

+0

traci proporcje ^^^^ –

7

Można utworzyć funkcję, tak aby obraz obracać w kierunku ruchu wskazówek zegara zawsze:

override func viewDidLoad() { 
     super.viewDidLoad() 

     let kRotationAnimationKey = "com.myapplication.rotationanimationkey" 

     func rotateView(view: UIView, duration: Double = 1) { 
      if view.layer.animationForKey(kRotationAnimationKey) == nil { 
       let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation") 

       rotationAnimation.fromValue = 0.0 
       rotationAnimation.toValue = Float(M_PI * 2.0) 
       rotationAnimation.duration = duration 
       rotationAnimation.repeatCount = Float.infinity 

       view.layer.addAnimation(rotationAnimation, forKey: kRotationAnimationKey) 
      } 
     } 
     rotateView(self.imageView) 
} 

Wynik jest:

enter image description here

+3

Jesteś obrotową UIView nie UIImage, to czyni wielkie różnica, jeśli pracujesz z aplikacją fotograficzną i musisz zapisać wynik. –

3

Dla tych, którzy potrzebują kod z @Mughees w Swift 3:

func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage { 
    //Calculate the size of the rotated view's containing box for our drawing space 
    let rotatedViewBox: UIView = UIView(frame: CGRect(x: 0, y: 0, width: oldImage.size.width, height: oldImage.size.height)) 
    let t: CGAffineTransform = CGAffineTransform(rotationAngle: degrees * CGFloat(M_PI/180)) 
    rotatedViewBox.transform = t 
    let rotatedSize: CGSize = rotatedViewBox.frame.size 
    //Create the bitmap context 
    UIGraphicsBeginImageContext(rotatedSize) 
    let bitmap: CGContext = UIGraphicsGetCurrentContext()! 
    //Move the origin to the middle of the image so we will rotate and scale around the center. 
    bitmap.translateBy(x: rotatedSize.width/2, y: rotatedSize.height/2) 
    //Rotate the image context 
    bitmap.rotate(by: (degrees * CGFloat(M_PI/180))) 
    //Now, draw the rotated/scaled image into the context 
    bitmap.scaleBy(x: 1.0, y: -1.0) 
    bitmap.draw(oldImage.cgImage!, in: CGRect(x: -oldImage.size.width/2, y: -oldImage.size.height/2, width: oldImage.size.width, height: oldImage.size.height)) 
    let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()! 
    UIGraphicsEndImageContext() 
    return newImage 
} 
+1

ten kod obraca obraz dobrze, ale proporcje są teraz odwrócone ... wysokość starego obrazu jest teraz szerokość i na odwrót. Czy ktoś wie, jak to naprawić? Myślę, że to dlatego, że rozmiar rotatedSize jest niepoprawny, ale kiedy próbuję to odwrócić, nowy obraz jest po prostu mniejszy. –

7

@Jason Chitla, nie mogę jeszcze komentarza, więc wysyłam to jako nową odpowiedź. Powyższe rozwiązanie z @ Albert działa, ale tylko w przypadku obrazów kwadratowych. Problem polega na tym, że nadal używa oryginalnego rozmiaru, więc jeśli obrócisz o 90 stopni, aspekt jest nieprawidłowy.

Co działa dla mnie jest, aby korzystać z nowej rotatedSize, tak:

func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage { 
    //Calculate the size of the rotated view's containing box for our drawing space 
    let rotatedViewBox: UIView = UIView(frame: CGRect(x: 0, y: 0, width: oldImage.size.width, height: oldImage.size.height)) 
    let t: CGAffineTransform = CGAffineTransform(rotationAngle: degrees * CGFloat(M_PI/180)) 
    rotatedViewBox.transform = t 
    let rotatedSize: CGSize = rotatedViewBox.frame.size 
    //Create the bitmap context 
    UIGraphicsBeginImageContext(rotatedSize) 
    let bitmap: CGContext = UIGraphicsGetCurrentContext()! 
    //Move the origin to the middle of the image so we will rotate and scale around the center. 
    bitmap.translateBy(x: rotatedSize.width/2, y: rotatedSize.height/2) 
    //Rotate the image context 
    bitmap.rotate(by: (degrees * CGFloat(M_PI/180))) 
    //Now, draw the rotated/scaled image into the context 
    bitmap.scaleBy(x: 1.0, y: -1.0) 
    bitmap.draw(self.cgImage!, in: CGRect(x: -rotatedSize.width/2, y: -rotatedSize.height/2, width: rotatedSize.width, height: rotatedSize.height)) 
    let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()! 
    UIGraphicsEndImageContext() 
    return newImage 
} 
9
extension UIImage { 
    public func imageRotatedByDegrees(degrees: CGFloat) -> UIImage { 
     //Calculate the size of the rotated view's containing box for our drawing space 
     let rotatedViewBox: UIView = UIView(frame: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)) 
     let t: CGAffineTransform = CGAffineTransform(rotationAngle: degrees * CGFloat.pi/180) 
     rotatedViewBox.transform = t 
     let rotatedSize: CGSize = rotatedViewBox.frame.size 
     //Create the bitmap context 
     UIGraphicsBeginImageContext(rotatedSize) 
     let bitmap: CGContext = UIGraphicsGetCurrentContext()! 
     //Move the origin to the middle of the image so we will rotate and scale around the center. 
     bitmap.translateBy(x: rotatedSize.width/2, y: rotatedSize.height/2) 
     //Rotate the image context 
     bitmap.rotate(by: (degrees * CGFloat.pi/180)) 
     //Now, draw the rotated/scaled image into the context 
     bitmap.scaleBy(x: 1.0, y: -1.0) 
     bitmap.draw(self.cgImage!, in: CGRect(x: -self.size.width/2, y: -self.size.height/2, width: self.size.width, height: self.size.height)) 
     let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()! 
     UIGraphicsEndImageContext() 
     return newImage 
    } 


    public func fixedOrientation() -> UIImage { 
     if imageOrientation == UIImageOrientation.up { 
      return self 
     } 

     var transform: CGAffineTransform = CGAffineTransform.identity 

     switch imageOrientation { 
     case UIImageOrientation.down, UIImageOrientation.downMirrored: 
      transform = transform.translatedBy(x: size.width, y: size.height) 
      transform = transform.rotated(by: CGFloat.pi) 
      break 
     case UIImageOrientation.left, UIImageOrientation.leftMirrored: 
      transform = transform.translatedBy(x: size.width, y: 0) 
      transform = transform.rotated(by: CGFloat.pi/2) 
      break 
     case UIImageOrientation.right, UIImageOrientation.rightMirrored: 
      transform = transform.translatedBy(x: 0, y: size.height) 
      transform = transform.rotated(by: -CGFloat.pi/2) 
      break 
     case UIImageOrientation.up, UIImageOrientation.upMirrored: 
      break 
     } 

     switch imageOrientation { 
     case UIImageOrientation.upMirrored, UIImageOrientation.downMirrored: 
      transform.translatedBy(x: size.width, y: 0) 
      transform.scaledBy(x: -1, y: 1) 
      break 
     case UIImageOrientation.leftMirrored, UIImageOrientation.rightMirrored: 
      transform.translatedBy(x: size.height, y: 0) 
      transform.scaledBy(x: -1, y: 1) 
     case UIImageOrientation.up, UIImageOrientation.down, UIImageOrientation.left, UIImageOrientation.right: 
      break 
     } 

     let ctx: CGContext = CGContext(data: nil, 
             width: Int(size.width), 
             height: Int(size.height), 
             bitsPerComponent: self.cgImage!.bitsPerComponent, 
             bytesPerRow: 0, 
             space: self.cgImage!.colorSpace!, 
             bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)! 

     ctx.concatenate(transform) 

     switch imageOrientation { 
     case UIImageOrientation.left, UIImageOrientation.leftMirrored, UIImageOrientation.right, UIImageOrientation.rightMirrored: 
      ctx.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: size.height, height: size.width)) 
     default: 
      ctx.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) 
      break 
     } 

     let cgImage: CGImage = ctx.makeImage()! 

     return UIImage(cgImage: cgImage) 
    } 
} 

@Jason, należy ustalić orientację obrazu przed obrotem.

let image = oldimage.fixedOrientation().imageRotatedByDegrees(90.0) 
+0

niesamowite! tylko rozwiązanie, które działa po wyjęciu z pudełka! dzięki! :) – datayeah

+0

Świetne rozwiązanie. Dziękuję Ci bardzo. Próbowałem wiele rozwiązań na SO, ale jest to jedyny, który naprawdę działa. – Timo