Est-ce que quelqu'un sait pourquoi CGContextDrawImage
dessiner mon image à l'envers? Je charge une image depuis mon application:
UIImage *image = [UIImage imageNamed:@"testImage.png"];
Et puis demander simplement aux graphiques de base de le dessiner dans mon contexte:
CGContextDrawImage(context, CGRectMake(0, 0, 145, 15), image.CGImage);
Il rend au bon endroit et aux bonnes dimensions, mais l'image est à l'envers. Je dois manquer quelque chose de vraiment évident ici?
Même après avoir appliqué tout ce que j'ai mentionné, j'ai encore eu des drames avec les images. En fin de compte, je viens d'utiliser Gimp pour créer une version «verticale inversée» de toutes mes images. Désormais, je n'ai plus besoin d'utiliser de Transforms. Espérons que cela ne causera pas d'autres problèmes sur la piste.
Quartz2d utilise un système de coordonnées différent, où l'origine se trouve dans le coin inférieur gauche. Ainsi, lorsque Quartz dessine le pixel x [5], y [10] d'une image 100 * 100, ce pixel est dessiné dans le coin inférieur gauche au lieu du coin supérieur gauche. Ainsi provoquant l'image «retournée».
Le système de coordonnées x correspond, vous devrez donc inverser les coordonnées y.
Cela signifie que nous avons traduit l'image par 0 unité sur l'axe x et par la hauteur des images sur l'axe y. Cependant, cela seul signifiera que notre image est toujours à l'envers, étant simplement dessinée "image.size.height" ci-dessous où nous souhaitons qu'elle soit dessinée.
Le guide de programmation Quartz2D recommande d'utiliser ScaleCTM et de passer des valeurs négatives pour inverser l'image. Vous pouvez utiliser le code suivant pour ce faire -
Combinez les deux juste avant votre
CGContextDrawImage
appel et vous devriez avoir l'image correctement dessinée.Faites juste attention si vos coordonnées imageRect ne correspondent pas à celles de votre image, car vous pouvez obtenir des résultats inattendus.
Pour reconvertir les coordonnées:
la source
CGContextSaveGState()
etCGContextRestoreGState()
pour enregistrer et restaurer la matrice de transformation?Le meilleur des deux mondes, utilisez UIImage
drawAtPoint:
oudrawInRect:
tout en spécifiant votre contexte personnalisé:Vous évitez également de modifier votre contexte avec
CGContextTranslateCTM
ouCGContextScaleCTM
ce que fait la deuxième réponse.la source
UIGraphicsBeginImageContextWithOptions
au lieu de simplement en lancer un nouveauCGContext
, cela semblait fonctionner.Documents Quartz2D pertinents: https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP40010156-CH14-SW4
la source
Si quelqu'un est intéressé par une solution simple pour dessiner une image dans un rect personnalisé dans un contexte:
L'image sera mise à l'échelle pour remplir le rect.
la source
Je n'en suis pas sûr
UIImage
, mais ce genre de comportement se produit généralement lorsque les coordonnées sont inversées. La plupart des systèmes de coordonnées OS X ont leur origine dans le coin inférieur gauche, comme dans Postscript et PDF. Mais leCGImage
système de coordonnées a son origine dans le coin supérieur gauche.Les solutions possibles peuvent impliquer une
isFlipped
propriété ou unescaleYBy:-1
transformation affine.la source
UIImage
contient unCGImage
comme membre de contenu principal ainsi que des facteurs d'échelle et d'orientation. PuisqueCGImage
ses différentes fonctions sont dérivées d'OSX, il s'attend à un système de coordonnées à l'envers par rapport à l'iPhone. Lorsque vous créez unUIImage
, il utilise par défaut une orientation à l'envers pour compenser (vous pouvez changer cela!). Utilisez le .CGImage
propriété pour accéder auxCGImage
fonctions très puissantes , mais dessiner sur l'écran de l'iPhone, etc. est mieux fait avec lesUIImage
méthodes.la source
Réponse supplémentaire avec code Swift
Les graphiques Quartz 2D utilisent un système de coordonnées avec l'origine en bas à gauche tandis que UIKit sous iOS utilise un système de coordonnées avec l'origine en haut à gauche. Tout fonctionne généralement bien, mais lorsque vous effectuez certaines opérations graphiques, vous devez modifier vous-même le système de coordonnées. La documentation déclare:
Ce phénomène peut être observé dans les deux instances suivantes de vues personnalisées qui dessinent une image dans leurs
drawRect
méthodes.Sur le côté gauche, l'image est à l'envers et sur le côté droit le système de coordonnées a été traduit et mis à l'échelle de sorte que l'origine soit en haut à gauche.
Image à l'envers
Système de coordonnées modifié
la source
Swift 3.0 et 4.0
Aucune modification nécessaire
la source
Nous pouvons résoudre ce problème en utilisant la même fonction:
la source
drawInRect
est certainement la voie à suivre. Voici une autre petite chose qui vous sera utile lors de cette opération. Habituellement, l'image et le rectangle dans lesquels il va aller ne sont pas conformes. Dans ce cas,drawInRect
cela étendra l'image. Voici un moyen rapide et cool de vous assurer que le rapport hauteur / largeur de l'image n'est pas modifié, en inversant la transformation (ce qui sera pour adapter le tout):la source
Solution Swift 3 CoreGraphics
Si vous souhaitez utiliser CG pour quelque raison que ce soit, au lieu de UIImage, cette construction Swift 3 basée sur les réponses précédentes a résolu le problème pour moi:
la source
Cela se produit parce que QuartzCore a le système de coordonnées "en bas à gauche", tandis que UIKit - "en haut à gauche".
Dans le cas où vous pouvez étendre CGContext :
la source
J'utilise ce Swift 5 extension , pure Core Graphics qui gère correctement les origines non nulles dans les rects d'image:
Vous pouvez l'utiliser exactement comme
CGContext
ladraw(: in:)
méthode habituelle :la source
Au cours de mon projet, j'ai sauté de la réponse de Kendall à la réponse de Cliff pour résoudre ce problème pour les images chargées à partir du téléphone lui-même.
Au final, j'ai fini par utiliser à la
CGImageCreateWithPNGDataProvider
place:Cela ne souffre pas des problèmes d'orientation que vous obtiendriez en obtenant le
CGImage
depuis aUIImage
et il peut être utilisé comme contenu d'unCALayer
sans accroc.la source
la source
Réponse Swift 5 basée sur l'excellente réponse de @ ZpaceZombor
Si vous avez une UIImage, utilisez simplement
Si vous avez une CGImage, utilisez ma catégorie ci-dessous
Remarque: contrairement à d'autres réponses, celle-ci prend en compte le fait que le rect que vous voulez dessiner pourrait avoir y! = 0. Les réponses qui ne prennent pas cela en compte sont incorrectes et ne fonctionneront pas dans le cas général.
Utilisez comme ceci:
la source
Vous pouvez également résoudre ce problème en faisant ceci:
la source