web-dev-qa-db-fra.com

Redimensionner et organiser automatiquement les images sur une toile

Je veux faire un modèle pour imprimer 9 cartes de 63 x 88 mm sur un papier DIN A4) Je veux charger les images afin qu'elles se redimensionnent elles-mêmes et que je puisse les imprimer directement. Comment puis-je faire cela?

2
Arturo

Ci-dessous un script pour créer un fichier à partir d'un certain nombre d'images. Le script utilise imagemagick.

À propos d'imagemagick

De man imagemagick:
ImageMagick®, est une suite logicielle pour créer, éditer et composer des images bitmap. Il peut lire, convertir et écrire des images dans une variété de formats (environ 100), y compris GIF, JPEG, JPEG- 2000, PNG, PDF, PhotoCD, TIFF et DPX. Utilisez ImageMagick pour traduire, retourner, mettre en miroir, faire pivoter, mettre à l'échelle, cisailler et transformer des images, ajuster les couleurs de l'image, appliquer divers effets spéciaux ou dessiner du texte, des lignes, des polygones, des ellipses et Courbes de Bézier.

Comme Imagemagick est un outil en ligne de commande, il est particulièrement adapté à une utilisation dans des scripts; pour automatiser des travaux comme vous le mentionnez dans votre question par exemple.

Installez Imagemagick

Vous devrez peut-être d'abord installer imagemagick:

Sudo apt-get install imagemagick

Le script

Le script combine et organise un certain nombre d'images en un seul fichier. Ce faisant, il utilise l'espace maximum (en px), défini par vous, mais sans changer les proportions de l'image. Une fois le travail terminé, la sortie est automatiquement ouverte dans Gimp (donc Gimp doit être installé). Si, pour une raison quelconque, le fichier n'apparaît pas dans Gimp, il se trouve dans le dossier de vos images, nommé: out_file.jpg.

enter image description here

Un exemple

Dans l'exemple ci-dessous, la sortie souhaitée est une feuille de trois images (colonnes) x trois images (lignes), tandis que les images doivent être de 1 500 pixels (horizontale). Vous aurez besoin d'une zone de 4500 px (largeur), et en même temps assurez-vous que les trois rangées tiennent dans la zone. Dans la section head du script, vous définissez:

colrows = [3, 3]            # set the number of colums/rows
max_area = [4500, 6500]     # set the area (hxv in px) the script can use

puisque la hauteur est "surdimensionnée" pour nos photos, le script remplira jusqu'à la largeur maximale (4500/3 = 1500px par image)

Le résultat:

enter image description here

Le script suppose:

  • toutes les images sont de la même proportion et orientation (elles peuvent cependant être de tailles différentes)
  • le nombre d'images à l'intérieur du dossier (voir ci-dessus) est égal (ou au moins) aux lignes x colonnes (9 dans votre exemple). S'il y a plus d'images dans le dossier, seul le nombre nécessaire est utilisé.

Options/paramètres

Le script a un certain nombre d'options. Dans la section head du script, vous devez définir:

img_dir = "/path/to/files"      # path to the images
output_extension = ".jpg"       # desired output
colrows = [3, 3]                # columns  / rows of pictures
max_area = [4500, 6500]         # the (max) size of your sheet
border = 10                     # whitespace around the images

Le script

#!/usr/bin/env python3

import os
import subprocess
import shutil

# set the input below
###############################################################################
img_dir = "/path/to/files"      # path to the images
output_extension = ".jpg"       # desired output
colrows = [3, 3]                # columns  / rows of pictures
max_area = [4500, 6500]         # the (max) size of your sheet
border = 10                     # whitespace around the images 
###############################################################################
cd_topics = "cd "+"'"+img_dir+"'; "
# current picture size
images = sorted([item for item in os.listdir(img_dir)])[:colrows[0]*colrows[1]]
for image in images:
    shutil.copyfile(img_dir+"/"+image, img_dir+"/fixed_"+image.replace(" ", "_"))
images = sorted([item for item in os.listdir(img_dir) if item.startswith("fixed_")]) ##             
# a few functions                    
def get_picsize(image):
    command = cd_topics+'identify -format "%wx%h" '+image
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8").strip().split("x")

def resize(img_in, img_out, size, modus=None):
    modus = "^ " if modus == "outsize" else " "    
    newsize = str(size)+"x"+str(size)
    resize_command = cd_topics+"convert "+img_in+" -resize "+newsize+modus+img_out
    subprocess.call(["/bin/bash", "-c", resize_command])

def add_border(img_in, img_out, bd):
    if bd != None and str(bd) != "0":
        addborder_command = cd_topics+"convert "+img_in+" -bordercolor white -border "+bd+"x"+bd+" "+img_out
        subprocess.call(["/bin/bash", "-c", addborder_command])
# make all pictures of equal size
standard_size = get_picsize(images[0])
for pic in images:
    if not get_picsize(pic) == standard_size:
        resize(pic, pic, max(standard_size))   
# calculate resize
picture_orientation = int(standard_size[0])/int(standard_size[1])
area_ratio = float(max_area[0]/max_area[1])
combi_ratio = (colrows[0]*int(standard_size[0]))/(colrows[1]*int(standard_size[1]))
fit_in = area_ratio/combi_ratio
if fit_in > 1:
    newsize = int(max_area[1]/colrows[1])-2*border
    modus = "outsize" if picture_orientation > 1 else None
else:
    newsize = int(max_area[0]/colrows[0])-2*border
    modus = "outsize" if picture_orientation < 1 else None
# resize images
for image in images:
    resize(image, "rs_"+image, newsize, modus)
    add_border("rs_"+image, "rs_"+image, bd=str(border))
# combining into rows
images = sorted([pic for pic in os.listdir(img_dir) if pic.startswith("rs_")])
rows = [images[i:i+colrows[0]] for i in range(len(images)-colrows[0]+1) if i % colrows[0]== 0]
i = 0
while i in range(len(rows)):
    row = rows[i]; images = [im for im in row]
    command = cd_topics+"convert "+" ".join(images)+" +append "+"row_"+str(i+1)+output_extension
    subprocess.call(["/bin/bash", "-c", command])
    i = i+1
# combining rows
images = sorted([pic for pic in os.listdir(img_dir) if pic.startswith("row")])
output_file = "out_file"+output_extension
command = cd_topics+"convert "+(" ").join(images)+" -append "+output_file
subprocess.call(["/bin/bash", "-c", command])
# opening image with Gimp, cleaning up
for image in sum([[img for img in os.listdir(img_dir) if img.startswith(string)] \
              for string in ["fixed_", "row_", "rs_"]], []):
    os.remove(img_dir+"/"+image)
command = cd_topics+"gimp "+output_file
subprocess.Popen(["/bin/bash", "-c", command])

Comment utiliser

  • Copiez le script dans un fichier vide, enregistrez-le sous combine.py. Définissez les informations souhaitées dans la section de tête du script (voir Options / settings, au dessus).
  • Copiez le nombre approprié d'images dans un dossier
  • Exécutez le script par la commande:

    python3 /path/to/combine.py
    

Quelques notes

  • Le script crée une nouvelle image (outfile). Si vous faites une autre combinaison des mêmes images (-répertoire), supprimez-la d'abord, ou elle pourrait apparaître dans le fichier de sortie.
  • Le script trie les images par nom, donc si vous avez besoin d'une commande particulière, nommez-les simplement a.jpg, b.jpg et ainsi de suite.
3
Jacob Vlijm