5.21. Mise à l’échelle, retournement et recadrage

Les sous-sections précédentes travaillaient toutes sur les pixels aux positions où ils se trouvaient au départ. La famille des transformations change cela. La mise à l’échelle envoie chaque pixel d’entrée vers une position de sortie différente, possiblement vers plusieurs positions de sortie à la fois (lors d’un agrandissement) ou vers une position partagée avec plusieurs autres pixels d’entrée (lors d’une réduction). Le retournement et la rotation font la même chose au moyen d’une correspondance différente. Le recadrage conserve un sous-ensemble rectangulaire de pixels d’entrée et écarte le reste.

Le module image expose cette famille à travers trois méthodes qui partagent la plupart de leurs arguments et la plupart de leur comportement :

  • copy() – produit une copie de l’image, éventuellement mise à l’échelle, recadrée ou réorientée.

  • crop() – la même opération que copy, mais avec l’idée que l’application va sélectionner un sous-rectangle dans la source.

  • scale() – la même chose encore, avec l’idée que l’application va redimensionner le résultat.

Les trois partagent les mêmes arguments et le même mécanisme de transformation ; la différence réside dans l’endroit où atterrit le résultat par défaut. copy() produit une nouvelle image, tandis que crop() et scale() modifient la source sur place.

5.21.1. Les arguments partagés

Un seul appel combine la combinaison de mise à l’échelle, de recadrage, d’orientation et d’extraction de canal que l’application demande :

x_scale et y_scale mettent à l’échelle l’entrée le long des axes horizontal et vertical indépendamment. Tous deux valent par défaut 1.0 (aucune mise à l’échelle). Des valeurs différentes pour chacun produisent une mise à l’échelle non uniforme – une trame étirée deux fois plus large que haute, par exemple.

roi restreint l’entrée à un rectangle de l’image source, ne faisant passer que ces pixels par le reste de la transformation. C’est la partie « recadrage » de l’opération : passez un roi pour extraire une sous-région.

hint est un champ de bits d’indicateurs qui sélectionne la méthode d’interpolation et tout retournement d’orientation. Plusieurs indicateurs se combinent par OU bit à bit (hint=image.BILINEAR | image.HMIRROR). Les indicateurs se répartissent en deux groupes – la famille interpolation et la famille orientation – qui n’ont rien à voir l’un avec l’autre mais partagent le même champ de bits.

rgb_channel sélectionne un seul canal d’une source RGB565. 0 signifie rouge, 1 signifie vert, 2 signifie bleu ; le résultat est produit sous forme d’image en niveaux de gris contenant uniquement ce canal. Utile pour seuiller sur le seul canal rouge, par exemple.

color_palette et alpha_palette remappent les valeurs des pixels au moyen d’une table de correspondance à la sortie, de la même manière que le font les méthodes de conversion to_rainbow() et to_ironbow().

copy=True et copy_to_fb=True suivent la même convention que toute autre méthode produisant un résultat – sur place par défaut, copy=True alloue un résultat distinct, copy_to_fb=True place le résultat dans le tampon d’image pour l’aperçu de l’IDE.

5.21.2. Interpolation : AREA, BILINEAR, BICUBIC

Lorsque la mise à l’échelle envoie chaque pixel de sortie vers une position qui ne s’aligne sur aucun pixel d’entrée unique, la méthode doit choisir quelle valeur écrire. Trois indicateurs contrôlent comment :

image.BILINEAR interpole entre les quatre pixels d’entrée les plus proches, pondérés par leur distance par rapport à la position de sortie. Le résultat est plus lisse que le plus proche voisin, sans crénelage visible sur les lignes diagonales, mais le calcul supplémentaire coûte environ quatre fois la passe du plus proche voisin. Le bon choix pour la plupart des travaux d’agrandissement et pour tout facteur d’échelle non entier.

image.BICUBIC interpole entre les seize pixels d’entrée les plus proches à l’aide d’une courbe cubique, ce qui produit des résultats encore plus lisses au prix d’un calcul plus important encore. La meilleure qualité pour les applications sensibles au coût qui en ont besoin ; rarement utile au regard du calcul supplémentaire pour des trames en direct que l’IDE ne fera qu’afficher.

image.AREA moyenne chaque pixel d’entrée qui tombe à l’intérieur de l’empreinte du pixel de sortie – le bon algorithme pour la réduction. Le bilinéaire et le bicubique sont des interpolateurs : ils estiment une valeur entre les pixels source, ce dont l’agrandissement a besoin, mais lors d’une réduction chaque pixel de sortie couvre de nombreux pixels source et un interpolateur n’en lit que les quelques plus proches – le détail qu’il ignore revient sous forme de crénelage. image.AREA intègre à la place chaque pixel couvert dans la moyenne.

L’algorithme de mise à l’échelle par défaut sans aucun indicateur est le plus proche voisin, qui est le moins coûteux et la bonne réponse lorsque la source est déjà à la résolution en pixels de la destination.

5.21.3. Orientation : retournements et rotations

Les indicateurs d’orientation sont un petit ensemble de transformations booléennes qui se composent librement entre elles et avec les indicateurs d’interpolation :

  • image.VFLIP retourne l’image verticalement (le haut devient le bas).

  • image.HMIRROR la met en miroir horizontalement (la gauche devient la droite).

  • image.TRANSPOSE échange les axes x et y (les lignes deviennent des colonnes).

La plupart des rotations proviennent de la composition de ces trois opérations. Le module expose également des raccourcis nommés :

  • image.ROTATE_90 (= VFLIP | TRANSPOSE)

  • image.ROTATE_180 (= HMIRROR | VFLIP)

  • image.ROTATE_270 (= HMIRROR | TRANSPOSE)

En code :

img.copy(hint=image.ROTATE_90, copy_to_fb=True)

5.21.4. Gestion du rapport d’aspect

Lorsque le rapport d’aspect de la source ne correspond pas au rectangle dans lequel elle est dessinée, trois indicateurs décident quoi faire de cet écart :

image.SCALE_ASPECT_KEEP préserve le rapport d’aspect de la source et ajoute des bandes noires au résultat – la source est mise à l’échelle jusqu’à ce qu’elle tienne à l’intérieur de la destination, les pixels vides (zéro) remplissant le reste de la destination. Le bon choix lorsque conserver la source sans distorsion importe plus que remplir toute la sortie.

image.SCALE_ASPECT_EXPAND préserve le rapport d’aspect de la source et la recadre – la source est mise à l’échelle jusqu’à ce qu’elle remplisse la destination, les parties qui dépassent la destination étant coupées. Le bon choix lorsque remplir toute la sortie importe plus que voir chaque partie de la source.

image.SCALE_ASPECT_IGNORE ignore le rapport d’aspect et étire la source pour remplir la destination, en acceptant toute distorsion ainsi introduite. Le bon choix lorsque l’application a déjà tenu compte de la distorsion – lorsque les dimensions de la destination ne constituent pas réellement un rectangle de la même scène, par exemple.

La valeur par défaut (aucun indicateur d’aspect défini) est la même que SCALE_ASPECT_IGNORE : étirer pour remplir. Les applications soucieuses du rapport d’aspect en spécifient explicitement l’un des trois.

5.21.5. Quand recourir à laquelle

La plupart des redimensionnements utilisent scale() avec une paire x_scale / y_scale et un indicateur d’interpolation :

img.scale(x_scale=0.5, y_scale=0.5, hint=image.AREA)

La plupart des rotations utilisent le même appel avec hint=image.ROTATE_90 ou similaire.

Le recadrage utilise crop() avec un roi non par défaut :

img.crop(roi=(40, 30, 200, 150))

Lorsque la source doit survivre à l’opération – capturer une trame de référence, prendre une miniature d’une trame sur le point d’être traitée de manière destructive – copy() produit le résultat sous forme de nouvelle image et laisse la source intacte :

thumbnail = img.copy(x_scale=0.25, y_scale=0.25, hint=image.AREA)

Cette valeur par défaut est la vraie différence derrière les trois noms : scale et crop transforment sur place, copy alloue. Les mots-clés de placement du résultat comblent l’écart : copy=True sur scale ou crop alloue le résultat dans un tampon de tas distinct au lieu d’écraser la source, et copy_to_fb=True sur l’une quelconque des trois le place dans le tampon d’image pour l’aperçu de l’IDE.