En Flash on peut être amené à manipuler des BitmapData, par exemple si on code les vignettes d'une galerie photo (c'est un exemple qui revient souvent ;-)... Voilà une première méthode "brute" qui prend un BitmapData et en retourne un autre au ratio voulu :

public static function reduceBitmapData (bmp:BitmapData, ratio:Number, transparent:Boolean = true):BitmapData {
	var bmpData:BitmapData = new BitmapData(Math.round(bmp.width * ratio), Math.round(bmp.height * ratio), transparent, 0x00FFFFFF);
	var scaleMatrix:Matrix = new Matrix(bmpData.width / bmp.width, 0, 0, bmpData.height / bmp.height, 0, 0);
	bmpData.draw(bmp, scaleMatrix);

	return (bmpData);
}

Et là forcement, on se rend vite compte que le résultat est pas génial. Donc on se dit que le paramètre smoothing de la méthode draw est LA solution, et on utilise un truc du genre :

public static function resizeBitmapData (bmp:BitmapData, ratio:Number, transparent:Boolean = true):BitmapData {
	var bmpData:BitmapData = new BitmapData(Math.round(bmp.width * ratio), Math.round(bmp.height * ratio), transparent, 0x00FFFFFF);
	var scaleMatrix:Matrix = new Matrix(bmpData.width / bmp.width, 0, 0, bmpData.height / bmp.height, 0, 0);
	var colorTransform:ColorTransform = new ColorTransform();
	bmpData.draw(bmp, scaleMatrix, colorTransform, null, null, true);
	
	return (bmpData);
}

Cruelle déception... autant ça donne des résultats corrects quand le ratio est proche de 1, autant les différences avec la méthode précédente sont quasi nulles quand on demande une grosse réduction... Pourquoi ?

Eh bin tout simplement parce que le filtre utilisé par Flash est un filtre bilinéaire, et qu'il est bien connu (c'est marqué dans Wikipedia) que ce filtre, rapide, trouve rapidement ses limites dans les ratio < 50% ou > 200%

Y'a rien à faire alors ?

Bah non...

Nan attendez, revenez, j'aurais pas fait un billet juste pour un pauv' paramètre smoothing. Si le filtre bilineaire est efficace pour des ratio de 50%, on va simplement procéder récursivement de 50% en 50% jusqu'au ratio voulu :

public static function resampleBitmapData (bmp:BitmapData, ratio:Number, transparent:Boolean = true):BitmapData {
	if (ratio >= 1) {
		return (BitmapManager.resizeBitmapData(bmp, ratio, transparent));
	}
	else {
		var bmpData:BitmapData 	= bmp.clone();
		var appliedRatio:Number = 1;
		
		do {
			if (ratio < 0.5 * appliedRatio) {
				bmpData = BitmapManager.resizeBitmapData(bmpData, 0.5, transparent);
				appliedRatio = 0.5 * appliedRatio;
			}
			else {
				bmpData = BitmapManager.resizeBitmapData(bmpData, ratio / appliedRatio, transparent);
				appliedRatio = ratio;
			}
		} while (appliedRatio != ratio);
		
		return (bmpData);
	}
}

Les calculs sont un peu plus longs (on a rien sans rien), mais les résultats sont maintenant dignes d'un PhotoShop !

Pour les flemmards, le fichier regroupant les 3 méthodes est ici

[UPDATE du 2009-08-28] J'ai incorporé les modifs pour que cela fonctionne aussi avec les Bitmap avec transparence.