Weiß jemand, warum CGContextDrawImage
ich mein Bild verkehrt herum zeichnen würde? Ich lade ein Bild aus meiner Anwendung ein:
UIImage *image = [UIImage imageNamed:@"testImage.png"];
Und dann einfach die Kerngrafiken bitten, sie in meinen Kontext zu zeichnen:
CGContextDrawImage(context, CGRectMake(0, 0, 145, 15), image.CGImage);
Es wird an der richtigen Stelle und in den richtigen Abmessungen gerendert, aber das Bild steht auf dem Kopf. Mir muss hier etwas wirklich Offensichtliches fehlen?
Selbst nachdem ich alles angewendet habe, was ich erwähnt habe, hatte ich immer noch Dramen mit den Bildern. Am Ende habe ich gerade Gimp verwendet, um eine "gespiegelte vertikale" Version aller meiner Bilder zu erstellen. Jetzt muss ich keine Transformationen mehr verwenden. Hoffentlich wird dies später keine weiteren Probleme verursachen.
Quartz2d verwendet ein anderes Koordinatensystem, bei dem der Ursprung in der unteren linken Ecke liegt. Wenn Quarz also Pixel x [5], y [10] eines 100 * 100-Bildes zeichnet, wird dieses Pixel in der unteren linken Ecke anstatt in der oberen linken Ecke gezeichnet. Dadurch entsteht das "gespiegelte" Bild.
Das x-Koordinatensystem stimmt überein, daher müssen Sie die y-Koordinaten umdrehen.
Dies bedeutet, dass wir das Bild auf der x-Achse um 0 Einheiten und auf der y-Achse um die Bildhöhe verschoben haben. Dies allein bedeutet jedoch, dass unser Bild immer noch auf dem Kopf steht und nur "image.size.height" unten gezeichnet wird, wo wir es zeichnen möchten.
In der Quartz2D-Programmieranleitung wird empfohlen, ScaleCTM zu verwenden und negative Werte zu übergeben, um das Bild umzudrehen. Sie können dazu den folgenden Code verwenden:
Kombinieren Sie die beiden kurz vor Ihrem
CGContextDrawImage
Anruf und Sie sollten das Bild richtig gezeichnet haben.Seien Sie nur vorsichtig, wenn Ihre imageRect-Koordinaten nicht mit denen Ihres Bildes übereinstimmen, da Sie unbeabsichtigte Ergebnisse erzielen können.
So konvertieren Sie die Koordinaten zurück:
quelle
CGContextSaveGState()
undCGContextRestoreGState()
speichern Sie die Transformationsmatrix nicht und stellen sie wieder her?Verwenden Sie UIImage's
drawAtPoint:
oder geben SiedrawInRect:
Ihren benutzerdefinierten Kontext an:Außerdem vermeiden Sie es, Ihren Kontext zu ändern
CGContextTranslateCTM
oderCGContextScaleCTM
was die zweite Antwort tut.quelle
UIGraphicsBeginImageContextWithOptions
ein neues zu verwendenCGContext
, anstatt es nur zu starten , schien es zu funktionieren.Relevante Quartz2D-Dokumente: https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP40010154-CH14-
quelle
Wenn jemand an einer einfachen Lösung zum Zeichnen eines Bildes in einem benutzerdefinierten Rechteck in einem Kontext interessiert ist:
Das Bild wird skaliert, um das Rechteck zu füllen.
quelle
Ich bin mir nicht sicher
UIImage
, aber diese Art von Verhalten tritt normalerweise auf, wenn Koordinaten umgedreht werden. Die meisten OS X-Koordinatensysteme haben ihren Ursprung in der unteren linken Ecke, wie in Postscript und PDF. DasCGImage
Koordinatensystem hat jedoch seinen Ursprung in der oberen linken Ecke.Mögliche Lösungen können eine
isFlipped
Eigenschaft oder einescaleYBy:-1
affine Transformation beinhalten.quelle
UIImage
enthält einCGImage
als Hauptinhaltselement sowie Skalierungs- und Orientierungsfaktoren. DaCGImage
und seine verschiedenen Funktionen von OSX abgeleitet sind, erwartet es ein Koordinatensystem, das im Vergleich zum iPhone auf dem Kopf steht. Wenn Sie ein erstellenUIImage
, wird standardmäßig eine verkehrte Ausrichtung verwendet, um dies zu kompensieren (Sie können dies ändern!). Verwenden Sie die.CGImage
Eigenschaft, um auf die sehr leistungsfähigenCGImage
Funktionen zuzugreifen , aber das Zeichnen auf den iPhone-Bildschirm usw. erfolgt am besten mit denUIImage
Methoden.quelle
Ergänzende Antwort mit Swift-Code
Quarz-2D-Grafiken verwenden ein Koordinatensystem mit dem Ursprung unten links, während UIKit in iOS ein Koordinatensystem mit dem Ursprung oben links verwendet. Normalerweise funktioniert alles einwandfrei, aber bei einigen Grafikoperationen müssen Sie das Koordinatensystem selbst ändern. In der Dokumentation heißt es:
Dieses Phänomen tritt in den folgenden zwei Fällen von benutzerdefinierten Ansichten auf, die in ihren
drawRect
Methoden ein Bild zeichnen .Auf der linken Seite steht das Bild auf dem Kopf und auf der rechten Seite wurde das Koordinatensystem übersetzt und skaliert, sodass der Ursprung oben links liegt.
Umgedrehtes Bild
Modifiziertes Koordinatensystem
quelle
Swift 3.0 & 4.0
Keine Änderung erforderlich
quelle
Wir können dieses Problem mit derselben Funktion lösen:
quelle
drawInRect
ist sicherlich der richtige Weg. Hier ist eine weitere Kleinigkeit, die dabei nützlich sein wird. Normalerweise stimmen das Bild und das Rechteck, in das es gehen soll, nicht überein. In diesem FalldrawInRect
wird das Bild gedehnt. Hier ist eine schnelle und coole Möglichkeit, um sicherzustellen, dass das Seitenverhältnis des Bildes nicht geändert wird, indem Sie die Transformation umkehren (die das Ganze einfügt):quelle
Swift 3 CoreGraphics-Lösung
Wenn Sie CG aus irgendeinem Grund anstelle von UIImage verwenden möchten, hat diese Swift 3-Konstruktion, die auf früheren Antworten basiert, das Problem für mich gelöst:
quelle
Dies geschieht, weil QuartzCore das Koordinatensystem "unten links" und UIKit "oben links" hat.
In dem Fall können Sie CGContext erweitern :
quelle
Ich verwende diese Swift 5 , eine reine Core Graphics- Erweiterung, die Nicht-Null-Ursprünge in Bildbereichen korrekt behandelt:
Sie können es genau wie
CGContext
die reguläredraw(: in:)
Methode verwenden:quelle
Im Verlauf meines Projekts bin ich von Kendalls Antwort zu Cliffs Antwort gesprungen , um dieses Problem für Bilder zu lösen, die vom Telefon selbst geladen werden.
Am Ende habe ich
CGImageCreateWithPNGDataProvider
stattdessen verwendet:Dies leidet nicht unter den Orientierungsproblemen, die Sie durch das Abrufen
CGImage
von a erhalten würden,UIImage
und es kann problemlos als Inhalt von a verwendetCALayer
werden.quelle
quelle
Schnelle 5-Antwort basierend auf der hervorragenden Antwort von @ ZpaceZombor
Wenn Sie ein UIImage haben, verwenden Sie einfach
Wenn Sie ein CGImage haben, verwenden Sie meine Kategorie unten
Hinweis: Im Gegensatz zu einigen anderen Antworten wird bei dieser Antwort berücksichtigt, dass das zu zeichnende Rechteck möglicherweise y! = 0 hat. Die Antworten, die dies nicht berücksichtigen, sind falsch und funktionieren im allgemeinen Fall nicht.
Verwenden Sie wie folgt:
quelle
Sie können dieses Problem auch folgendermaßen lösen:
quelle