begin process at 2010 09 04 19:47:10
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Application complète

 > COMPACTEUR D'IMAGES JPEG PAR LOT

COMPACTEUR D'IMAGES JPEG PAR LOT


 Information sur la source

Note :
8,5 / 10 - par 2 personnes
8,50 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Application complète Classé sous :compression, images, barre progression, PIL, jpeg Niveau :Débutant Date de création :10/12/2007 Date de mise à jour :28/11/2008 09:58:22 Vu / téléchargé :4 901 / 121

Auteur : yveslc

Ecrire un message privé
Commentaire sur cette source (14)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
CompactImages  v.2.1
(Compacteur d'images Jpeg par lot)

Lassé d'appeler une à une avec Gimp toutes mes photos jpeg pour en réduire le poids,j'ai écrit ce
programme qui lit et réécrit tous les fichier Jpeg (ou jpg) d'un répertoire donné.

Cette version est une amélioration de la précédente avec les caractéristiques suivantes :

Mémorisation du répertoire précédemment ouvert dans la même session,
Réglage possible du taux de compression sur toute la plage autorisée en Jpeg,
Possibilité de demander une sauvegarde des originaux avant compression,
Visualisation multiple des images par un simple clic dans la liste,
Affichage de la barre de progression du traitement,
Possibilité d'interrompre le traitement à tout moment,
Liste des images non traitées (images protégées ou en erreur) en fin de traitement,
Affichage automatique du nom de répertoire de sauvegarde des originaux,
Affichage du nombre et du poids total des images avant et après traitement

Ce programme est écrit en python avec Tkinter et PIL ; il est compatible avec la compilation py2exe
sous windows et c'est sous cette forme compilée que je le distribue à mes amis windowsiens.
J'espère qu'il vous sera aussi utile que pour moi.
Yves Le Chevalier

Source

  • #Compacteur images JPEG v.2.1
  • # -*- coding: utf-8 -*-
  • from Tkinter import *
  • from winsound import *
  • from PIL import Image, ImageTk
  • import glob
  • import os
  • import tkFileDialog
  • import string
  • import Tix
  • import shutil
  • import tkMessageBox
  • global repert, dirinit, nbfich, tailaff, taux, chtaux, indsauv
  • taux = 85
  • dirinit = ''
  • indsauv='N'
  • def Exploration() :
  • global repert, dirinit, nbfich,tailaff, tailrepe
  • list1.delete(0,END)
  • nbfich=0
  • lab2.configure(text='')
  • lab3.configure(text='')
  • lab4.configure(text='')
  • lab5.configure(text='')
  • lab6.configure(text='')
  • lab7.configure(text='')
  • lab8.configure(text='')
  • lab9.configure(text='')
  • button1.config(bg='SlateGray2',text='',state=DISABLED,relief=FLAT)
  • repert=tkFileDialog.askdirectory(title='Choisir le répertoire à traiter',initialdir=dirinit)
  • dirinit=repert
  • repert=repert+'\\*.*'
  • for fichier in glob.glob(repert):
  • file, ext = os.path.splitext(fichier)
  • tailfich = os.path.getsize(fichier)
  • tailfiaff = tailfich/1024
  • chaine='%4d'%tailfiaff+' Ko ^ '+fichier
  • if ext=='.jpg' or ext=='.JPG' or ext=='.jpeg' or ext=='.JPEG' :
  • list1.insert(END,chaine)
  • nbfich=nbfich+1
  • Taille_Repert()
  • tailrepe = tailaff
  • if nbfich > 0 :
  • lab2.configure(text='Taille cumulée des images = '+tailaff)
  • lab3.configure(text='Nombre d''\'images = '+str(nbfich))
  • button1.config(bg='yellow',text='Valider',state=NORMAL,relief=RAISED)
  • list1.select_set(0)
  • list1.bind('<ButtonRelease>',Affiche_image1)
  • def Affiche_image1(e) :
  • if nbfich > 0 :
  • index = map(int,list1.curselection())[0]
  • fichima = string.strip(list1.get(index))
  • nom=''
  • ind=0
  • i=0
  • while i< len(fichima) :
  • if ind==1 :
  • nom=nom+fichima[i]
  • if fichima[i]=='^' :
  • ind=1
  • i=i+1
  • i=i+1
  • im=Image.open(nom)
  • im.load()
  • im.thumbnail((300,300),Image.ANTIALIAS)
  • fenaff = Toplevel()
  • if im.size[0] < 100 :
  • larim=100
  • else : larim=im.size[0]
  • if im.size[1] < 20 :
  • hauim=20
  • else : hauim=im.size[1]
  • fenaff.geometry(str(larim)+"x"+str(hauim))
  • fenaff.resizable(width=False, height=False)
  • fenaff.config(bg='lightgrey')
  • canaff = Canvas(fenaff,width=im.size[0],height=im.size[1])
  • canaff.pack()
  • nombase = os.path.basename(nom)
  • fenaff.title(nombase)
  • vignette = ImageTk.PhotoImage(im)
  • canaff.create_image(0,0,anchor=NW,image=vignette)
  • canaff.monimage = vignette
  • canaff.configure()
  • boeff.config(text="Fermer vues",bg='DarkOliveGreen3', fg='white',state=NORMAL,relief=RAISED)
  • def Arreter_validation() :
  • global ifin3,nbok
  • ifin3=1
  • lab8.configure(text='Traitement interrompu : '+str(nbok)+' images traitées.')
  • def Validation() :
  • global dirinit, repert, nbfich, ficherr, tailaff, tailrep, tailrepe,ifin3,nbok,indsauv,isav
  • ifin3=0
  • fen3=Tix.Tk()
  • geo1=fen1.winfo_geometry()
  • geox=fen1.winfo_rootx()
  • geoy=fen1.winfo_rooty()
  • fen3.geometry("400x120+"+str(geox+55)+"+"+str(geoy+190))
  • fen3.title(repert)
  • labb=Label(fen3,text='Progression du compactage', fg='blue', font=('Arial', 10))
  • labb.pack(side=TOP)
  • meter=Tix.Meter(fen3,value=0.)
  • meter.pack()
  • labf=Label(fen3,text='', fg='black', font=('Arial',9))
  • labf.pack(side=BOTTOM)
  • Bfin3=Button(fen3,text="Arrêter",bg='pink',fg='blue', command=lambda : Arreter_validation())
  • Bfin3.pack(side=BOTTOM,pady=10)
  • nberr=0
  • nbok = 0
  • ficherr=[] # liste des fichiers en erreur écriture
  • if indsauv=='O':
  • isav=1
  • while os.path.isdir(dirinit+'/Originaux'+str(isav)+'/') :
  • isav=isav+1
  • os.mkdir(dirinit+'/Originaux'+str(isav)+'/')
  • if repert <> '' and nbfich>0 :
  • lab4.configure(text='Traitement en cours.......Patience, merci.')
  • fram5.update_idletasks()
  • i=0
  • for fichier in glob.glob(repert):
  • file, ext = os.path.splitext(fichier)
  • if ext=='.jpg' or ext=='.JPG' or ext=='.jpeg' or ext=='.JPEG' :
  • if ifin3==1 :
  • break
  • i=i+1
  • meter.config(value=float(i)/nbfich)
  • meter.update()
  • labf.configure(text=file)
  • im=Image.open(fichier)
  • chem,fich=os.path.split(fichier)
  • if indsauv=='O' :
  • shutil.copy(fichier,chem+'/Originaux'+str(isav)+'/'+fich)
  • try :
  • im.save(file+'.jpg',quality=taux)
  • nbok = nbok+1
  • except IOError :
  • nberr = nberr+1
  • ficherr.append(file)
  • button1.config(text="",bg='SlateGray2',state=DISABLED,relief=FLAT)
  • lab4.configure(text='Résultat du traitement :')
  • Taille_Repert()
  • if nbok==0 :
  • lab5.configure(text=' Aucune image traitée')
  • elif tailaff == tailrepe :
  • lab5.configure(text=' Ce dossier est déjà compacté')
  • else :
  • lab5.configure(text=str(nbok)+' image(s) analysée(s)')
  • lab6.configure(text='Nouvelle taille cumulée des images = '+tailaff)
  • if indsauv=='O':
  • lab9.configure(text='Originaux dans : '+dirinit+'/Originaux'+str(isav))
  • nbfich=0
  • if nberr>0 :
  • Beep(800,100)
  • lab7.configure(text=str(nberr)+' erreur(s)')
  • Trt_Erreur(nberr,ficherr)
  • repert=''
  • list1.delete(0,END)
  • fen3.destroy()
  • def Taille_Repert() :
  • global repert, tailaff, tailrep
  • tailrep=0
  • for fichier in glob.glob(repert) :
  • file, ext = os.path.splitext(fichier)
  • tailfich = os.path.getsize(fichier)
  • if ext=='.jpg' or ext=='.JPG' or ext=='.jpeg' or ext=='.JPEG' :
  • tailrep=tailrep+tailfich
  • tailrep1 = tailrep/1024/1024.0
  • tailaff = '%.2f' % tailrep1 +' Mo'
  • def Trt_Erreur(nberr,ficherr) :
  • fen2=Toplevel()
  • geo1=fen1.winfo_geometry()
  • geox=fen1.winfo_rootx()
  • geoy=fen1.winfo_rooty()
  • fen2.geometry("400x350+"+str(geox+55)+"+"+str(geoy+170))
  • fen2.title("CompactImages : Erreurs de traitement")
  • labf2=Label(fen2,text=str(nberr)+' images ne pouvant être traitées \n (Images peut-être en lecture seule)', fg='blue', font=('Arial', 9))
  • labf2.pack(side=TOP,pady=10)
  • fram4=Frame(fen2,borderwidth=0)
  • scrollf2 =Scrollbar(fram4,orient=VERTICAL)
  • listf2 = Listbox(fram4,bg='yellow',width=60,height=15,selectmode='single', yscrollcommand=scrollf2.set)
  • scrollf2.config(command = listf2.yview)
  • scrollf2.pack(side=LEFT,fill=Y)
  • listf2.pack(side=LEFT)
  • fram4.pack()
  • bouf2=Button(fen2,text="Fermer",bg='brown',fg='white', command=fen2.destroy)
  • bouf2.pack(side=BOTTOM,pady=10)
  • for x in ficherr :
  • listf2.insert(END,x)
  • fen2.grab_set()
  • fen2.wait_window()
  • def Affich_Infos() :
  • feninf = Toplevel()
  • feninf.config(bg='SlateGray4')
  • geo1=fen1.winfo_geometry()
  • geox=fen1.winfo_rootx()
  • geoy=fen1.winfo_rooty()
  • feninf.geometry("350x390+"+str(geox+75)+"+"+str(geoy+160))
  • feninf.title("À propos de CompactImages")
  • labinf=Label(feninf,bg='SlateGray4', fg='white',width=50,font=('Arial', 9),
  • text= "\nCompactImages v.2.1\n\n"
  • "Programme écrit en Python / Tkinter \n"
  • "et distribué sous licence GNU GPL.\n\n"
  • "© 2008 Yves Le Chevalier\n\n"
  • "Ce programme comprime toutes les images JPG (jpeg)\n"
  • "d'un répertoire donné, sans modifier leurs dimensions.\n"
  • "Il ne comprime pas les images protégées (en lecture seule).\n\n"
  • "Le niveau de compression est réglé à 85 par défaut, mais\n"
  • "peut être modifié sur toute la plage de compression Jpeg.\n\n"
  • "La sauvegarde est facultative et provoque la création d'un\n"
  • "sous-répertoire '''Originaux1'''. Si vous exécutez un second\n"
  • "traitement sur le même répertoire, la sauvegarde se fait alors\n"
  • "dans un sous-répertoire '''Originaux2''', puis la troisième fois\n"
  • " dans un sous-répertoire '''Originaux3''' et ainsi de suite. \n"
  • "Toutes les images analysées sont alors sauvegardées. \n"
  • "Attention : Par défaut, la sauvegarde n'est pas activée.")
  • labinf.pack(pady=5)
  • bouf3=Button(feninf, text="Fermer", command=feninf.destroy,bg="orange", fg='brown')
  • bouf3.pack(side=BOTTOM,pady=10)
  • feninf.grab_set()
  • feninf.wait_window()
  • def Modif_Taux() :
  • global can2, fentau, choixtau
  • fentau = Toplevel()
  • fentau.config(bg='SlateGray3')
  • geo1=fen1.winfo_geometry()
  • geox=fen1.winfo_rootx()
  • geoy=fen1.winfo_rooty()
  • fentau.geometry("350x330+"+str(geox+75)+"+"+str(geoy+170))
  • fentau.title("Taux de compression")
  • labtau=Label(fentau,bg='SlateGray3', fg='black',width=50,font=('Arial', 9),
  • text= "\nModification du taux de compression\n\n"
  • "ATTENTION : le niveau de compression Jpeg varie de 1 à 100 \n"
  • "1 = compression maximale ; 100= aucune compression.\n\n"
  • "La compression optimale se situe vers 85 (valeur par défaut).\n\n"
  • "Vous pouvez changer le niveau de compression, sachant que\n"
  • "si vous comprimez trop, vous perdez de la qualité et si vous ne \n"
  • "comprimez pas assez, vous ne gagnez pas en volume.\n"
  • "Il vaut mieux rester dans une plage de 75 à 90\n")
  • labtau.pack(pady=0)
  • can2 = Canvas(fentau, width=200, height=50, bg='SlateGray3')
  • can2.pack(pady=20)
  • curs= Scale(can2, from_=1, to=100, length=150, sliderlength=7,
  • resolution=1, showvalue=1, orient=HORIZONTAL,
  • label="Réglage du niveau :",command=choix_taux,font=('Arial', 8),bg='SlateGray3',fg='blue')
  • curs.set (85)
  • curs.pack(side=TOP)
  • boutau=Button(can2, text="OK", command=set_taux,font=('Arial', 8),bg="orange", fg='brown')
  • boutau.pack(side=BOTTOM)
  • fentau.grab_set()
  • fentau.wait_window()
  • def choix_taux(valcurs) :
  • global chtaux
  • chtaux=float(valcurs)
  • if chtaux < 75 or chtaux > 90 :
  • fentau.config(bg='red')
  • else : fentau.config(bg='green')
  • def set_taux() :
  • global chtaux, taux
  • taux=int(chtaux)
  • if taux < 75 or taux > 90 :
  • boutau.config(text ="Niveau "+'% d' %taux,bg='red',fg='black')
  • Beep(800,100)
  • else : boutau.config(text ="Niveau "+'% d' %taux,bg='green',fg='black')
  • if taux <> 85 :
  • lab3a.configure(text='ATTENTION : Niveau compression à '+str(taux))
  • else : lab3a.configure(text='')
  • can2.destroy()
  • fentau.destroy()
  • def quitter_prog() :
  • global fenqui
  • fenqui=Toplevel()
  • fenqui.config(bg='yellow',bd=3,relief='groove')
  • geo1=fen1.winfo_geometry()
  • geox=fen1.winfo_rootx()
  • geoy=fen1.winfo_rooty()
  • fenqui.geometry("200x60+"+str(geox+160)+"+"+str(geoy+350))
  • fenqui.resizable(width=False, height=False)
  • fenqui.overrideredirect(1)
  • labqui=Label(fenqui,bg='yellow',fg='black',font=('Arial', 11),text="Quitter CompactImage ?")
  • labqui.place(x=17,y=1)
  • repon=StringVar()
  • bououi=Button(fenqui,text="Oui", bg='pink', fg='black',command=confir_quitter)
  • bounon=Button(fenqui,text="Non", bg='pink', fg='black',command=continu_prog)
  • bououi.place(x=40,y=25)
  • bounon.place(x=120,y=25)
  • fenqui.grab_set()
  • def confir_quitter() :
  • fen1.destroy()
  • def continu_prog() :
  • global fenqui
  • fenqui.destroy()
  • def sauvegarde() :
  • global indsauv
  • if indsauv =='N' :
  • indsauv='O'
  • labsau1.configure(text='Avec sauvegarde',fg='black')
  • bosav.config(text='Sans',bg='SeaGreen4', fg='white')
  • else :
  • indsauv='N'
  • labsau1.configure(text='Sans sauvegarde',fg='grey50')
  • bosav.config(text='Avec',bg='firebrick4', fg='white')
  • def effacer_vues() :
  • for widget in fen1.winfo_children():
  • if isinstance(widget,Toplevel):
  • widget.destroy()
  • boeff.config(text="",bg='SlateGray2',state=DISABLED,relief=FLAT)
  • def close_window() :
  • if tkMessageBox.askokcancel :
  • quitter_prog()
  • # main
  • fen1 = Tk(className=" CompactImages v_2,1")
  • fen1.protocol("WM_DELETE_WINDOW", close_window)
  • fen1.tk_setPalette(background = 'SlateGray2')
  • fen1.geometry("500x800+550+100")
  • fen1.resizable(width=False, height=False)
  • can1 = Canvas(fen1, width=20, height=20, bg='lightgrey')
  • signat=PhotoImage(file='YLC.gif')
  • sign=can1.create_image(12,12, image=signat)
  • can1.pack(side=BOTTOM,anchor=E)
  • fram1=Frame(fen1,borderwidth=0)
  • button2 = Button(fram1, text = 'Répertoire',bg='snow', command = Exploration)
  • button2.grid(row=0,column=0,pady=20)
  • boutau=Button(fram1,text=" Niveau "+'% d' %taux, bg='green', fg='black',command=Modif_Taux)
  • boutau.grid(row=0,column=1,padx=30)
  • bouinf=Button(fram1,text="Information", bg="seagreen4", fg='yellow',command=Affich_Infos)
  • bouinf.grid(row=0,column=2,padx=30)
  • bouf1=Button(fram1,text="Quitter", command=quitter_prog,bg='salmon', fg='black')
  • bouf1.grid(row=0,column=3)
  • labsau1=Label(fram1,text='Sans sauvegarde', fg='grey50', font=('Arial',11))
  • labsau1.grid(row=1,column=0)
  • bosav=Button(fram1,text="Avec", command=sauvegarde,bg='firebrick4', fg='white')
  • bosav.grid(row=1,column=1)
  • boeff=Button(fram1,text="",command=effacer_vues,state=DISABLED,relief=FLAT)
  • boeff.grid(row=1,column=3)
  • fram1.pack(side=TOP)
  • fram2=Frame(fen1,borderwidth=0)
  • labbid1=Label(fram2,text='')
  • labbid1.pack(side=TOP)
  • lab1=Label(fram2,text='Liste des images (Jpg ou Jpeg) à comprimer', fg='blue', font=('Arial', 12))
  • lab1.pack()
  • lab1b=Label(fram2,text='(Cliquer sur une ligne pour voir l''image)', fg='black', font=('Arial', 9))
  • lab1b.pack()
  • scrolly =Scrollbar(fram2,orient=VERTICAL)
  • list1 = Listbox(fram2,bg="SlateGray1",width=70,height=31,selectmode='single', yscrollcommand=scrolly.set)
  • scrolly.config(command = list1.yview)
  • scrolly.pack(side=LEFT,fill=Y)
  • list1.pack()
  • fram2.pack()
  • fram3=Frame(fen1)
  • lab3=Label(fram3,fg='blue',font=('Arial', 9))
  • lab3.grid(row=0,column=1,padx=5)
  • lab2=Label(fram3,fg='blue',font=('Arial', 9))
  • lab2.grid(row=0,column=0,padx=15)
  • lab3a=Label(fram3,fg='red',font=('Arial', 9))
  • lab3a.grid(row=1,column=0,padx=5)
  • button1 = Button(fram3, text = '', command = Validation,state=DISABLED,relief=FLAT)
  • button1.grid(row=1,column=1,padx=35,pady=5)
  • fram3.pack()
  • fram5=Frame(fen1)
  • lab4=Label(fram5,fg='black', font=('Arial', 10))
  • lab4.grid(row=0,column=0,pady=5)
  • lab5=Label(fram5,fg='blue', font=('Arial', 9))
  • lab5.grid(row=0,column=1,sticky=W)
  • lab6=Label(fram5,fg='blue', font=('Arial', 9))
  • lab6.grid(row=1,column=0)
  • lab7=Label(fram5,fg='red', font=('Arial', 9))
  • lab7.grid(row=1,column=1)
  • lab8=Label(fram5,fg='red', font=('Arial', 10))
  • lab8.grid(row=2,column=0,sticky=W)
  • lab9=Label(fram5,fg='black', font=('Arial', 9))
  • lab9.grid(row=3,column=0)
  • fram5.pack()
  • fen1.mainloop()
#Compacteur images JPEG  v.2.1
# -*- coding: utf-8 -*-
from Tkinter import *
from winsound import * 
from PIL import Image, ImageTk
import glob
import os
import tkFileDialog
import  string
import Tix
import shutil
import tkMessageBox

global repert, dirinit, nbfich, tailaff, taux, chtaux, indsauv
taux = 85
dirinit = ''
indsauv='N'
     
def Exploration() :
    global repert, dirinit, nbfich,tailaff, tailrepe
    list1.delete(0,END)
    nbfich=0
    lab2.configure(text='')
    lab3.configure(text='')
    lab4.configure(text='')
    lab5.configure(text='')
    lab6.configure(text='')
    lab7.configure(text='')
    lab8.configure(text='')
    lab9.configure(text='')
    button1.config(bg='SlateGray2',text='',state=DISABLED,relief=FLAT)
    repert=tkFileDialog.askdirectory(title='Choisir le répertoire à traiter',initialdir=dirinit)
    dirinit=repert
    repert=repert+'\\*.*'
    for fichier in glob.glob(repert):
        file, ext = os.path.splitext(fichier)
        tailfich = os.path.getsize(fichier)
        tailfiaff = tailfich/1024
        chaine='%4d'%tailfiaff+' Ko   ^ '+fichier
        if ext=='.jpg' or ext=='.JPG'  or ext=='.jpeg' or ext=='.JPEG' :
            list1.insert(END,chaine)
            nbfich=nbfich+1
    Taille_Repert()
    tailrepe = tailaff
    if nbfich > 0 :
        lab2.configure(text='Taille cumulée des images = '+tailaff)
        lab3.configure(text='Nombre d''\'images = '+str(nbfich))
        button1.config(bg='yellow',text='Valider',state=NORMAL,relief=RAISED)
    list1.select_set(0)
    list1.bind('<ButtonRelease>',Affiche_image1)
    
def Affiche_image1(e) :
    if nbfich > 0 :
        index = map(int,list1.curselection())[0]
        fichima = string.strip(list1.get(index))
        nom=''
        ind=0
        i=0
        while i< len(fichima) :
            if ind==1 :          
                nom=nom+fichima[i]
            if fichima[i]=='^' :
                ind=1
                i=i+1
            i=i+1   
        im=Image.open(nom)
        im.load()
        im.thumbnail((300,300),Image.ANTIALIAS)
        fenaff = Toplevel()
        if im.size[0] < 100 :
            larim=100
        else : larim=im.size[0]
        if im.size[1] < 20 :
            hauim=20
        else : hauim=im.size[1] 
        fenaff.geometry(str(larim)+"x"+str(hauim))
        fenaff.resizable(width=False, height=False)
        fenaff.config(bg='lightgrey')
        canaff = Canvas(fenaff,width=im.size[0],height=im.size[1])
        canaff.pack()
        nombase = os.path.basename(nom)
        fenaff.title(nombase)       
        vignette = ImageTk.PhotoImage(im)
        canaff.create_image(0,0,anchor=NW,image=vignette)
        canaff.monimage = vignette
        canaff.configure()
        boeff.config(text="Fermer vues",bg='DarkOliveGreen3', fg='white',state=NORMAL,relief=RAISED)
    
def Arreter_validation() :
    global ifin3,nbok
    ifin3=1
    lab8.configure(text='Traitement interrompu :  '+str(nbok)+' images traitées.')
    
def Validation() :
    global dirinit, repert, nbfich, ficherr, tailaff, tailrep, tailrepe,ifin3,nbok,indsauv,isav
    ifin3=0
    fen3=Tix.Tk()
    geo1=fen1.winfo_geometry()
    geox=fen1.winfo_rootx()
    geoy=fen1.winfo_rooty() 
    fen3.geometry("400x120+"+str(geox+55)+"+"+str(geoy+190)) 
    fen3.title(repert)
    labb=Label(fen3,text='Progression du compactage', fg='blue', font=('Arial', 10))
    labb.pack(side=TOP)
    meter=Tix.Meter(fen3,value=0.)
    meter.pack()
    labf=Label(fen3,text='', fg='black', font=('Arial',9))
    labf.pack(side=BOTTOM)
    Bfin3=Button(fen3,text="Arrêter",bg='pink',fg='blue', command=lambda : Arreter_validation())
    Bfin3.pack(side=BOTTOM,pady=10)
    nberr=0
    nbok = 0
    ficherr=[]       # liste des fichiers en erreur écriture
    if indsauv=='O':
        isav=1
        while os.path.isdir(dirinit+'/Originaux'+str(isav)+'/') :
             isav=isav+1
        os.mkdir(dirinit+'/Originaux'+str(isav)+'/')       
    if repert <> '' and nbfich>0 :
        lab4.configure(text='Traitement en cours.......Patience, merci.')
        fram5.update_idletasks()
        i=0
        for fichier in glob.glob(repert):
            file, ext = os.path.splitext(fichier)
            if ext=='.jpg' or ext=='.JPG'  or ext=='.jpeg' or ext=='.JPEG' :
                if ifin3==1 :
                    break
                i=i+1
                meter.config(value=float(i)/nbfich)
                meter.update()
                labf.configure(text=file)
                im=Image.open(fichier)
                chem,fich=os.path.split(fichier)
                if indsauv=='O' :
                    shutil.copy(fichier,chem+'/Originaux'+str(isav)+'/'+fich)
                try :
                    im.save(file+'.jpg',quality=taux)
                    nbok = nbok+1
                except IOError :
                    nberr = nberr+1
                    ficherr.append(file)                    
        button1.config(text="",bg='SlateGray2',state=DISABLED,relief=FLAT)
        lab4.configure(text='Résultat du traitement :')
        Taille_Repert()
        if nbok==0 :
            lab5.configure(text=' Aucune image traitée')
        elif tailaff == tailrepe  :
            lab5.configure(text=' Ce dossier est déjà compacté')
        else :
            lab5.configure(text=str(nbok)+'  image(s) analysée(s)')
            lab6.configure(text='Nouvelle taille cumulée des images = '+tailaff)
        if indsauv=='O':
            lab9.configure(text='Originaux dans : '+dirinit+'/Originaux'+str(isav))
        nbfich=0
        if nberr>0 :
            Beep(800,100)
            lab7.configure(text=str(nberr)+'   erreur(s)')
            Trt_Erreur(nberr,ficherr)            
        repert=''
        list1.delete(0,END)
        fen3.destroy()
    
def Taille_Repert() :
    global repert, tailaff, tailrep
    tailrep=0
    for fichier in glob.glob(repert) :
        file, ext = os.path.splitext(fichier)
        tailfich = os.path.getsize(fichier)
        if ext=='.jpg' or ext=='.JPG'  or ext=='.jpeg' or ext=='.JPEG' :
            tailrep=tailrep+tailfich
    tailrep1 = tailrep/1024/1024.0
    tailaff = '%.2f' % tailrep1 +'  Mo'
    
def Trt_Erreur(nberr,ficherr) :
    fen2=Toplevel()
    geo1=fen1.winfo_geometry()
    geox=fen1.winfo_rootx()
    geoy=fen1.winfo_rooty() 
    fen2.geometry("400x350+"+str(geox+55)+"+"+str(geoy+170))
    fen2.title("CompactImages : Erreurs de traitement")
    labf2=Label(fen2,text=str(nberr)+'  images ne pouvant être traitées \n (Images peut-être en lecture seule)', fg='blue', font=('Arial', 9))
    labf2.pack(side=TOP,pady=10)
    fram4=Frame(fen2,borderwidth=0)
    scrollf2 =Scrollbar(fram4,orient=VERTICAL)
    listf2 = Listbox(fram4,bg='yellow',width=60,height=15,selectmode='single', yscrollcommand=scrollf2.set)
    scrollf2.config(command  =  listf2.yview)
    scrollf2.pack(side=LEFT,fill=Y)
    listf2.pack(side=LEFT)
    fram4.pack()
    bouf2=Button(fen2,text="Fermer",bg='brown',fg='white', command=fen2.destroy)
    bouf2.pack(side=BOTTOM,pady=10)
    for x in ficherr :
        listf2.insert(END,x)
    fen2.grab_set()
    fen2.wait_window()

def Affich_Infos() :	
    feninf = Toplevel()
    feninf.config(bg='SlateGray4')
    geo1=fen1.winfo_geometry()
    geox=fen1.winfo_rootx()
    geoy=fen1.winfo_rooty() 
    feninf.geometry("350x390+"+str(geox+75)+"+"+str(geoy+160))
    feninf.title("À propos de CompactImages")
    labinf=Label(feninf,bg='SlateGray4', fg='white',width=50,font=('Arial', 9),
        text= "\nCompactImages v.2.1\n\n"
                "Programme écrit en Python / Tkinter \n"
                 "et distribué sous licence GNU GPL.\n\n"
                "© 2008  Yves Le Chevalier\n\n"
                "Ce programme comprime toutes les images JPG (jpeg)\n"
                "d'un répertoire donné, sans modifier leurs dimensions.\n"
                 "Il ne comprime pas les images protégées (en lecture seule).\n\n"
                 "Le niveau de compression est réglé à 85 par défaut, mais\n"
                 "peut être modifié sur toute la plage de compression Jpeg.\n\n"
                 "La sauvegarde est facultative et provoque la création d'un\n"
                 "sous-répertoire '''Originaux1'''. Si vous exécutez un second\n"
                 "traitement sur le même répertoire, la sauvegarde se fait alors\n"
                 "dans un sous-répertoire '''Originaux2''', puis la troisième fois\n"
                 " dans un sous-répertoire '''Originaux3''' et ainsi de suite.      \n"
                 "Toutes les images analysées sont alors sauvegardées.     \n"
                 "Attention :  Par défaut, la sauvegarde n'est pas activée.")
    labinf.pack(pady=5)
    bouf3=Button(feninf, text="Fermer", command=feninf.destroy,bg="orange", fg='brown')
    bouf3.pack(side=BOTTOM,pady=10)
    feninf.grab_set()
    feninf.wait_window()

def Modif_Taux() :
    global can2, fentau, choixtau
    fentau = Toplevel()
    fentau.config(bg='SlateGray3')
    geo1=fen1.winfo_geometry()
    geox=fen1.winfo_rootx()
    geoy=fen1.winfo_rooty() 
    fentau.geometry("350x330+"+str(geox+75)+"+"+str(geoy+170))
    fentau.title("Taux de compression")
    labtau=Label(fentau,bg='SlateGray3', fg='black',width=50,font=('Arial', 9),
        text= "\nModification du taux de compression\n\n"
                "ATTENTION : le niveau de compression Jpeg varie de 1 à 100 \n"
                 "1 = compression maximale ; 100= aucune compression.\n\n"
                 "La compression optimale se situe vers 85 (valeur par défaut).\n\n"
                "Vous pouvez changer le niveau de compression, sachant que\n"
                "si vous comprimez trop, vous perdez de la qualité et si vous ne \n"
                 "comprimez pas assez, vous ne gagnez pas en volume.\n"
                 "Il vaut mieux rester dans une plage de 75 à 90\n")
    labtau.pack(pady=0)
    can2 = Canvas(fentau, width=200, height=50, bg='SlateGray3')
    can2.pack(pady=20)
    curs= Scale(can2, from_=1, to=100, length=150, sliderlength=7,
                resolution=1, showvalue=1, orient=HORIZONTAL,
                label="Réglage du niveau :",command=choix_taux,font=('Arial', 8),bg='SlateGray3',fg='blue')
    curs.set (85)
    curs.pack(side=TOP)
    boutau=Button(can2, text="OK", command=set_taux,font=('Arial', 8),bg="orange", fg='brown')
    boutau.pack(side=BOTTOM)
    fentau.grab_set()
    fentau.wait_window()
    
def choix_taux(valcurs) :
    global chtaux
    chtaux=float(valcurs)
    if chtaux < 75 or chtaux > 90 :
        fentau.config(bg='red')
    else :  fentau.config(bg='green')

def set_taux() :
    global chtaux, taux
    taux=int(chtaux)
    if taux < 75 or taux > 90 :
        boutau.config(text ="Niveau "+'% d' %taux,bg='red',fg='black')
        Beep(800,100)
    else : boutau.config(text ="Niveau "+'% d' %taux,bg='green',fg='black')
    if taux <> 85 :
        lab3a.configure(text='ATTENTION : Niveau compression à '+str(taux))
    else : lab3a.configure(text='')
    can2.destroy()
    fentau.destroy()

def quitter_prog() :
    global fenqui
    fenqui=Toplevel()
    fenqui.config(bg='yellow',bd=3,relief='groove')
    geo1=fen1.winfo_geometry()
    geox=fen1.winfo_rootx()
    geoy=fen1.winfo_rooty() 
    fenqui.geometry("200x60+"+str(geox+160)+"+"+str(geoy+350))
    fenqui.resizable(width=False, height=False)
    fenqui.overrideredirect(1)
    labqui=Label(fenqui,bg='yellow',fg='black',font=('Arial', 11),text="Quitter CompactImage ?")
    labqui.place(x=17,y=1)
    repon=StringVar()
    bououi=Button(fenqui,text="Oui", bg='pink', fg='black',command=confir_quitter)
    bounon=Button(fenqui,text="Non", bg='pink', fg='black',command=continu_prog)
    bououi.place(x=40,y=25)
    bounon.place(x=120,y=25)
    fenqui.grab_set()

def confir_quitter() :
    fen1.destroy()

def continu_prog() :
    global fenqui
    fenqui.destroy()

def sauvegarde() :
    global indsauv
    if indsauv =='N' :
        indsauv='O'
        labsau1.configure(text='Avec sauvegarde',fg='black')
        bosav.config(text='Sans',bg='SeaGreen4', fg='white')
    else :
        indsauv='N'
        labsau1.configure(text='Sans sauvegarde',fg='grey50')
        bosav.config(text='Avec',bg='firebrick4', fg='white')

def effacer_vues() :
    for widget in fen1.winfo_children(): 
        if isinstance(widget,Toplevel): 
            widget.destroy() 
    boeff.config(text="",bg='SlateGray2',state=DISABLED,relief=FLAT)
    
def close_window() :
    if tkMessageBox.askokcancel :
        quitter_prog()
    
# main
fen1 = Tk(className=" CompactImages   v_2,1")
fen1.protocol("WM_DELETE_WINDOW", close_window)
fen1.tk_setPalette(background = 'SlateGray2')
fen1.geometry("500x800+550+100")
fen1.resizable(width=False, height=False)
can1 = Canvas(fen1, width=20, height=20, bg='lightgrey')
signat=PhotoImage(file='YLC.gif')
sign=can1.create_image(12,12, image=signat)
can1.pack(side=BOTTOM,anchor=E)

fram1=Frame(fen1,borderwidth=0)
button2 = Button(fram1, text = 'Répertoire',bg='snow', command = Exploration)
button2.grid(row=0,column=0,pady=20)
boutau=Button(fram1,text=" Niveau "+'% d' %taux, bg='green', fg='black',command=Modif_Taux)
boutau.grid(row=0,column=1,padx=30)
bouinf=Button(fram1,text="Information", bg="seagreen4", fg='yellow',command=Affich_Infos)
bouinf.grid(row=0,column=2,padx=30)
bouf1=Button(fram1,text="Quitter", command=quitter_prog,bg='salmon', fg='black')
bouf1.grid(row=0,column=3)
labsau1=Label(fram1,text='Sans sauvegarde', fg='grey50', font=('Arial',11))
labsau1.grid(row=1,column=0)
bosav=Button(fram1,text="Avec", command=sauvegarde,bg='firebrick4', fg='white')
bosav.grid(row=1,column=1)
boeff=Button(fram1,text="",command=effacer_vues,state=DISABLED,relief=FLAT)
boeff.grid(row=1,column=3)
fram1.pack(side=TOP)

fram2=Frame(fen1,borderwidth=0)
labbid1=Label(fram2,text='')
labbid1.pack(side=TOP)
lab1=Label(fram2,text='Liste des images (Jpg ou Jpeg) à comprimer', fg='blue', font=('Arial', 12))
lab1.pack()
lab1b=Label(fram2,text='(Cliquer sur une ligne pour voir l''image)', fg='black', font=('Arial', 9))
lab1b.pack()
scrolly =Scrollbar(fram2,orient=VERTICAL)
list1 = Listbox(fram2,bg="SlateGray1",width=70,height=31,selectmode='single', yscrollcommand=scrolly.set)
scrolly.config(command  =  list1.yview)
scrolly.pack(side=LEFT,fill=Y)
list1.pack()
fram2.pack()

fram3=Frame(fen1)
lab3=Label(fram3,fg='blue',font=('Arial', 9))
lab3.grid(row=0,column=1,padx=5)
lab2=Label(fram3,fg='blue',font=('Arial', 9))
lab2.grid(row=0,column=0,padx=15)
lab3a=Label(fram3,fg='red',font=('Arial', 9))
lab3a.grid(row=1,column=0,padx=5)
button1 = Button(fram3, text = '', command = Validation,state=DISABLED,relief=FLAT)
button1.grid(row=1,column=1,padx=35,pady=5)
fram3.pack()

fram5=Frame(fen1)
lab4=Label(fram5,fg='black', font=('Arial', 10))
lab4.grid(row=0,column=0,pady=5)
lab5=Label(fram5,fg='blue', font=('Arial', 9))
lab5.grid(row=0,column=1,sticky=W)
lab6=Label(fram5,fg='blue', font=('Arial', 9))
lab6.grid(row=1,column=0)
lab7=Label(fram5,fg='red', font=('Arial', 9))
lab7.grid(row=1,column=1)
lab8=Label(fram5,fg='red', font=('Arial', 10))
lab8.grid(row=2,column=0,sticky=W)
lab9=Label(fram5,fg='black', font=('Arial', 9))
lab9.grid(row=3,column=0)
fram5.pack()

fen1.mainloop()


 Conclusion

C'est à vous de la donner ; moi, je trouve ça très pratique.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

11 décembre 2007 19:18:01 :
En travaillant sur des répertoire de plusieurs centaines de photos, je trouvais le temps long et ne savais pas où le traitement en était rendu. J'ai donc ajouté une barre de progression (avec TIX). Attention à la compile sous windows avec py2exe, il manque les DLL Tix dans python 2.5 à récupérer à cette adresse: http://python.developpez.com/faq/?page=TkinterPrerequis (Merci à Guillaume Duriaud) Il faut aussi modifier le setup.py : voir à cette adresse: http://www.py2exe.org/index.cgi/TixSetup
15 novembre 2008 10:44:14 :
Nouvelle version améliorée
21 novembre 2008 16:49:14 :
J'avais oublié de joindre l'image YLC.gif à mon Zip. C'est fait.
28 novembre 2008 09:54:23 :
Juste une petite adaptation des dimensions des fenêtres d'affichage des fignettes aux images affichées.
28 novembre 2008 09:58:22 :
Amélioration de la dimension de la fenêtre des vignettes aux images affichées. (fonction Affiche_image1)

 Sources du même auteur

Source avec Zip Source avec une capture RENOMMEUR DE FICHIERS PAR LOTS
Source avec Zip Source avec une capture HORLOGE-CHRONOMÈTRE-RÉVEIL
Source avec Zip Source avec une capture BIBLIO : GESTIONNAIRE DE BIBLIOTHÈQUE
Source avec Zip REPERT V1.4 (REPERTOIRE D'ADRESSES, TÉLÉPHONES ET MAILS)

 Sources de la même categorie

Source avec une capture RECHERCHE DE DOUBLONS DANS DES DOSSIERS. par Rano Its
Source avec Zip Source avec une capture ILLUSTRATION DE SINUS ET DE COSINUS par calogerogigante
Source avec Zip Source avec une capture LE MOT LE PLUS LONG PAR DICO par Clempython
Source avec Zip Source avec une capture EQUATION STANDARD DE LA DROITE par calogerogigante
Source avec Zip Source avec une capture RENOMMEUR DE FICHIERS PAR LOTS par yveslc

 Sources en rapport avec celle ci

Source avec une capture PREVIEW AVEC MPLAYER par mumupy
Source avec Zip Source avec une capture ALBUMEUR PHOTO: SCRIPT DE CRÉATION D'ALBUM PHOTO EN HTML À P... par vychnou
Source avec Zip COMPRESSION PAR LA METHODE DE HUFFMAN par Bl0tCh
Source avec Zip COMPRESSION ZIP ET CGI par Ulala2

Commentaires et avis

Commentaire de Lapou le 11/06/2008 12:57:52

Bonjour,

Cette "outil" m'intéresse fortement sauf que je ne parviens pas à le faire tourner, il semble que j'ai un problème avec PIL qui ne serait pas reconnu !
Pourriez-vous m'aider ou même mettre à dispo l'exécutable windows :-)

Merciiiiiiiiiiiiiiiiii

Commentaire de yveslc le 12/06/2008 09:24:46

Bonjour lapou,
Encore faut-il télécharger la bibliothèque PIL pour l'utiliser. Pour avoir un package Windows, je n'ai jamais trouvé de site où les mettre. Si tu en connais un qui accepte d'uploader un gros ZIP indique le-moi. merci.
YLC

Commentaire de Lapou le 12/06/2008 13:45:42

merci yveslc :-) je ne connais pas du tout pyhon donc j'ai eu la flemme de chercher !

Merci

Commentaire de Lapou le 12/06/2008 16:33:49 9/10

Bon ça y'est j'ai réussi pour TIL ainsi que pour la progressbar :-)

Cela fonctionne en utilisant le CompactImages.py.
Je créer donc l'exécutable avec py2exe, et quand je lance le CompactImages.exe dans dist j'ai l'invite de commande pendant 1sec puis il disparait mais pas d'action !

Merci de votre aide.

Commentaire de yveslc le 13/06/2008 14:33:29

Bonjour,
as-tu pensé à mettre le fichier YLC.gif dans le répertoire où se trouve ton exécutable ?

Commentaire de Lapou le 16/06/2008 09:48:38

Bonjour,

Effectivemment c'était bien cela !
Je n'avais pas vu que le fichier ne s'était pas mis dans le dossier avec la création avec py2exe !

Merci,
@+

Commentaire de Lapou le 16/06/2008 09:54:11

Re Yves,

Et donc logiquement je n'ai plus qu'à copier le dossier dist sur d'autres PC pour pouvoir utiliser ce magnifique outil ?

Merci
@+

Commentaire de Lapou le 16/06/2008 14:20:10

Re salut à tous !

Je vous conseille vraiement cette source, yslc a vraiement fait un super boulot !!!
La prochaine évolutions serait peut-être de pouvoir sélectionner plusieurs dossiers ? Car quand on a "cumulé" des dizaines de dossiers de photos, il n'y a pas d'autres possibilités que de lancer la source dossier par dossier,...
Puis il serait peut-être intéressant d'avoir la possibilité d'inclure les sous-dossiers ou pas (au choix via une checkbox par exemple) ?

Qu'en pensez-vous ?  N'ayant aucune connaissance en Python, voir même dans d'autres langages (oups), je suis incapable de réaliser ces évol' !

Par avance merci,
@+

Commentaire de yveslc le 17/06/2008 08:37:27

Bonjour,
Effectivement c'est une possibilité, bien que si on s'organise bien ce n'est pas nécéssaire. Je m'explique : quand je remonte des photos sur mon ordi, je passe systématiquement par un dossier de travail sur lequel j'applique le compactage et que je reprend ensuite dans Picassa pour ventiler mes photos dans les dossiers destinataires finaux.
De toutes façons, je n'écris pas de code à la belle saison, c'est pour passer l'hiver, quand on ne peut pas beaucoup sortir faire du vélo ou de la rando.....
A+
YLC
PS : j'aurais aimé (pour ceux qui ne connaissent pas Python) pouvoir mettre la librairie exécutable sous Windows sur le net, mais je n'ai pas trouvé de site qui propose de téléchager des appli toutes faites.

Commentaire de pil91 le 17/11/2008 09:41:49 8/10

Bonjour,
merci pour ce code Python qui est très didactique.
Je ne comprend pas bien ton problème d'upload d'exécutable. Tu peux probablement créer ton espace web chez ton fournisseur et mettre à disposition de tout le monde ce que tu souhaites, alternativement sur SourceForge tu peux faire un dépôt.

Encore merci pour tes contributions.

Commentaire de Lapou le 03/12/2008 16:34:43

Salut !!!

Toujours aussi parfait :-)

@+

Commentaire de yveslc le 03/12/2008 19:00:41

Bonjour,
Ca y est, j'ai enfin mis le code exécutable pour Windows (en compilé) de ce programme sur mon site Web à cette adresse :

     http://pigments.e-monsite.com/blog.html

....pour ceusses que ça intéresse !.....
YLC

Commentaire de lpi_info le 16/01/2009 22:52:55

Bonjour je viens de decouvrir ton site et vraiment j apprecie ce que vous a fait, c'est pas du tout facile d inventé les choses. j ai decouvert ton site juste par hazard lors de la recherche du principe du la compression JPEG sur l image,autrement dit c'est quoi la particularité d une image qui a subi une forte compression. il est bien entendu qu on voit des effets de bloque(des artefacts) mais moi mon travail consiste a programmer un detecteur sur matlab qui peut detecter ce defaut de compression sur une image donné, c a d si je teste mon programme avec cette image il doit me renvoié une valeur par exemple 100 ç a d que l image a ce defaut de forte compression, mais je connais pas le critere sur quoi va se basé mon algo! vraiment si vous pouvé m aidé je serai ravi!! merci et desolé pour le derangement!bonne soiree

Commentaire de yveslc le 17/01/2009 09:32:55

Bonjour,LPI_INFO,
Tout d'abord, en Jpeg, la compression est inversement proportionnelle au facteur de compression indiqué. Ainsi 100 indique une image sans compression alors que 40 indique une image très (trop) fortement comprimée. Les algos de compression sont très complexes, à base de transformée DCT puis de quantification. Pour en savoir plus je te renvoie au wiki : http://fr.wikipedia.org/wiki/Norme_JPEG  
Bon courage.
YLC

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Compression d'images en lignes de commande - Python [ par Elninor ] Bonsoir, j'ai cherché sur tous les sites possibles (francophone et anglophone) mais je n'ai rien trouvé. Je recherche quelques lignes de commande perm PIL, erreur lors de l'ouverture d'une image :/ [ par rezuz ] bonjour, j'utilise la bibliothèque PIL pour modifier des images, notament la taille. mais lorsque je lance le script et avant d'afficher les images, Erreur avec PIL [ par elnabo ] Bonjour, ayant récemment acheter un nouvel ordinateur (avec Seven Pro), j'ai voulu réinstaller Python et reprendre/améliorer certain de mes programme wxpython : afficher et effacer des images [ par steede ] Bonjour,J'ai besoin dans mon application d'affiicher des images et de les remplacer par d'autres en fonction des clics de la souris.Je sais les affich erreurs video [ par ktamine ] bonjour &#233;tudiante en arts plastiques, je travaille autour de l&#146;esth&#233;tique de l&#146;erreur et des donn&#233;es corrompues (d&#146;image Compression de fichier :Winzip et 7zip [ par HCD ] Bonjour à tousCe qui suit s'adresse aux administrateurs du site.Lorsque l'on ajoute une nouvelle source sur le site, le fichier compressé doir comport affichage des images sur python [ par amina22 ] salut,je sais qu'on peut afficher les images .gif avec python mais je veux savoir si on peut afficher les images(jpeg,jpg,..)  et les vidéos si oui et Cacher une image [ par akkuciha ] Bonjour à tous, Le but de mon application est de trouver l'image "Question" parmis les images "réponses" possibles.J'ai une zone d'image faite avec gl Canvas, scrollbar et images [ par linkid ] Bonjour,Je suis en train de faire une petite application en python et j'ai un petit problème avec les Canvas... (j'utilise Tkinter pour l'interface)(1 Problème avec draw.text du module PIL [ par MasterID ]


Nos sponsors


Sondage...

CalendriCode

Septembre 2010
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
27282930   

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,936 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales