Wiki Root66

Le Wiki de Root66, tuto, infos et astuces

Outils pour utilisateurs

Outils du site


redimensionner_des_images_jpeg

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 :

  :wiki-taille-images1.jpg

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 8-)
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
redimensionner_des_images_jpeg.txt · Dernière modification : 2021/10/18 16:09 de 127.0.0.1