594 votes

Comment redimensionner une image à l'aide du LIP tout en conservant son rapport hauteur/largeur ?

Y a-t-il un moyen évident de le faire que j'ai manqué ? J'essaie simplement de créer des vignettes.

13 votes

Puisque cette question est assez ancienne mais utile, et que l'oreiller est plutôt préféré, pour un tutoriel basé sur l'oreiller, jetez un œil à ceci : pillow.readthedocs.org/en/latest/handbook/

4 votes

J'ai créé une petite bibliothèque pour le redimensionnement des images, elle peut être d'une quelconque aide : github.com/charlesthk/python-resize-image

0 votes

La dernière sortie de LIP remonte à 2006. Le paquet pillow est le remplacement pour autant que je sache. La dernière version de Pillow date du 2 avril 2020.

597voto

gnud Points 26854

Définissez une taille maximale. Ensuite, calculez un rapport de redimensionnement en prenant min(maxwidth/width, maxheight/height) .

La taille appropriée est oldsize*ratio .

Il existe bien sûr aussi une méthode de bibliothèque pour faire cela : la méthode Image.thumbnail .
Vous trouverez ci-dessous un exemple (édité) tiré de l Documentation LIP .

import os, sys
import Image

size = 128, 128

for infile in sys.argv[1:]:
    outfile = os.path.splitext(infile)[0] + ".thumbnail"
    if infile != outfile:
        try:
            im = Image.open(infile)
            im.thumbnail(size, Image.ANTIALIAS)
            im.save(outfile, "JPEG")
        except IOError:
            print "cannot create thumbnail for '%s'" % infile

5 votes

Comme il est dit, l'exemple était tiré de la documentation du pilote, et cet exemple n'utilise pas (encore) le drapeau antialias. Mais comme c'est probablement ce que la plupart des gens veulent, je l'ai ajouté.

3 votes

PIL fixe la hauteur de la nouvelle image à la taille donnée (128 ici) et calcule la largeur pour conserver le rapport d'aspect. Existe-t-il un moyen de fixer la largeur au lieu de la hauteur ? Je vais peut-être poser cette question séparément.

9 votes

@Eugene : essayez quelque chose comme s= img.size(); ratio = MAXWIDTH/s[0]; newimg = img.resize((s[0]*ratio, s[1]*ratio), Image.ANTIALIAS) ? (c'est pour la division en virgule flottante :)

371voto

tomvon Points 743

Ce script va redimensionner une image (somepic.jpg) à l'aide de PIL (Python Imaging Library) pour obtenir une largeur de 300 pixels et une hauteur proportionnelle à la nouvelle largeur. Pour ce faire, il détermine le pourcentage que représentent 300 pixels par rapport à la largeur d'origine (img.size[0]), puis multiplie la hauteur d'origine (img.size[1]) par ce pourcentage. Remplacez "basewidth" par n'importe quel autre chiffre pour modifier la largeur par défaut de vos images.

from PIL import Image

basewidth = 300
img = Image.open('somepic.jpg')
wpercent = (basewidth/float(img.size[0]))
hsize = int((float(img.size[1])*float(wpercent)))
img = img.resize((basewidth,hsize), Image.ANTIALIAS)
img.save('somepic.jpg')

3 votes

Si vous utilisez ce script dans Zope comme une méthode externe, vous aurez besoin de la ligne "from PIL import Image" pour éviter les conflits d'espace de noms avec "Image" de Zope.

0 votes

Ce code me donne un fichier de sortie de 0 octet. sompic.jpg . Pourquoi cela se produit-il ? J'utilise Python 3.x.

0 votes

- Mise à jour : la même chose se produit dans Python 2.7.

83voto

Franz Points 652

Je recommande également d'utiliser la méthode des vignettes de la LIP, car elle vous évite tous les tracas liés aux rapports.

Un conseil important, cependant : Remplacez

im.thumbnail(size)

avec

im.thumbnail(size,Image.ANTIALIAS)

Par défaut, PIL utilise le filtre Image.NEAREST pour le redimensionnement, ce qui donne de bonnes performances, mais une qualité médiocre.

9 votes

Avec cela, vous ne pouvez que diminuer la taille d'une image. Il n'est pas possible d'augmenter la taille avec Image.thumbnail .

33voto

Chris Cameron Points 3841

Si vous essayez de conserver le même rapport hauteur/largeur, ne devriez-vous pas redimensionner en fonction d'un certain pourcentage de la taille d'origine ?

Par exemple, la moitié de la taille originale

half = 0.5
out = im.resize( [int(half * s) for s in im.size] )

16 votes

Il se peut que les images soient de tailles différentes et que le résultat du redimensionnement doive être de taille uniforme.

0 votes

C'était une solution très simple et élégante pour moi.

2 votes

Très sexy. Cet exemple utilise une compréhension de liste. L'utilisation d'un générateur (enveloppé dans des parenthèses) fonctionne également : out = im.resize( (int(half * s) for s in im.size) )

13voto

Le LIP offre déjà la possibilité de recadrer une image.

img = ImageOps.fit(img, size, Image.ANTIALIAS)

26 votes

Cela ne fait que recadrer l'image, sans maintenir le rapport d'aspect.

5 votes

Cela ne répond en rien à la question.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X