Schneiden Sie ein aus der Fotobibliothek erhaltenes Bild ordnungsgemäß aus

8

Ich habe den ganzen Tag daran gearbeitet und habe viele Fragen hier auf SO und google angeschaut, aber bis jetzt kann ich nichts richtig finden.

Ich habe ein Foto auf einem iPad mit iOS 5.1.1 gemacht und es mit der Fotos App zugeschnitten. Ich bekomme dann einen Verweis darauf aus der Objektbibliothek und erhalte das Bild mit voller Auflösung, das nicht beschnitten ist.

Ich habe festgestellt, dass die Informationen zum Zuschneiden in der AdjustmentXMP -Schlüssel von metadata auf meinem Objekt ALAssetRepresentation enthalten sind.

Also beschneide ich das Foto mit den XMP-Infos und hier ist was ich bekomme:

Originalfoto (1.936 x 2.592):

Gut zugeschnittenes Foto, wie in der Fotos App (1.420 x 1.938) zu sehen:

Foto mit Code unten abgeschnitten (auch 1,420 x 1,938, aber etwa 200 Pixel zu weit rechts abgeschnitten):

Dies sind die XMP-Daten vom Foto:

%Vor%

Hier ist der Code, mit dem ich das Foto beschneide:

%Vor%

Ich habe das Problem mit mehreren Bildern reproduziert. Wenn ich nur fullScreenImage verwende, wird es perfekt angezeigt, aber ich brauche das Bild in voller Größe.

    
lnafziger 30.12.2012, 06:27
quelle

1 Antwort

11

Das ist eine schwierige Frage! Es gibt offensichtlich keine Dokumentation für diese XMP-Daten, daher müssen wir raten, wie sie zu interpretieren ist. Es gibt eine Reihe von Wahlmöglichkeiten, und wenn man es falsch macht, kann dies zu leicht falschen Ergebnissen führen.

TL; DR: In der Theorie sieht dein Code korrekt aus, aber in der Praxis gibt es das falsche Ergebnis, und es gibt eine ziemlich offensichtliche Anpassung, die wir ausprobieren können.

Orientierung

Bilddateien können zusätzliche Metadaten enthalten, die angeben, ob (und wie) die Rohdaten des Bilds gedreht und / oder umgedreht werden sollen, wenn sie angezeigt werden. UIImage drückt dies mit seiner imageOrientation Eigenschaft und ALAssetRepresentation ist ähnlich .

CGImage s sind jedoch nur Bitmaps, in denen keine Ausrichtung gespeichert ist. -[ALAssetRepresentation fullResolutionImage] gibt dir CGImage in der ursprünglichen Ausrichtung, ohne dass Anpassungen vorgenommen wurden.

In Ihrem Fall lautet die Ausrichtung 3 , also ALAssetOrientationRight oder UIImageOrientationRight . Die Ansichtssoftware (z. B. UIImage ) berücksichtigt diesen Wert, erkennt, dass das Bild um 90 ° nach rechts (im Uhrzeigersinn) ausgerichtet ist, und dreht es dann um 90 ° nach links (gegen den Uhrzeigersinn), bevor es angezeigt wird. Oder, um es anders auszudrücken, das CGImage wird um 90 ° im Uhrzeigersinn von dem Bild gedreht, das Sie auf Ihrem Bildschirm sehen.

(Um dies zu überprüfen, ermitteln Sie die Breite und Höhe von CGImage mit CGImageGetWidth() und CGImageGetHeight() . Sie sollten feststellen, dass CGImage 2592 breit und 1936 hoch ist. Dies ist um 90 ° von ALAssetRepresentation gedreht. who dimensions sollte 1936 wide um 2592 high sein Sie könnten auch eine UIImage aus der CGImage mit der normalen Ausrichtung UIImageOrientationUp erstellen, schreiben Sie die UIImage in eine Datei und sehen Sie, wie sie aussieht.)

Die Werte im XMP-Wörterbuch scheinen relativ zur Ausrichtung von CGImage zu sein. Zum Beispiel ist die Crop-Rect breiter als hoch, die X-Translation ist größer als die Y-Translation, macht Sinn.

Koordinatensystem

Wir müssen auch entscheiden, in welchem ​​Koordinatensystem die XMP-Werte liegen sollen. Am wahrscheinlichsten ist es eines dieser beiden:

  • "Kartesisch" : Der Ursprung befindet sich in der unteren linken Ecke des Bildes, X nimmt nach rechts zu und Y steigt nach oben . Dieses System wird normalerweise von Core Graphics verwendet.
  • "Gekippt": Der Ursprung befindet sich in der oberen linken Ecke des Bilds, X wird nach rechts und Y nach unten vergrößert. Dies ist das System, das UIKit normalerweise verwendet. Überraschenderweise, im Gegensatz zu den meisten CG, CGImageCreateWithImageInRect() interpretiert das Argument rect auf diese Weise.

Nehmen wir an, dass "umgedreht" korrekt ist, da es im Allgemeinen bequemer ist. Dein Code versucht es ohnehin schon so.

Interpretieren des XMP-Wörterbuchs

Das Wörterbuch enthält eine affine Transformation und ein Crop-Rect. Lassen Sie uns raten, dass es in dieser Reihenfolge interpretiert werden sollte:

  1. Übernehmen Sie die Transformation
  2. Zeichnen Sie das Bild in seinem natürlichen Rect (0,0, w, h)
  3. Heben Sie die Anwendung auf (den Transformationsstapel öffnen)
  4. Zuschneiden auf das Feld rect

Wenn wir das von Hand versuchen, scheinen die Zahlen zu funktionieren. Hier ist ein grobes Diagramm, mit der Crop Rect in durchsichtigem Lila:

Jetzt für etwas Code

Wir müssen diese genauen Schritte in Bezug auf den Aufruf von CG nicht wirklich befolgen, aber wir sollten so tun, als ob wir hätten.

Wir wollen nur CGImageCreateWithImageInRect aufrufen, und es ist ziemlich offensichtlich, wie man das richtige Crop rect (331,161,1938,1420) berechnet. Dein Code scheint das richtig zu machen.

Wenn wir das Bild auf dieses Rechteck zuschneiden, dann erstellen wir ein UIImage (unter Angabe der korrekten Ausrichtung, UIImageOrientationRight ), dann sollten wir die richtigen Ergebnisse erhalten.

Aber die Ergebnisse sind falsch! Was Sie erhalten haben, war als ob wir die Operationen in einem kartesischen Koordinatensystem ausgeführt hätten:

Alternativ verhält es sich so, als ob das Bild in die entgegengesetzte Richtung rotiert wurde, UIImageOrientationLeft , aber wir haben dasselbe Bild rect beibehalten:

Eine Korrektur

Das ist alles sehr merkwürdig, und ich verstehe nicht, was schiefgelaufen ist, obwohl ich es gerne tun würde.

Aber eine Lösung scheint ziemlich einfach zu sein: Einfach den Clip rect drehen. Nach der Berechnung wie oben:

%Vor%

Funktioniert das? (Für diesen Fall und für Bilder mit anderen Orientierungen?)

    
Kurt Revis 30.12.2012, 11:21
quelle