Redimensionner une UIImage
AliGator
Membre, Modérateur
Suite à ce post, je vous propose ici une méthode permettant de redimensionner une UIImage, ou plutôt de créer une version miniature d'une UIImage existante.
C'est par ici :
http://ressources.mediabox.fr/tutoriaux/apple/redimensionner_uiimage
C'est par ici :
http://ressources.mediabox.fr/tutoriaux/apple/redimensionner_uiimage
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Moi j'ai traité que le cas où y'avait une couche alpha et dans ce cas j'ai adapté la constante (car comme il dit dans ses commentaires, dans le Quartz2D Programming Guide y'a la liste des formats de contexte supportés et ils ne sont pas tous disponibles) avec un PremultipliedFirst/PremultipliedLast...
Mais comme je le dis dans mon petit aparté en gris, je suis pas sûr d'avoir traité tous les cas pour l'alpha... Pour l'instant ça m'avait l'air de marcher avec ce que j'ai testé comme cas, mais faut p'tet en rajouter, genre justement le cas de AlphaNone en plus des 2 autres "if" que je fais sur ce alphaInfo...
détail : M_PI/2 peut s'écrire M_PI_2.
Des macros de math.h
• Elles sont assez faciles à retenir le "sur" étant traduit par "underscore".
• consulter /usr/include/math.h pour plus d'infos
M_E e
M_LOG2E log2(e)
M_LOG10E log10(e)
M_LN2 ln(2)
M_LN10 ln(10)
M_PI π
M_PI_2 π/2
M_PI_4 π/4
M_1_PI 1/Ï€
M_2_PI 2/Ï€
M_2_SQRTPI 2/√(π)
M_SQRT2 √(2)
M_SQRT1_2 1/√(2)
(Du coup j'ai corrigé dans le message d'origine qui servira à priori de snippet de référence)
On aurait tendance à faire :
?
Ici , je lis :
Pourquoi ce test si les deux sont équivalents ?
Par ailleurs, il y a quelque chose que je ne pige pas. Pour moi, il y a trois "images"
• L'image initiale
• Le contenu du BitmapContext après CGContextDrawImage(),
• Et celle créée image par CGBitmapContextCreateImage()
Pourquoi faudrait-il faire un lien entre les alphaInfo de ces trois images ?
Comme la doc a l'air de dire que le mode premultiplied est plus rapide à l'utilisation, je serais tenté de ne pas m'occuper du alphaInfo de l'image initial, et de prendre kCGImageAlphaPremultipliedFirst par exemple dans la création du bitmap.
Après si l'image est en kCGImageAlphaNone, peu importe, la fonction CGContextDrawImage() est sensée savoir se débrouiller pour faire le dessin correct dans mon context.
Me gourres-je ?
Par exemple on ne peut pas créer une image RGB 32 bits avec kCGImageAlphaFirst. Si on le fait on a un warning à l'exécution nous indiquant que CGCreateBitmapContext ne supporte pas cette combinaison d'arguments, en cela a pour effet que cette fonction nous retourne un CGContext NULL, donc toute la suite foire.
Voilà pourquoi on est obligé de gérer ce cas de alphaInfo, que je ne gérais pas avant d'être confronté au problème et de réaliser cette limitation.
Comme le disent les commentaires dans l'autre bout de code cité par apocaalypso, ceci est indiqué dans "Supported Pixel Formats" dans le "Quartz 2D Programming Guide". On voit que pour le colorspace RGB, tous les modes utilisant l'alpha sont de l'alpha prémultiplié (PremultipliedFirst ou PremultipledLast) et que les autres modes contenant de l'alpha ne sont pas supportés.
C'est juste que j'étais parti pour garder le colorspace de l'image d'origine parce que là même si seul un oeil de graphiste en général peut voir la différence et qu'en général pour les autres elle ne saute pas aux yeux, toutes les couleurs d'un espace colorimétrique ne peuvent être forcément représenté dans un autre espace colorimétrique, il n'y a pas bijection parfaite (les gammuts des espaces colorimétriques ne sont pas identiques).
Du coup dans la foulée j'ai voulu conserver aussi le alphaInfo au plus proche : dans un premier temps j'avais, tout comme pour le colorspace, gardé le même alphaInfo que l'image d'origine. Quand j'ai vu la limitation, j'ai rajouté le test pour exclure les cas interdits et les remplacer par le plus proche... Mais c'est vrai qu'en en imposant un ça devrait marcher aussi.
Par contre je suis plutôt partant pour garder un contexte sans alpha si l'image d'origine n'a pas de couche alpha (donc n'avoir que 2 cas : kCGAlphaNone et kCGAlphaPremulitpliedLast par exemple, selon si l'image d'origine avait une couche alpha ou non), pour des raisons évidentes tant de potentielle occupation mémoire réduite (nous permettant de réduire à 24 bpp au lieu de 32) que de limitation des calculs à effectuer (puisqu'il est conseillé, d'autant plus sur iPhone même si c'est surtout vrai pour l'affichage et sans doute moins pour les rendus offscreen mais quand même, de se passer de la couche alpha dans la mesure du possible pour ne travailler qu'avec de l'opaque), et pour ainsi limiter les compositions inutiles.
C'est pas impossible que je me sois mélangé les pinceaux là dessus (ou genre introduction de BitmapInfo qui serait nouveau avec le SDK 3.0 un truc du genre ?), faudrait creuser y compris avec des images de formats divers et variés en terme tant de format que d'alpha, de colorspace, de codage...
Le code trouvé par Apoocalypso en est un exemple
Les énumérations ne prennent pas les mêmes valeurs. Comment la fonction s'y retrouve-t-elle ?
[EDIT] on a même le droit à la faute de frappe CGImageBitmapInfo dans la doc :why?: :why?:
Car si on regarde dans le CGImage.h on a [tt]typedef uint32_t CGBitmapInfo; /* Available in MAC OS X 10.4 & later. */[/tt] donc après il peut regarder les valeurs des divers bits via un masquage et faire un mix de ces 2 enums/constantes.
Mais bon j'avoue que ça reste pas clair. Dans la doc de la fonction on voit bien CGBitmapInfo, dans l'utilisation et les exemples du Programming Guide on voit les constantes émanant de l'enum CGAlphaInfo...
Du coup il ferait un masquage (& 0x0F par exemple) pour obtenir le choix en alpha, et un autre sur la partie haute pour le nombre de bits/pixel. Le double rôle de CGBitmapInfo n'étant qu'une maladresse. C'est ce qui est le plus compatible avec la doc, en effet.
Alors, je viens de tester dans le simulateur avec le pickerView, et voilà le message que j'ai :
Donc, quelle est la mauvaise combinaison employée ?
J'ai utilisé ton dernier code (en haut).
J'avoue que votre discussion me dépasse un peu.
Donc avec ceci :
le code fonctionne.
Il faut donc rajouter une variable supplémentaire poue gérer le nombre de bitsPerComponents en fonction de l'alphaInfo ?
Voir ici : http://developer.apple.com/mac/library/qa/qa2001/qa1037.html
Donc bah heu je vois pas trop (et à vrai dire je trouve que c'est un peu prise de tête ce truc là ... ça doit pas être bien sorcier mais penser à tous les cas ça me met un mal de crâne )
if (alphaInfo == kCGImageAlphaNone)
alphaInfo = kCGImageAlphaNoneSkipLast;
ça semble marcher pour tout en restant sur 8 bits... :-)
Bon, merci en tout cas, ta catégorie fait bien le boulot de redimmensionnement avec contraintes. ;-) Beau boulot.
J'ai ce message après la dernière ligne :
Je ne vois absolument pas ce que je pourrais releaser ici que je n'ai pas attribué !
L'appli ne plante pas, mais je n'aime pas ça.
PS : Quel est l'intéret de passer par dataWithData ? et non pas d'attribuer directement le résultat de UIImageJPEGRepresentation à thumbImageData ?
Aucun, je faisais juste un test par désespoir ce matin...
Alors, plus d'erreur si je commente la ligne qui redimmensionne !!
Ce matin, je suis allé voir ta méthode, et tout me paraissait nikel, tu renvoyais une image autoreleasée, du classique quoi.
Mieux :
Pas d'erreur pour la fullImage, mais erreur pour l'image qui doit être réduite... T'as une idée ? (c'est ds le simulateur, et les images font la tailles de l'écran de l'iPhone)
Essaye avec une taille multiple de 4 ou puissance de deux au lieu de 75x75 pour essayer d'isoler le pb ?
Essaye avec des valeurs de compression autre que 0.75 ou 0.60 ?
Bon, je m'y suis remis (au bug).
Alors à force de tests, il s'avère qu'il survient si une des dimensions de l'image demandée est infèrieure à sa taille réelle (donc pour tout ce qui est vignette miniature par exemple).
Ainsi, je fais le test dans le simulateur, si l'image originale fait 320*215, le bug apparaà®t si je demande du 214*214, mais pas à partir de 215*215... !!!
J'ai mis des pointeurs partout dans ton code, et l'erreur apparaà®t à la suite de son exécution MAIS PAS pendant que je le parcourre :
c'est à dire à la deuxième ligne ici...
Du coup j'en ai profité pour mettre à jour l'article sur le blog de PommeDev (qui pointe sur mon github maintenant comme ça l'article pointera tjs sur la dernière version du code).
ChangeLog :
J'ai testé (via le projet d'exemple que je fournis également sur GitHub d'ailleurs) toutes les orientations de l'iPhone lorsque je prend une photo de la camera, et toutes ces orientations sont bien prises en compte. J'ai également test avec des images de ma Library.
Je n'ai pas testé avec des images diverses et variées provenant d'images du filesystem ou créées à partir de NSData ou autre, mais bon.