2015-02-12 20 views
6

Ich stehe vor einem Bildausrichtungsproblem, wenn ein quadratischer Teil eines Bildes aus einem rechteckigen Originalbild ausgeschnitten wird. Wenn das Bild in der Landschaft ist, ist es in Ordnung. Aber wenn es im Portrait ist, so scheint es, dass die Bildausrichtung nicht erhalten wird, die mit falscher Orientierung in einem Bild führen und schlechter Ernte:Verlieren der Bildausrichtung beim Konvertieren eines Bildes in CGImage

func cropImage(cropRectangleCoordinates: CGRect) { 

     let croppedImage = originalImage 

     let finalCroppedImage : CGImageRef = CGImageCreateWithImageInRect(croppedImage.CGImage, cropRectangleCoordinates) 

     finalImage = UIImage(CGImage: finalCroppedImage)! 


    } 

Ich denke, das Problem mit croppedImage.CGImage ist. Hier wird das Bild in CGImage konvertiert, aber es scheint nicht die Orientierung zu bewahren. Es ist einfach, die Orientierung zu erhalten, indem Sie nur UIImage verwenden, aber um den Ausschnitt zu machen, muss das Bild vorübergehend CGImage sein, und das ist das Problem. Selbst wenn ich das Bild bei der Konvertierung zurück in UIImage neu orientiere, könnte es in der richtigen Ausrichtung sein, aber der Schaden ist bereits beim Beschneiden CGImage.

Dies ist eine schnelle Frage, also antworten Sie bitte schnell, da die Lösung in Objective-C anders sein kann.

Antwort

5

Ich habe eine Lösung gefunden .... die Zeit wird zeigen, ob sie robust genug ist, aber sie scheint in allen Situationen zu funktionieren. Das war ein böser Fehler, den es zu beheben galt.

Also das Problem ist, dass UIImage, in einigen Fällen nur, verlieren ihre Orientierung, wenn sie zu CGImage konvertiert. Es wirkt sich auf Porträts aus, die automatisch in den Querformatmodus versetzt werden. So sind Bilder, die standardmäßig als Landschaft angezeigt werden, nicht betroffen. Aber wo der Fehler bösartig ist, ist, dass es nicht alle Porträtbilder betrifft !! Auch der Bildorientierungswert hilft bei manchen Bildern nicht. Diese problematischen Bilder sind Bilder, die der Benutzer in seiner Bibliothek hat, die er aus E-Mails, Nachrichten oder aus dem Internet erhalten hat, also nicht mit einer Kamera aufgenommen wurde. Diese Bilder haben möglicherweise keine Orientierungsinformationen und somit in manchen Fällen ein Bild im Hochformat .... BLEIBT im Hochformat, wenn sie in CGImage konvertiert werden. Ich steckte wirklich fest, bis ich merkte, dass einige meiner Bilder in meiner Gerätebibliothek von Nachrichten oder E-Mails gespeichert wurden.

Die einzige zuverlässige Methode, um herauszufinden, welches Bild neu ausgerichtet wird, besteht darin, beide Versionen eines gegebenen Bildes zu erstellen: UIImage und CGImage und deren Höhenwert zu vergleichen. Wenn sie gleich sind, wird die CGImage-Version nicht gedreht und Sie könnten damit wie erwartet arbeiten. Wenn die Höhe jedoch unterschiedlich ist, können Sie sicher sein, dass die CGImage-Konvertierung von CGImageCreateWithImageInRect das Bild landscapize. Nur in diesem Fall tausche ich die X/Y-Koordinate des Ursprungs, die ich als Rechteckkoordinate übergebe, und beschneidet diese speziellen Bilder korrekt.

Das war ein langer Post, aber die Hauptidee ist, CGImage Höhe zu UIImage Breite zu vergleichen, und wenn sie unterschiedlich sind, erwarten Sie, dass der Ursprungspunkt invertiert wird.

+2

Aber wenn das Bild quadriert wurde, wird das ein großes Problem für deine Lösung sein: [] – Husam

+0

Setze einfach einen Bildpfad wie folgende Ansicht und lade Bild hoch UIImageView * imgViewTemp = [[UIImageView alloc] init]; [imgViewTemp setImage: [UIImake imageWithCGImage: [rep fullScreenImage]]]; UIImage * compressedImage = [mYGlobal funResizing: imgViewTemp.image]; Ich habe das gleiche Problem, aber reparieren wie oben. – chetu

3

Ihre UIImage call ändern:

finalImage = UIImage(CGImage:finalCroppedImage, scale:originalImage.scale, orientation:originalImage.orientation) 

die ursprüngliche Ausrichtung (und Skala) des Bildes zu erhalten.

+0

ich versucht, aber das Problem ist, bösartiger: finalimage ist bereits abgeschnitten, der Orientierungsverlust tritt zu einem früheren Zeitpunkt auf: croppedImage.CGImage. Was Sie vorschlagen, kann das Bild korrekt drehen, aber nachdem ein Schaden entstanden ist. –

+0

Vielen Dank. Das hilft mir. –

4

Hier ist eine UIImage-Erweiterung, die ich geschrieben habe, nachdem ich einige ältere Code-Teile angeschaut habe, die von anderen geschrieben wurden. Es ist in Swift 3 geschrieben und verwendet die iOS-Orientierungseigenschaft plus CGAffineTransform, um das Bild in der richtigen Ausrichtung neu zu zeichnen.

SWIFT 3:

public extension UIImage { 

    /// Extension to fix orientation of an UIImage without EXIF 
    func fixOrientation() -> UIImage { 

     guard let cgImage = cgImage else { return self } 

     if imageOrientation == .up { return self } 

     var transform = CGAffineTransform.identity 

     switch imageOrientation { 

     case .down, .downMirrored: 
      transform = transform.translatedBy(x: size.width, y: size.height) 
      transform = transform.rotated(by: CGFloat(M_PI)) 

     case .left, .leftMirrored: 
      transform = transform.translatedBy(x: size.width, y: 0) 
      transform = transform.rotated(by: CGFloat(M_PI_2)) 

     case .right, .rightMirrored: 
      transform = transform.translatedBy(x: 0, y: size.height) 
      transform = transform.rotated(by: CGFloat(-M_PI_2)) 

     case .up, .upMirrored: 
      break 
     } 

     switch imageOrientation { 

     case .upMirrored, .downMirrored: 
      transform.translatedBy(x: size.width, y: 0) 
      transform.scaledBy(x: -1, y: 1) 

     case .leftMirrored, .rightMirrored: 
      transform.translatedBy(x: size.height, y: 0) 
      transform.scaledBy(x: -1, y: 1) 

     case .up, .down, .left, .right: 
      break 
     } 

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

      ctx.concatenate(transform) 

      switch imageOrientation { 

      case .left, .leftMirrored, .right, .rightMirrored: 
       ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width)) 

      default: 
       ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) 
      } 

      if let finalImage = ctx.makeImage() { 
       return (UIImage(cgImage: finalImage)) 
      } 
     } 

     // something failed -- return original 
     return self 
    } 
} 
+0

Aufruf dies vor dem Konvertieren zum Aufruf von image.cgImage arbeitete – Cjay

8

SWIFT 3:

convert gedreht CGImage zu UIImage durch diese Methode

UIImage(cgImage:croppedCGImage, scale:originalImage.scale, orientation:originalImage.imageOrientation) 

Quelle @ David Berry antworten

+0

Danke :) Das ist so viel besser als die 100 Zeilen von Code, die ich in anderen Antworten gesehen habe: D –

0

Dies ist die Antwort, Kredit an @awolf (Cropping an UIImage). Griffe Maßstab und Orientierung perfekt. Rufen Sie einfach diese Methode für das Bild auf, das Sie zuschneiden möchten, und geben Sie den Ausschnitt CGRect ein, ohne sich Gedanken über Skalierung oder Ausrichtung zu machen. Fühlen Sie sich frei zu überprüfen, ob cgImage Null ist statt Kraft auszupacken, wie ich hier tat.

extension UIImage { 
    func croppedInRect(rect: CGRect) -> UIImage { 
     func rad(_ degree: Double) -> CGFloat { 
      return CGFloat(degree/180.0 * .pi) 
     } 

     var rectTransform: CGAffineTransform 
     switch imageOrientation { 
     case .left: 
      rectTransform = CGAffineTransform(rotationAngle: rad(90)).translatedBy(x: 0, y: -self.size.height) 
     case .right: 
      rectTransform = CGAffineTransform(rotationAngle: rad(-90)).translatedBy(x: -self.size.width, y: 0) 
     case .down: 
      rectTransform = CGAffineTransform(rotationAngle: rad(-180)).translatedBy(x: -self.size.width, y: -self.size.height) 
     default: 
      rectTransform = .identity 
     } 
     rectTransform = rectTransform.scaledBy(x: self.scale, y: self.scale) 

     let imageRef = self.cgImage!.cropping(to: rect.applying(rectTransform)) 
     let result = UIImage(cgImage: imageRef!, scale: self.scale, orientation: self.imageOrientation) 
     return result 
    } 
} 

Noch ein Hinweis: Wenn Sie mit imageView in einem scrollView eingebettet arbeiten, gibt einen zusätzlichen Schritt ist, haben Sie den Zoomfaktor zu berücksichtigen. Angenommen, Ihre imageView erstreckt sich über den gesamten Inhalt Ansicht des scrollView, und verwenden Sie die Grenzen des scrollView als Zuschneiderahmen kann das zugeschnittene Bild als

let ratio = imageView.image!.size.height/scrollView.contentSize.height 
let origin = CGPoint(x: scrollView.contentOffset.x * ratio, y: scrollView.contentOffset.y * ratio) 
let size = CGSize(width: scrollView.bounds.size.width * ratio, let height: scrollView.bounds.size.height * ratio) 
let cropFrame = CGRect(origin: origin, size: size) 
let croppedImage = imageView.image!.croppedInRect(rect: cropFrame) 
erhalten werden