Table des matières
Introduction
Cet article présente un outil destiné à traiter en batch des images JPEG (ou JPG), pour leur appliquer des redimensionnements. Il s'appuie exactement sur l'option “-resize” d'ImageMagick et permet donc les traitements suivants :
- Largeur x Hauteur max : chaque image sera mise à la plus grande taille possible tout en restant contenue dans un rectangle Largeur x Hauteur (en pixels), de sorte que les proportions d'origine entre largeur et hauteur de l'image soient conservées;
- Largeur x Hauteur forcés : cette option est la seule qui ne garantit pas la conservation des proportions d'origine, car on force réellement chaque image à mesurer la largeur et la hauteur spécifiées;
- Largeur forcée : on fixe la largeur de chaque image à la valeur spécifiée, la conservation des proportions d'origine fixant alors la hauteur en conséquence;
- Hauteur forcée : on fixe la hauteur de chaque image à la valeur spécifiée, la conservation des proportions d'origine fixant alors la largeur en conséquence;
- Largeur x Hauteur max (si images plus grandes) : cette option est identique à la première ci-dessus, mais n'agit que sur les grandes images qui ne tiennent pas dans le rectangle spécifié (les plus petites restent inchangées);
- En % (agrandissement si > 100, reduction si < 100) : la largeur et la hauteur de chaque image subit une homothétie proportionnelle au pourcentage souhaité, par exemple pour doubler de taille on mettre 200, pour diviser par 4 on mettra 25.
Exemple d'utilisation : si un appareil photo numérique produit par défaut des photos de haute résolution, on voudra par exemple réduire les poids des fichiers sans perdre trop en définition, par exemple dans le but de mettre des images sur un site internet ou de les envoyer vers des destinataires à liaison bas débit ou avec boîte-à-lettre limitée en taille.
L'outil est une réplique du 1er outil JPG présenté ici : Modifier des images jpg, qu'on conseille vivement d'installer au préalable car nombre de paquetages et scripts sont communs.
Voici l'aspect de la fenêtre de l'outil :
Remarque : aulieu de copier/coller les lignes de code de cet article vers des fichiers, essayez de télécharger et installer le contenu de :taille_images_1.2.tar.gz.
Article rédigé par Jeanmm
Version initiale : 24/9/2006.
Dernière version : 1.2 du 1er octobre 2006.
Script Python principal
Le script principal ressemble fortement au script de l'outil de modifications cité ci-dessus. Tous les commentaires s'appliquent donc de la même manière.
Le script ci-dessous s'appellera par défaut jpeg-taille.py dans /usr/local/bin. Il gère la fenêtre graphique, analyse les options saisies par l'utilisateur puis appelle le script bash de traitement. Les dimensions minimales admises sont 10×8 et 5%.
#!/usr/bin/python # -*- coding: iso-8859-1 -*- # Ce script affiche une fenetre de parametrage et de # lancement de scripts bash qui permettent de modifier # la taille d'images jpeg. # Auteur : Jeanmm # Date : 1er octobre 2006 # Version : 1.2 # Licence : GPL # Lien : http://www.root66.net import sys, os, string from Tkinter import * from FileDialog import * import Pmw from DialogueDossiersJmm import DirBrowserDialog from DialogueFichiersEtDossiersJmm import PmwFileDialog #=========================================== # Debut de la partie a adapter a ses besoins #=========================================== # Titre de la fenetre MonTitre1 = "Modification de tailles d'images jpg" # Les scripts Bash a executer; MonScript1 = 'jpeg-taille' MonScript2 = 'jpeg-comptage' # Logos pour agrementer la fenetre MonLogoDossier = '/usr/local/divers/LogoDossier.gif' MonLogoLinux = '/usr/local/divers/LogoRoot66b.gif' # Options de traitement # Ou modifier le contenu du fichier /home/nom/.root66/jpeg-taille.txt monDossier = os.path.join(os.getenv('HOME'), 'Images') sousDossiers = '1' largeurImages = '1024' hauteurImages = '768' pourcentAgrandissement = '75' optionTraitement = 'Largeur x Hauteur max' #optionTraitement = 'Largeur x Hauteur forces' #optionTraitement = 'Largeur forcee' #optionTraitement = 'Hauteur forcee' #optionTraitement = 'Largeur x Hauteur max (si images plus grandes)' #optionTraitement = 'En % (agrandissement si > 100, reduction si < 100)' # titre facultatif en debut de zone deroulante titre = """ Cet outil sert a modifier la taille d'images JPG ------------------------------------------------ Choisissez : - le dossier de base contenant les images a traiter (F3 permet de naviguer entre le dossier mis par defaut, le dossier courant de l'utilisateur et son home; F4 affiche la fenetre de navigation comme quand on clique sur le logo de dossier), - le nombre de niveaux de sous-dossiers qu'il faut traiter (1 par defaut ==> seul le dossier choisi sera traite), - les parametres de Largeur et Hauteur en pixels, le % d'agrandissement/reduction, - une des options parmi celles proposees, puis appuyez sur le bouton de traitement. A noter : - Les images gardent toujours les mêmes proportions, sauf dans le cas de l'option 'Largeur x Hauteur forces'. - F5 agit comme quand on clique sur le bouton Compter / Lister, - Alt+F4 termine le programme comme le bouton Quitter, - La config par défaut est modifiable dans /home/utilisateur/.root66/jpeg-taille.txt. \n""" #=========================================== # Fin de la partie a adapter a ses besoins #=========================================== # Option generale de listage de numeros de lignes NumLi = 0 # option : 0=non, 1=oui ii = 0 # numero de ligne # Dossiers accessibles cycliquement par F3 Dossiers = ['','',''] # dossier courant, courant au lancement, et home NumDos = 0 # Argument selon Option de traitement monArgument = "1024x768" # Sous-programmes generaux # ======================== # Parcours de 3 dossiers predefinis par F3 # ---------------------------------------- def f3(ev=None): global Dossiers, NumDos NumDos = NumDos + 1 if NumDos == 3: NumDos = 0 entree1.delete(0,END) entree1.insert(END, Dossiers[NumDos]) # Parcours de dossiers general par F4 #------------------------------------ def f4(ev=None): texte2['text'] = "" if os.path.isdir(entree1.get()): rep = entree1.get() else: texte2.configure(fg='red', font=('Times', 12, 'bold')) texte2['text']="Nom de dossier invalide ?" entree1.focus_set() entree1.xview(END) return dirBrowserDialog = DirBrowserDialog(fen1, label = '', path = rep, hidedotfiles = 1, title = 'Selection de dossier') dir = dirBrowserDialog.activate() fen1.focus_set() if dir != None: entree1.delete(0,END) entree1.insert(END, dir) entree1.focus_set() entree1.xview(END) # Comptage/Listage de noms de fichiers JPG par bouton ou F5 #---------------------------------------------------------- # On les compte d'abord, avec listage d'infos sommaires, # puis on affiche une fenetre de parcours. def f5(ev=None): global ii # Numero de ligne texte2['text'] = "" if os.path.isdir(entree1.get()): rep=entree1.get() else: texte2.configure(fg='red', font=('Times', 12, 'bold')) texte2['text'] = "Nom de dossier invalide ?" entree1.focus_set() entree1.xview(END) return texte2.configure(fg='red', font=('Times', 12, 'bold')) fen1.update_idletasks() # Traitement du dossier try: os.chdir(entree1.get()) except: ii += 1 if NumLi: ligne = '%04d ' %(ii) zoneListage.insert(END, ligne) ligne = "Le Dossier n'existe pas ?!?\n\n" zoneListage.insert(END, ligne, 'rouge') zoneListage.see(END) texte2['text'] = "Le Dossier n'existe pas ?!?" entree1.focus_set() return Dossiers[0] = entree1.get() # Argument 1 : Pofondeur de parcours des sous-dossiers # (1 par defaut = seulement le dossier courant) try: NbDos = int(entree2.get()) except: ii += 1 if NumLi: ligne = '%04d ' %(ii) zoneListage.insert(END, ligne) ligne = "Le nombre de sous-dossiers est invalide ?!?\n\n" zoneListage.insert(END, ligne, 'rouge') zoneListage.see(END) texte2['text']="Le nombre de sous-dossiers est invalide ?!?" entree2.focus_set() return if NbDos < 1: # Nb >= 1 NbDos = 1 entree2.delete(0,END) entree2.insert(END, '1') # Lancement du script de comptage fin,fout = os.popen4(MonScript2 + ' ' + str(NbDos)) # Boucle de recuperation des resultats (txt='' => termine) txt = 'x' # Contenu de chaque ligne produite (stdout + stderr) while txt: txt=fout.readline() ii += 1 if NumLi: ligne = '%04d ' %(ii) zoneListage.insert(END, ligne) if txt: ligne = '%s' %(txt) else: ligne = '\n' if ligne[0:12] == 'Aucune image': texte2['text'] = 'Aucune image.jpg ?' zoneListage.insert(END, ligne, 'rouge') else: zoneListage.insert(END, ligne) zoneListage.see(END) fen1.update_idletasks() fin.close() fout.close() if texte2['text'][0:12] == 'Aucune image': pass else: texte2['text'] = '' # Affichage de fenetre de parcours des dossiers f0 = PmwFileDialog(fen1, info = "(nota : les dossiers debutant avec un '.' ne seront pas traites)") f0.title("Listage des images.jpg") fname = f0.askfilename(directory=rep, filter='*.jpg') # Actionnement des boutons radio # ------------------------------ def modifBoutonMultiple(tag): """ fonction appelee quand un bouton de choix parmi un groupe est modifie - tag = nom du bouton """ global monArgument monArgument = tag # Rafraichissement de fenetre en cas de deplacement # ------------------------------------------------- def rafraichissement(ev): fen1.update_idletasks() # quitter le programme # -------------------- # on simule le clic sur le bouton quand il est selectionne + touche entree def quitter(ev=None): bouton2.invoke() # Sous-programme de Traitement principal # -------------------------------------- def traiter_les_images(ev=None): global ii # Numero de ligne global Dossiers # Noms dossiers global monArgument # Option selectionnee dans la fenetre texte2.configure(fg='red', font=('Times', 12, 'bold')) texte2['text'] = 'Traitement en cours...' fen1.update_idletasks() # Traitement du dossier try: os.chdir(entree1.get()) except: ii += 1 if NumLi: ligne = '%04d ' %(ii) zoneListage.insert(END, ligne) ligne = "Le Dossier n'existe pas ?!?\n\n" zoneListage.insert(END, ligne, 'rouge') zoneListage.see(END) texte2['text'] = "Le Dossier n'existe pas ?!?" entree1.focus_set() return Dossiers[0] = entree1.get() # Argument 2 : Pofondeur de parcours des sous-dossiers # (1 par defaut = seulement le dossier courant) try: NbDos = int(entree2.get()) except: ii += 1 if NumLi: ligne = '%04d ' %(ii) zoneListage.insert(END, ligne) ligne = "Le nombre de sous-dossiers est invalide ?!?\n\n" zoneListage.insert(END, ligne, 'rouge') zoneListage.see(END) texte2['text'] = "Le nombre de sous-dossiers est invalide ?!?" entree2.focus_set() return if NbDos < 1: # Nb >= 1 NbDos = 1 entree2.delete(0,END) entree2.insert(END, '1') # Argument 3 : Largeur des images try: largeur = int(entree3.get()) except: ii += 1 if NumLi: ligne = '%04d ' %(ii) zoneListage.insert(END, ligne) ligne = "La Largeur des images est invalide ?!?\n\n" zoneListage.insert(END, ligne, 'rouge') zoneListage.see(END) texte2['text'] = "La Largeur des images est invalide ?!?" entree3.focus_set() return if largeur < 10: # Largeur >= 10 largeur = 10 entree3.delete(0,END) entree3.insert(END, '10') # Argument 4 : Hauteur des images try: hauteur = int(entree4.get()) except: ii += 1 if NumLi: ligne = '%04d ' %(ii) zoneListage.insert(END, ligne) ligne = "La Hauteur des images est invalide ?!?\n\n" zoneListage.insert(END, ligne, 'rouge') zoneListage.see(END) texte2['text'] = "La Hauteur des images est invalide ?!?" entree4.focus_set() return if hauteur < 8: # Hauteur >= 8 hauteur = 8 entree4.delete(0,END) entree4.insert(END, '8') # Argument 5 : % de redimensionnement try: pourcent = int(entree5.get()) except: ii += 1 if NumLi: ligne = '%04d ' %(ii) zoneListage.insert(END, ligne) ligne = "Le % de reduction/agrandissement est invalide ?!?\n\n" zoneListage.insert(END, ligne, 'rouge') zoneListage.see(END) texte2['text'] = "Le % de reduction/agrandissement est invalide ?!?" entree5.focus_set() return if pourcent < 5: # Nb >= 5 pourcent = 5 entree5.delete(0,END) entree5.insert(END, '5') if monArgument == 'Largeur x Hauteur max': z = "%dx%d" %(largeur, hauteur) elif monArgument == 'Largeur x Hauteur forces': z = "%dx%d!" %(largeur, hauteur) elif monArgument == 'Largeur forcee': z = "%d" %(largeur) elif monArgument == 'Hauteur forcee': z = "x%d" %(hauteur) elif monArgument == 'Largeur x Hauteur max (si images plus grandes)': z = "%dx%d>" %(largeur, hauteur) elif monArgument == 'En % (agrandissement si > 100, reduction si < 100)': z = "%d" %(pourcent) + "%" # Lancement du script z = MonScript1 + ' "' + z + '"' + ' ' + str(NbDos) + ' 1' fin,fout=os.popen4(z) # Boucle de recuperation des resultats (txt='' => termine) txt='x' # Contenu de chaque ligne produite (stdout + stderr) while txt: txt = fout.readline() ii += 1 if NumLi: ligne = '%04d ' %(ii) zoneListage.insert(END, ligne) if txt: ligne = '%s' %(txt) else: ligne = '\n' if ligne[0:12] == 'Aucune image': texte2['text'] = 'Aucune image.jpg ?' zoneListage.insert(END, ligne, 'rouge') else: zoneListage.insert(END, ligne) zoneListage.see(END) fen1.update_idletasks() fin.close() fout.close() if texte2['text'][0:12] == 'Aucune image': pass else: texte2['text'] = 'OK - traitement termine' # =============== Programme principal ================= # Lecture du fichier de configuration ~/.root66/jpeg-taille.txt # ------------------------------------------------------------- d1=os.path.join(os.getenv('HOME'), '.root66') f1=os.path.join(d1, 'jpeg-taille.txt') if os.path.isfile(f1): try: fo1=open(f1, 'r') t="" while 1: # Lecture d'une ligne t=fo1.readline() # Ligne vide => fin de fichier if t=='': break # Suppression des caracteres de fins de lignes if t[-1]=='\n': # 'new-line' t=t[0:-1] # Separation et analyse des champs : parametre = z[0], valeur = z[1] z=string.split(t,'=') if z[0] == 'monDossier' and z[1] != '': monDossier = z[1] elif z[0] == 'sousDossiers' and z[1] != '': sousDossiers = z[1] elif z[0] == 'largeurImages' and z[1] != '': largeurImages = z[1] elif z[0] == 'hauteurImages' and z[1] != '': hauteurImages = z[1] elif z[0] == 'pourcentAgrandissement' and z[1] != '': pourcentAgrandissement = z[1] elif z[0] == 'optionTraitement' and z[1] != '': optionTraitement = z[1] fo1.close() except: print "Fichier de config invalide", t, "?" else: # On essaie de creer le dossier .root66 et le fichier if not os.path.isdir(d1): try: os.makedirs(d1) except: print "Impossible de creer le dossier " + d1 sys.exit(1) try: fo1=open(f1, 'w') fo1.write("# Fichier de configuration de l'outil jpeg-taille.py\n") fo1.write("#\n") fo1.write("# Options de traitement :\n") fo1.write("# - mettre un '#' devant les lignes inutiles,\n") fo1.write("# - et pas de blancs autour des '='.\n") fo1.write("#\n") fo1.write("monDossier=%s\n" %monDossier) fo1.write("sousDossiers=%s\n" %sousDossiers) fo1.write("#\n") fo1.write("largeurImages=%s\n" %largeurImages) fo1.write("hauteurImages=%s\n" %hauteurImages) fo1.write("pourcentAgrandissement=%s\n" %pourcentAgrandissement) fo1.write("#\n") z='Largeur x Hauteur max' if optionTraitement==z: fo1.write("optionTraitement=%s\n" %z) else: fo1.write("#optionTraitement=%s\n" %z) z='Largeur x Hauteur forces' if optionTraitement==z: fo1.write("optionTraitement=%s\n" %z) else: fo1.write("#optionTraitement=%s\n" %z) z='Largeur forcee' if optionTraitement==z: fo1.write("optionTraitement=%s\n" %z) else: fo1.write("#optionTraitement=%s\n" %z) z='Hauteur forcee' if optionTraitement==z: fo1.write("optionTraitement=%s\n" %z) else: fo1.write("#optionTraitement=%s\n" %z) z='Largeur x Hauteur max (si images plus grandes)' if optionTraitement==z: fo1.write("optionTraitement=%s\n" %z) else: fo1.write("#optionTraitement=%s\n" %z) z='En % (agrandissement si > 100, reduction si < 100)' if optionTraitement==z: fo1.write("optionTraitement=%s\n" %z) else: fo1.write("#optionTraitement=%s\n" %z) fo1.close() except: print "Impossible de creer le fichier",f1 # Instanciation d'une fenetre Pmw (Python mega-widgets) # ----------------------------------------------------- fen1 = Pmw.initialise() fen1.title(MonTitre1) fen1.monOption = IntVar() # Dossiers pour touche F3 Dossiers[0] = monDossier Dossiers[1] = os.getcwd() Dossiers[2] = os.getenv('HOME') fen1.bind("<F3>", f3) fen1.bind("<F4>", f4) fen1.bind("<F5>", f5) fen1.bind("<Alt-F4>", quitter) fen1.bind("<Configure>", rafraichissement) # creation des widgets de configuration/lancement du script # ========================================================= # Ligne 1 # ------- texte1 = Label(fen1, text=' Dossier :') texte1.grid(row=1, column=1, sticky=E, padx=5, pady=5) # Saisie de nom de dossier # alternatives : f3 pour 3 valeurs predefinies, f4 pour dialogue entree1 = Entry(fen1, bg='white', fg='dark blue') #entree1 = Entry(fen1, width=74, bg='white', fg='dark blue') entree1.grid(row=1, column=2, columnspan=7, sticky=EW, padx=3, pady=5) entree1.insert(END, monDossier) # Dossier configure entree1.focus_set() # Bouton pour dialogue de parcours de dossier (aussi par f4) logo = PhotoImage(file=MonLogoDossier) bouton0 = Button(fen1, activebackground='DeepSkyBlue2', image=logo, command=f4) bouton0.grid(row=1, column=9, sticky=W, padx=3, pady=3) bouton0.bind("<Return>",f4) # Ligne 2 # ------- texte2 = Label(fen1, text='Sous-Dossiers :') texte2.grid(row=2, column=1, sticky=E, padx=5, pady=5) entree2 = Entry(fen1, width=3, bg='white', fg='dark blue') entree2.grid(row=2, column=2, sticky=W, padx=3, pady=5) entree2.insert(END, sousDossiers) # valeur par defaut texte3 = Label(fen1, text='Largeur :') texte3.grid(row=2, column=3, sticky=E, padx=5, pady=5) entree3 = Entry(fen1, width=5, bg='white', fg='dark blue') entree3.grid(row=2, column=4, sticky=W, padx=3, pady=5) entree3.insert(END, largeurImages) # valeur par defaut texte4 = Label(fen1, text='Hauteur :') texte4.grid(row=2, column=5, sticky=E, padx=5, pady=5) entree4 = Entry(fen1, width=5, bg='white', fg='dark blue') entree4.grid(row=2, column=6, sticky=W, padx=3, pady=5) entree4.insert(END, hauteurImages) # valeur par defaut texte5 = Label(fen1, text='% :') texte5.grid(row=2, column=7, sticky=E, padx=5, pady=5) entree5 = Entry(fen1, width=4, bg='white', fg='dark blue') entree5.grid(row=2, column=8, sticky=W, padx=3, pady=5) entree5.insert(END, pourcentAgrandissement) # valeur par defaut # Lignes 3 a 9 # ------------ # widget RadioSelect vertical, avec les choix de traitements # sur 7 colonnes zz = Pmw.RadioSelect(fen1, buttontype = 'radiobutton', orient = 'vertical', labelpos = 'w', command = modifBoutonMultiple, label_text = 'Redimensionner :', hull_borderwidth = 2, hull_relief = 'ridge', ) zz.grid(row=3, rowspan=6, column=1, columnspan=8, sticky='ew', padx=5, pady=2) zz.add('Largeur x Hauteur max') zz.add('Largeur x Hauteur forces') zz.add('Largeur forcee') zz.add('Hauteur forcee') zz.add('Largeur x Hauteur max (si images plus grandes)') zz.add('En % (agrandissement si > 100, reduction si < 100)') zz.invoke(optionTraitement) # Ligne 9 # ------- # Infos diverses (erreurs, fin de traitement...) texte2 = Label(fen1, text='Dossier courant : ' + os.getcwd()) texte2.grid(row=9, column=1, columnspan=8, padx=5, pady=5) # Ligne 10 # -------- # Bouton pour lister les images bouton1a = Button(fen1, bg='DeepSkyBlue4', activebackground='DeepSkyBlue2', fg='white', width=15, text="Compter / Lister", command=f5) bouton1a.grid(row=6, column=9, columnspan=2, padx=3, pady=2) bouton1a.bind("<Return>",f5) # Bouton pour traiter les images bouton1b = Button(fen1, bg='DeepSkyBlue4', activebackground='DeepSkyBlue2', fg='white', width=15, text="Traiter", command=traiter_les_images) bouton1b.grid(row=7, column=9, columnspan=2, padx=3, pady=2) bouton1b.bind("<Return>",traiter_les_images) # Bouton pour quitter bouton2 = Button(fen1, bg='DeepSkyBlue4', activebackground='DeepSkyBlue2', fg='white', width=15, text='Quitter', command=fen1.quit) bouton2.grid(row=8, column=9, columnspan=2, padx=3, pady=2) bouton2.bind("<Return>",quitter) # Logo en bout de lignes # ---------------------- # decoratif et facultatif can1 = Canvas(fen1, width=102, height=104, bg='AntiqueWhite3') photo = PhotoImage(file=MonLogoLinux) item = can1.create_image(52, 53, image=photo) can1.grid(row=1, column=10, rowspan=5, sticky=N, padx=3, pady=3) # Ligne 12 : Zone de listage des resultats des scripts # ---------------------------------------------------- # C'est un rectangle de la largeur totale de la fenetre, # avec ascenseurs automatiques si necessaire; # hauteur max : limitee selon taille d'ecran, pour que # toute la fenetre soit totalement visible (important pour # les ecrans de 600 ou 768 pixels). h = fen1.winfo_screenheight() - 426 - 48 if h > 400: h = 400 elif h < 100: h = 100 zoneListage = Pmw.ScrolledText(fen1, text_font = 'Courier 11 normal', text_bg = 'AliceBlue', text_padx = 10, text_pady = 10, text_wrap = 'none', borderframe = 1, borderframe_borderwidth = 3, borderframe_relief = RIDGE, usehullsize = 1, hull_width = 680, hull_height = h) zoneListage.grid(row=10, column=1, columnspan=10, padx=5, pady=5) zoneListage._textbox['takefocus'] = 0 ii = 0 # Compteur des lignes inserees # balise pour lignes rouges creees ici (en plus # des lignes noires generees par le script) zoneListage.tag_configure('rouge', foreground='red') zoneListage.insert(END, titre) # Lancement de l'application # -------------------------- fen1.mainloop()
Valeurs par défaut
Les adaptations sont principalement à faire en début de script entre les lignes :
#=========================================== # Debut de la partie a adapter a ses besoins #=========================================== ...etc... #=========================================== # Fin de la partie a adapter a ses besoins #===========================================
Les valeurs par défaut sont définies ainsi :
# Options de traitement # Ou modifier le contenu du fichier /home/nom/.root66/jpeg-taille.txt monDossier = os.path.join(os.getenv('HOME'), 'Images') sousDossiers = '1' largeurImages = '1024' hauteurImages = '768' pourcentAgrandissement = '75' optionTraitement = 'Largeur x Hauteur max' #optionTraitement = 'Largeur x Hauteur forces' #optionTraitement = 'Largeur forcee' #optionTraitement = 'Hauteur forcee' #optionTraitement = 'Largeur x Hauteur max (si images plus grandes)' #optionTraitement = 'En % (agrandissement si > 100, reduction si < 100)'
On pourra y mettre les chiffres qu'on utilisera le plus souvent, par exemple 800×600, 600×450… et pareil pour le %. Ici les largeurs/hauteurs sont toutes dans le rapport 4/3, mais si on a des images 16/9 on adaptera.
De même le dossier par défaut pourra par exemple être redéfini dans “monDossier”. Si par exemple on veut “/mnt/MesPhotos/DossierTempo”, on codera :
MonDossier = "/mnt/MesPhotos/DossierTempo"
Attention : Les options par défaut ci-dessus ne sont valables qu'une seule fois. Dès le 1er lancement l'outil crée le fichier /home/nom/.root66/jpeg-taille.txt s'il n'existait pas. Le fichier est créé à partir des options ci-dessus, et c'est dans ce fichier qu'on pourra ensuite fixer ses options perso de manière stable, même si on installe ultérieurement une nouvelle version de l'outil.
L'outil démarre donc en lisant le fichier /home/nom/.root66/jpeg-taille.txt (sauf la toute 1ère fois). Si on veut personnaliser l'outil, le mieux est de se le copier dans son espace perso, et de lancer cet outil perso, donc sans modifier l'outil commun. Seul le fichier jpeg-taille.py serait à dupliquer, les autres pourront rester inchangés dans /usr/local/bin. Pour un outil perso on conseille à minima de remplacer toutes les occurrences du fichier de configuration jpeg-taille.txt par un nom différent, comme ça chaque outil disposera de sa propre configuration indépendante des autres.
Pour le reste des explications on se reportera à l'article sur l'outil de modifications générales d'images JPG, et à l'article sur l'outil de sauvegarde de fichiers. On conseille notamment d'effectuer les premiers tests en lançant l'outil en ligne de commande afin de visualiser et corriger d'éventuelles erreurs (paquetages non trouvés, dossiers inexistants, scripts non exécutables…).
Script Bash de redimensionnement
Le script ci-dessous s'appellera par défaut jpeg-taille dans /usr/local/bin. Il reçoit les paramètres de l'utilisateur via le script Python ci-dessus, puis effectue les traitements en appelant l'outil convert d'ImageMagick.
#!/bin/sh # # Redimensionnement d'images JPG par ImageMagick # ---------------------------------------------- # # Les dates des fichiers sont preservees. # # Boucle sur les seules images jpg du dossier courant # ou plusieurs niveaux de sous-dossiers selon la variable # max passee optionnellement en 2eme argument du script. # # Auteur : Jeanmm # Date : 24 septembre 2006 # Licence : GPL # Lien : http://www.root66.net # 1er argument obligatoire : options de redimensionnement pour ImageMagick # ------------------------------------------------------------------------ if [ "0$1" == "0" ] ; then echo "Indiquer en argument 1 les options de redimensionnement pour ImageMagick" exit 1 fi # 2eme argument : profondeur find # ------------------------------- if [ 0$2 -ne 0 ] ; then max=$2 else max=1 fi # 3eme argument : listage d'infos en + # ------------------------------------ if [ 0$3 -ne 0 ] ; then bavard=$3 else bavard=0 fi # Comptage des images # ------------------- countT=0 for ii in `find . -maxdepth $max -type f -iname "*.jpg"` ; do countT=$[$countT + 1] done test $countT -eq 0 && echo "Aucune image.jpg a traiter ?" && exit 0 if [ $bavard -eq 1 ] ; then if [ $countT -lt 2 ] ; then echo "Redimensionnement d'images : $countT image trouvee" else echo "Redimensionnement d'images : $countT images trouvees" fi cc=0 fi # Traitement du redimensionnement # ------------------------------- for i in `find . -maxdepth $max -type f -iname "*.jpg" | sort` ; do if [ $bavard -eq 1 ] ; then echo "Redimensionnement de l'image $i" cc=$[$cc + 1] fi # Redimensionnement par ImageMagick convert -resize "$1" "$i" "$i.tmp.jpg" # Remise de la date d'origine touch -r "$i" "$i.tmp.jpg" && rm -f "$i" && mv "$i.tmp.jpg" "$i" done if [ $bavard -eq 1 ] ; then if [ $cc -lt 2 ] ; then echo "Redimensionnement d'images : $cc image traitee" else echo "Redimensionnement d'images : $cc images traitees" fi fi