Redimensionner une UIImage

Dans: Articles| iPhone SDK

par AliGator

15 déc 2009

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.

(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

Avatar

maru

février 9th, 2010 at 16 h 30 min

Très pratique !
Merci infiniment :)

Avatar

Hegurka

mars 10th, 2010 at 9 h 37 min

Excellent !
Bravo (et merci !)

Formulaire