Skip to content

Générer des vignettes carrées ou circulaires avec Python, Pillow

Vous pouvez créer des vignettes carrées ou circulaires à l’aide de la bibliothèque de traitement d’image de Python Pillow (PIL).

Bien qu’il existe une méthode appelée thumbnail() dans le module Image de Pillow, elle redimensionne simplement l’image pour l’adapter à la taille spécifiée.

Cet article décrit le contenu suivant.

  • Comment faire un carré d’image rectangulaire
    • Recadrer un carré à partir d’une image rectangulaire
    • Ajouter un rembourrage pour faire un rectangle carré
  • Rogner une image carrée en cercle
    • Faire de l’arrière-plan une couleur unie
    • Rendre le fond transparent
  • Exemple de code pour le traitement par lots

Consultez les articles suivants pour l’installation et l’utilisation de base de Pillow (PIL).

Importez Image, ImageDraw et ImageFilter à partir de PIL. ImageDraw et ImageFilter sont utilisés pour dessiner et traiter des cercles. Lors de la création d’une image miniature carrée, elles peuvent être omises.

Pour le traitement par lots, importez os et glob.

Lisez l’image utilisée dans les exemples suivants, et décidez de la largeur (= hauteur) de l’image miniature que vous souhaitez obtenir finalement.

import os
import glob

from PIL import Image, ImageDraw, ImageFilter

im = Image.open('data/src/astronaut_rect.bmp')
thumb_width = 200

image originale - astronaute

Comment faire un carré d’image rectangulaire

Étant donné que le redimensionnement d’une image rectangulaire en carré avec resize() du module Image modifie le rapport d’aspect, utilisez l’une des méthodes suivantes.

  • Recadrer un carré à partir d’une image rectangulaire
  • Ajouter un rembourrage pour faire un rectangle carré

Recadrer un carré à partir d’une image rectangulaire

Rogner une zone d’une image avec crop().

Définissez une fonction pour recadrer la zone centrale de l’image.

def crop_center(pil_img, crop_width, crop_height):
    img_width, img_height = pil_img.size
    return pil_img.crop(((img_width - crop_width) // 2,
                         (img_height - crop_height) // 2,
                         (img_width + crop_width) // 2,
                         (img_height + crop_height) // 2))

Exemple d’utilisation :

im_thumb = crop_center(im, thumb_width, thumb_width)
im_thumb.save('data/dst/astronaut_thumbnail_center_square.jpg', quality=95)

Carré central de la vignette de l'oreiller

Au lieu de recadrer la zone de la taille de la vignette, vous pouvez recadrer le carré de plus grande taille (= carré rectangulaire à côté court) puis le redimensionner.

Définissez une fonction pour recadrer le carré le plus grand. Il utilise une fonction pour recadrer la zone centrale de l’image.

def crop_max_square(pil_img):
    return crop_center(pil_img, min(pil_img.size), min(pil_img.size))

Exemple d’utilisation :

Après avoir transformé l’image rectangulaire en carré, elle est redimensionnée par resize() à la taille de l’image miniature souhaitée.

im_thumb = crop_max_square(im).resize((thumb_width, thumb_width), Image.LANCZOS)
im_thumb.save('data/dst/astronaut_thumbnail_max_square.jpg', quality=95)

Vignette d'oreiller carré max

Ajouter un rembourrage pour faire un rectangle carré

Si vous souhaitez conserver l’intégralité de l’image rectangulaire d’origine, ajoutez un rembourrage en haut, en bas, à gauche ou à droite pour la rendre carrée.

new() peut être utilisé pour générer une image solide et la coller avec paste().

Définissez une fonction qui ajoute un rembourrage pour éventuellement devenir un carré de la taille du côté long du rectangle.

def expand2square(pil_img, background_color):
    width, height = pil_img.size
    if width == height:
        return pil_img
    elif width > height:
        result = Image.new(pil_img.mode, (width, width), background_color)
        result.paste(pil_img, (0, (width - height) // 2))
        return result
    else:
        result = Image.new(pil_img.mode, (height, height), background_color)
        result.paste(pil_img, ((height - width) // 2, 0))
        return result

Exemple d’utilisation :

Après avoir transformé l’image rectangulaire en carré, elle est réduite par resize() à la taille de l’image miniature souhaitée.

im_thumb = expand2square(im, (0, 0, 0)).resize((thumb_width, thumb_width), Image.LANCZOS)
im_thumb.save('data/dst/astronaut_thumbnail_expand.jpg', quality=95)

Vignette de l'oreiller, agrandir le carré

Rogner une image carrée en cercle

Si vous souhaitez générer une image miniature circulaire, vous devez recadrer une image carrée en cercle.

Il existe deux façons :

  • donner à l’arrière-plan une couleur unie (blanc, noir, etc.)
  • rendre le fond transparent (= rendre le png transparent)

Faire de l’arrière-plan une couleur unie

Utilisez composite() pour composer deux images en fonction de l’image du masque.

Dessinez un cercle et utilisez-le comme image de masque. Pour plus de détails sur le dessin, consultez l’article suivant.

Créez une image unicolore de la couleur d’arrière-plan souhaitée avec new() et composez-la avec l’image carrée avec un masque circulaire.

La bordure est lissée en brouillant l’image du masque avec ImageFilter. Étant donné que la zone du cercle s’étend lorsqu’elle est floue, il est nécessaire de dessiner d’abord un cercle plus petit.

Définissez la fonction suivante. Spécifiez la couleur d’arrière-plan background_color, la taille du flou blur_radius et le décalage de décalage. Pas de flou avec blur_radius=0.

def mask_circle_solid(pil_img, background_color, blur_radius, offset=0):
    background = Image.new(pil_img.mode, pil_img.size, background_color)

    offset = blur_radius * 2 + offset
    mask = Image.new("L", pil_img.size, 0)
    draw = ImageDraw.Draw(mask)
    draw.ellipse((offset, offset, pil_img.size[0] - offset, pil_img.size[1] - offset), fill=255)
    mask = mask.filter(ImageFilter.GaussianBlur(blur_radius))

    return Image.composite(pil_img, background, mask)

Exemple d’utilisation :

im_square = crop_max_square(im).resize((thumb_width, thumb_width), Image.LANCZOS)
im_thumb = mask_circle_solid(im_square, (0, 0, 0), 4)
im_thumb.save('data/dst/astronaut_thumbnail_mask_circle_solid.jpg', quality=95)

Vignette d'oreiller cercle solide

Rendre le fond transparent

Utilisez putalpha(), qui ajoute un canal alpha à l’image.

Le flux est le même que lors de l’utilisation d’un fond uni d’une seule couleur.

def mask_circle_transparent(pil_img, blur_radius, offset=0):
    offset = blur_radius * 2 + offset
    mask = Image.new("L", pil_img.size, 0)
    draw = ImageDraw.Draw(mask)
    draw.ellipse((offset, offset, pil_img.size[0] - offset, pil_img.size[1] - offset), fill=255)
    mask = mask.filter(ImageFilter.GaussianBlur(blur_radius))

    result = pil_img.copy()
    result.putalpha(mask)

    return result

Les images transparentes sont enregistrées au format png.

im_square = crop_max_square(im).resize((thumb_width, thumb_width), Image.LANCZOS)
im_thumb = mask_circle_transparent(im_square, 4)
im_thumb.save('data/dst/astronaut_thumbnail_mask_circle_transparent.png')

Cercle de vignette d'oreiller transparent

Exemple de code pour le traitement par lots

Créez des images miniatures collectivement à partir de fichiers image dans n’importe quel répertoire (dossier).

Cela peut être fait de la même manière que le redimensionnement par lots.

Générez des images miniatures des fichiers image dans src_dir et enregistrez-les dans dst_dir.

src_dir = 'data/temp/src'
dst_dir = 'data/temp/dst'

files = glob.glob(os.path.join(src_dir, '*.jpg'))

for f in files:
    im = Image.open(f)
    im_thumb = crop_max_square(im).resize((thumb_width, thumb_width), Image.LANCZOS)
    ftitle, fext = os.path.splitext(os.path.basename(f))
    im_thumb.save(os.path.join(dst_dir, ftitle + '_thumbnail' + fext), quality=95)