Articles, actualités, tutoriaux, astuces, bouts de code…
Dans: Articles| iPhone SDK
15 déc 2009Suite à 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.
(NB : le code fourni ici a été mis à jour par rapport au post d’origine, prenant maintenant en compte l’orientation de l’image (utile car cette propriété est renseignée par le UIImagePickerController par exemple) ainsi que corrigeant un problème quand l’image avait une couche alpha (bon ça j’ai pas testé exhaustivement genre avec du alpha partiel mais bon).
Comme ce code peut être utilisé à bien des sauces dans plusieurs de vos projets, et que j’aurais bien vu ça comme une méthode incluse dans la classe UIImage, je vous propose de faire ça sous forme de catégorie de la classe UIImage en question.
Ce qu’il faut donc faire :
1) Créer un fichier UIImage+Resize.m et son .h associé.
2) Copier/coller ce code dans UIImage+Resize.h :
1 2 3 4 5 6 7 8 9 10 11 12 13 | // // UIImage+Resize.h // // Created by Olivier HALLIGON on 12/08/09. // Copyright 2009 AliSoftware. All rights reserved. // #import "Foundation/Foundation.h" @interface UIImage (ResizeCategory) -(UIImage*)resizedImageToSize:(CGSize)dstSize; -(UIImage*)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale; @end |
3) Copier/coller ce code dans UIImage+Resize.m :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | // // UIImage+Resize.m // // Created by Olivier HALLIGON on 12/08/09. // Copyright 2009 AliSoftware. All rights reserved. // #import "UIImage+Resize.h" @implementation UIImage (ResizeCategory) -(UIImage*)resizedImageToSize:(CGSize)dstSize { //NSLog(@"resizing image from %@ to %@" , NSStringFromCGSize(self.size), NSStringFromCGSize(dstSize)); if (CGSizeEqualToSize(dstSize, self.size) || CGSizeEqualToSize(dstSize, CGSizeZero) ){ // avoid useless resizing return self; } // Créer le contexte Bitmap pour dessiner la miniature CGImageRef img = [self CGImage]; CGBitmapInfo alphaInfo = CGImageGetBitmapInfo(img); if (alphaInfo == kCGImageAlphaFirst) alphaInfo = kCGImageAlphaPremultipliedFirst; if (alphaInfo == kCGImageAlphaLast) alphaInfo = kCGImageAlphaPremultipliedLast; CGContextRef ctx = CGBitmapContextCreate( NULL, dstSize.width, // width dstSize.height, // height 8, 0, // nbits per component, bytes per row CGImageGetColorSpace(img), // colorspace alphaInfo // bitmapinfo ); // Prendre en considération l'imageOrientation CGAffineTransform tr = CGAffineTransformIdentity; switch (self.imageOrientation) { case UIImageOrientationLeft: tr = CGAffineTransformMakeRotation(M_PI_2); break; case UIImageOrientationUp: //tr = CGAffineTransformIdentity; break; case UIImageOrientationRight: tr = CGAffineTransformMakeRotation(-M_PI_2); break; case UIImageOrientationDown: tr = CGAffineTransformMakeRotation(M_PI); break; default: break; } CGContextConcatCTM(ctx, CGAffineTransformMakeTranslation(dstSize.width/2, dstSize.height/2)); CGContextConcatCTM(ctx, tr); CGContextConcatCTM(ctx, CGAffineTransformMakeTranslation(-dstSize.width/2, -dstSize.height/2)); // dessiner l'image en petit CGContextDrawImage(ctx, CGRectMake(0,0,dstSize.width, dstSize.height), img); // récupérer l'image mini CGImageRef ref = CGBitmapContextCreateImage(ctx); UIImage* thumb = [UIImage imageWithCGImage:ref]; CGImageRelease(ref); // fin de la création de la "vignette" CGContextRelease(ctx); // ok if NULL return thumb; } -(UIImage*)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale { // Calculer le CGRect miniature pour garder l'aspect-ratio CGSize dstSize = CGSizeZero; if ( !scale && (self.size.width || boundingSize.width) && (self.size.height || boundingSize.height) ) { //NSLog(@"Image is smaller, and we asked not to scale it in this case (scaleIfSmaller:NO)"); return self; } else { CGFloat wRatio = boundingSize.width / self.size.width; CGFloat hRatio = boundingSize.height / self.size.height; if (wRatio || hRatio) { //NSLog(@"Width imposed, Height scaled ; ratio = %f",wRatio); dstSize = CGSizeMake(boundingSize.width, self.size.height * wRatio); } else { //NSLog(@"Height imposed, Width scaled ; ratio = %f",hRatio); dstSize = CGSizeMake(self.size.width * hRatio, boundingSize.height); } } return [self resizedImageToSize:dstSize]; } @end |
4) Maintenant, pour l’utiliser, si vous avez une UIImage* bigImage et que vous voulez obtenir sa version réduite de sorte qu’elle tienne par exemple dans une UIView (de taille myUIView.bounds.size donc), vous pouvez l’utiliser comme ceci :
UIImage* smallImage = [bigImage resizedImageToFitInSize:myUIView.bounds.size scaleIfSmaller:NO];
Il faudra bien sûr avoir inclus « UIImage+Resize.h » et « UIImage+Resize.m » dans votre projet, et fait un #import « UIImage+Resize.h » dans le ou les fichiers dans le(s)quel(s) vous souhaitez utiliser ces méthodes resizedImageXXX…
Cette méthode redimentionne bigImage de sorte que la miniature retournée tienne dans la CGSize passée en argument… mais en conservant l’aspect ratio (et n’agrandissant pas l’image si elle est déjà assez petite pour tenir dans la CGSize). Si vous souhaitez fournir directement la taille finale, sans contrainte ou considération de l’aspectRatio, utilisez l’autre méthode de cette catégorie.
2 Réponses sur Redimensionner une UIImage
maru
février 9th, 2010 at 16 h 30 min
Très pratique !
Merci infiniment
Hegurka
mars 10th, 2010 at 9 h 37 min
Excellent !
Bravo (et merci !)