Comment créer un CGBitmapContext qui fonctionne pour l'affichage Retina et ne gaspille pas d'espace pour un affichage régulier?
Est-il vrai que si c'est dans UIKit, y compris drawRect
le format HD de l'écran Retina est géré automatiquement? Donc, est-ce à dire dans drawRect
l'actuel contexte graphique pour une résolution de 1024 x 768 vue est en fait un 2048 x 1536 pixels du Bitmap contexte?
(Mise à jour: si je créer une image en utilisant le contexte actuel dans drawRect
et imprimer sa taille:
CGContextRef context = UIGraphicsGetCurrentContext();
CGImageRef image = CGBitmapContextCreateImage(context);
NSLog(@"width of context %i", (int) CGImageGetWidth(image));
NSLog(@"height of context %i", (int) CGImageGetHeight(image));
puis sur le nouvel iPad, avec la barre d'état désactivé, 2048 et 1536 est imprimé, et l'iPad 2 va montrer 1024 et 768)
Nous en fait profiter du luxe de 1 point = 4 pixels géré automatiquement pour nous.
Cependant, si nous utilisons CGBitmapContextCreate
puis ceux qui vont vraiment être pixels, pas de points? (au moins, si nous fournir une mémoire tampon de données pour l'image, la taille de la mémoire tampon (nombre d'octets) n'est évidemment pas pour une résolution plus élevée, mais pour une résolution standard, et même si nous passons NULL
comme le tampon, de sorte que CGBitmapContextCreate
gère la mémoire tampon pour nous, la taille est probablement le même que si l'on fait passer dans une mémoire tampon de données, et il est juste de résolution standard, pas de la Rétine résolution).
On peut toujours créer de 2048 x 1536 pour l'iPad 1 et l'iPad 2 et le Nouvel iPad, mais il perdra la mémoire et le processeur et le GPU de la puissance, comme il est seulement nécessaire pour le Nouvel iPad.
Donc faire, nous devons utiliser un if () { } else { }
pour créer un bitmap contexte et comment pouvons-nous réellement faire? Et tout notre code CGContextMoveToPoint
doit être ajusté pour l'écran Retina de l'utilisation x * 2
et y * 2
vs non-écran retina de simplement en utilisant x, y
ainsi? Qui peut être assez ennuyeux pour le code. (ou peut-être qu'on peut définir une variable locale scaleFactor
et mis à [[UIScreen mainScreen] scale]
de sorte qu'il est de 1 pour une résolution standard et de 2, si elle est de la rétine, de sorte que notre x
et y
sera toujours x * scaleFactor
y * scaleFactor
au lieu de simplement x
et y
lorsque l'on tire à l'aide de CGContextMoveToPoint
etc.)
Il semble que UIGraphicsBeginImageContextWithOptions
pouvez en créer un de la Rétine automatiquement si l'échelle de 0.0 est passé, mais je ne pense pas qu'il peut être utilisé si j'ai besoin de créer le contexte et le garder (et à l'aide de ivar ou la propriété de UIViewController pour le tenir). Si je n'ai pas le libérer à l'aide de UIGraphicsEndImageContext
alors il reste dans le contexte graphique de la pile, donc il semble que je dois utiliser CGBitmapContextCreate
à la place. (ou avons-nous simplement de la laisser rester au bas de la pile et ne pas s'inquiéter à ce sujet?)
source d'informationauteur
Vous devez vous connecter pour publier un commentaire.
Après avoir fait plusieurs recherches, j'ai trouvé la solution suivante:
Si vous devez utiliser
CGBitmapContextCreate
alors il y a deux étapes qui peuvent faire le contexte, avec une taille et un système de coordonnées adapté à un affichage standard ou d'un écran Retina:L'échantillon est de créer un 768 x 768 point région, et sur Le Nouvel iPad, il sera 1536 x 1536 pixel. Sur l'iPad 2, il est de 768 x 768 pixel.
Un facteur clé est que,
CGContextScaleCTM(context, scaleFactor, scaleFactor);
est utilisé pour ajuster le système de coordonnées, de sorte que tout dessin de Graphiques de Base, tels queCGContextMoveToPoint
etc, automatiquement, peu importe, il est la norme de la résolution ou de la Rétine résolution.Une autre remarque est que
UIGraphicsBeginImageContext(CGSizeMake(300, 300));
permettra de créer un 300 x 300 pixel sur l'affichage de la Rétine, tandis queUIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 300), NO, 0.0);
permettra de créer 600 x 600 pixel sur l'écran Retina. Le0.0
est pour l'appel de méthode à donner automatiquement à la bonne taille standard, l'affichage ou l'affichage de la Rétine.Aussi essayer celui-ci:
Après le début de la nouvelle image contexte, vous pouvez le récupérer en utilisant
UIGraphicsGetCurrentContext
. Alors, si vous voulez accrocher sur elle et de le réutiliser par la suite, juste le conserver comme vous le feriez tout CF objet (et n'oubliez pas de libérer lorsque vous avez terminé avec lui, conformément à l' les règles). Vous devez toujours appelerUIGraphicsEndImageContext
pour pop hors de UIKit de la pile de contexte, mais si vous avez conservé le contexte, le contexte sera en direct sur par la suite et vous devriez être en mesure de continuer à l'utiliser jusqu'à la libération.Plus tard, si vous souhaitez utiliser le contexte nouveau (et n'ont pas sorti d'album pour le moment), on pourrait appeler
UIGraphicsPushContext
qui va pousser le contexte de retour sur la pile de contexte.L'autre façon d'utiliser le contexte serait de supposer que c'est un CGBitmapContext (le UIKit docs appeler une “image-contexte” mais ne dis pas CGBitmapContext par nom) et l'utilisation
CGBitmapContextCreateImage
pour capturer une nouvelle image à partir du contexte après le dessin.La principale différence est que, si vous avez créé le contexte avec
UIGraphicsCreateImageContextWithOptions
UIGraphicsGetImageFromCurrentImageContext
renvoie une UIImage dontscale
doit correspondre à la valeur que vous avez créé le contexte. (Je ne sais pas si cette échelle de valeur est conservée si l'on ouvre le contexte et appuyez de nouveau plus tard.)CGBitmapContextCreateImage
renvoie une CGImage, et CGImage ne sait pixels.L'autre différence est que UIKit Api de dessin, tels que UIBezierPath, le travail sur le contexte actuel en UIKit de la pile de contexte. Donc, si vous ne poussez pas le contexte, vous pouvez uniquement utiliser le Quartz Api pour dessiner dans le contexte.
Je n'ai pas testé tout les ci-dessus, alors vous devriez le tester à fond de vous-même avant de le faire dans le code qui vous permettra d'offrir à des utilisateurs.
il suffit de créer le contexte de mise à l'échelle à 0.0 pour obtenir l'écran principal avec :
pas de troisième étape.