Comment redimensionner une image à l'aide de PIL et conserver son format d'image?
-
07-07-2019 - |
Question
Existe-t-il un moyen évident de faire cela qui me manque? J'essaie juste de créer des vignettes.
La solution
Définissez une taille maximale.
Ensuite, calculez un rapport de redimensionnement en prenant min (largeur maximale / largeur, hauteur maximale / hauteur)
.
La taille appropriée est oldsize * ratio
.
Il existe bien sûr aussi une méthode de bibliothèque pour cela: la méthode Image.thumbnail
.
Vous trouverez ci-dessous un exemple (modifié) tiré de la documentation PIL .
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
Autres conseils
Ce script redimensionnera une image (somepic.jpg) à l’aide de PIL (Python Imaging Library) sur une largeur de 300 pixels et une hauteur proportionnelle à la nouvelle largeur. Pour ce faire, il détermine le pourcentage de 300 pixels de la largeur d'origine (img.size [0]), puis multiplie la hauteur d'origine (img.size [1]) par ce pourcentage. Modifier la & largeur; largeur de base " à tout autre nombre pour changer 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('sompic.jpg')
Je vous recommande également d'utiliser la méthode des miniatures de PIL, car elle vous évite tous les problèmes liés au rapport.
Un conseil important, cependant: remplacer
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.
Basé sur @tomvon, j'ai terminé avec les éléments suivants:
Largeur de redimensionnement:
new_width = 680
new_height = new_width * height / width
Hauteur de redimensionnement:
new_height = 680
new_width = new_height * width / height
Alors juste:
img = img.resize((new_width, new_height), Image.ANTIALIAS)
PIL a déjà la possibilité de rogner une image
img = ImageOps.fit(img, size, Image.ANTIALIAS)
from PIL import Image
img = Image.open('/your iamge path/image.jpg') # image extension *.png,*.jpg
new_width = 200
new_height = 300
img = img.resize((new_width, new_height), Image.ANTIALIAS)
img.save('output image name.png') # format may what u want ,*.png,*jpg,*.gif
Si vous essayez de conserver le même rapport d'aspect, ne redimensionnez-vous pas d'un pourcentage de la taille d'origine?
Par exemple, la moitié de la taille d'origine
half = 0.5
out = im.resize( [int(half * s) for s in im.size] )
from PIL import Image
from resizeimage import resizeimage
def resize_file(in_file, out_file, size):
with open(in_file) as fd:
image = resizeimage.resize_thumbnail(Image.open(fd), size)
image.save(out_file)
image.close()
resize_file('foo.tif', 'foo_small.jpg', (256, 256))
J'utilise cette bibliothèque:
pip install python-resize-image
Mon exemple laid.
La fonction récupère un fichier comme suit: "image [0-9a-z]. [extension]", redimensionne-la en 120x120, déplace la section au centre et enregistre dans "ico [0-9a-z]. extension] [extension ] " ;, travaille avec portrait et paysage:
def imageResize(filepath):
from PIL import Image
file_dir=os.path.split(filepath)
img = Image.open(filepath)
if img.size[0] > img.size[1]:
aspect = img.size[1]/120
new_size = (img.size[0]/aspect, 120)
else:
aspect = img.size[0]/120
new_size = (120, img.size[1]/aspect)
img.resize(new_size).save(file_dir[0]+'/ico'+file_dir[1][3:])
img = Image.open(file_dir[0]+'/ico'+file_dir[1][3:])
if img.size[0] > img.size[1]:
new_img = img.crop( (
(((img.size[0])-120)/2),
0,
120+(((img.size[0])-120)/2),
120
) )
else:
new_img = img.crop( (
0,
(((img.size[1])-120)/2),
120,
120+(((img.size[1])-120)/2)
) )
new_img.save(file_dir[0]+'/ico'+file_dir[1][3:])
Une méthode simple pour conserver les rapports contraints et transmettre une largeur / hauteur maximale. Pas la plus jolie mais fait le travail et est facile à comprendre:
def resize(img_path, max_px_size, output_folder):
with Image.open(img_path) as img:
width_0, height_0 = img.size
out_f_name = os.path.split(img_path)[-1]
out_f_path = os.path.join(output_folder, out_f_name)
if max((width_0, height_0)) <= max_px_size:
print('writing {} to disk (no change from original)'.format(out_f_path))
img.save(out_f_path)
return
if width_0 > height_0:
wpercent = max_px_size / float(width_0)
hsize = int(float(height_0) * float(wpercent))
img = img.resize((max_px_size, hsize), Image.ANTIALIAS)
print('writing {} to disk'.format(out_f_path))
img.save(out_f_path)
return
if width_0 < height_0:
hpercent = max_px_size / float(height_0)
wsize = int(float(width_0) * float(hpercent))
img = img.resize((max_px_size, wsize), Image.ANTIALIAS)
print('writing {} to disk'.format(out_f_path))
img.save(out_f_path)
return
Voici un script python qui utilise cette fonction pour exécuter le redimensionnement d'image par lots.
J'essayais de redimensionner certaines images pour une vidéo de diaporama et à cause de cela, je ne voulais pas seulement une dimension maximale, mais une largeur maximale et une hauteur maximale (la taille de l'image vidéo) .
Et il y avait toujours la possibilité d'un portrait vidéo ...
La méthode Image.thumbnail
était prometteuse, mais je ne pouvais pas la faire passer à une image plus petite.
Donc, après ne pas avoir trouvé de moyen évident de le faire ici (ou ailleurs), j'ai écrit cette fonction et je l'ai mise ici pour celles à venir:
from PIL import Image
def get_resized_img(img_path, video_size):
img = Image.open(img_path)
width, height = video_size # these are the MAX dimensions
video_ratio = width / height
img_ratio = img.size[0] / img.size[1]
if video_ratio >= 1: # the video is wide
if img_ratio <= video_ratio: # image is not wide enough
width_new = int(height * img_ratio)
size_new = width_new, height
else: # image is wider than video
height_new = int(width / img_ratio)
size_new = width, height_new
else: # the video is tall
if img_ratio >= video_ratio: # image is not tall enough
height_new = int(width / img_ratio)
size_new = width, height_new
else: # image is taller than video
width_new = int(height * img_ratio)
size_new = width_new, height
return img.resize(size_new, resample=Image.LANCZOS)
Si vous ne voulez pas / n'avez pas besoin d'ouvrir l'image avec Pillow, utilisez ceci:
from PIL import Image
new_img_arr = numpy.array(Image.fromarray(img_arr).resize((new_width, new_height), Image.ANTIALIAS))
J'ai redimensionné l'image de telle manière et cela fonctionne très bien
from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
import os, sys
from PIL import Image
def imageResize(image):
outputIoStream = BytesIO()
imageTemproaryResized = imageTemproary.resize( (1920,1080), Image.ANTIALIAS)
imageTemproaryResized.save(outputIoStream , format='PNG', quality='10')
outputIoStream.seek(0)
uploadedImage = InMemoryUploadedFile(outputIoStream,'ImageField', "%s.jpg" % image.name.split('.')[0], 'image/jpeg', sys.getsizeof(outputIoStream), None)
## For upload local folder
fs = FileSystemStorage()
filename = fs.save(uploadedImage.name, uploadedImage)
Mise à jour de cette question avec un wrapper plus moderne Cette bibliothèque entoure Pillow (une fourchette de PIL) https://pypi.org/project/python-resize-image/
Vous permettant de faire quelque chose comme ceci: -
from PIL import Image
from resizeimage import resizeimage
fd_img = open('test-image.jpeg', 'r')
img = Image.open(fd_img)
img = resizeimage.resize_width(img, 200)
img.save('test-image-width.jpeg', img.format)
fd_img.close()
Plus d’exemples dans le lien ci-dessus.