Accueil > > > COMPACTEUR D'IMAGES JPEG PAR LOT
COMPACTEUR D'IMAGES JPEG PAR LOT
Information sur la source
Description
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.
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
Sources de la même categorie
Commentaires et avis
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
Zip images et mime type [ par DjChat ]
Bonjours a tous, j'ai une page de mon site où on peux sélectionner des images, j'aimerai que quand l'utilisateur click sur un submit, que je lui propo
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 étudiante en arts plastiques, je travaille autour de l’esthétique de l’erreur et des données corrompues (d’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
|
Derniers Blogs
TECHDAYS PARIS 2012 : COMMENT SHAREPOINT A SAUVé MES TECHDAYSTECHDAYS PARIS 2012 : COMMENT SHAREPOINT A SAUVé MES TECHDAYS par ROMELARD Fabrice
Speakers : Lionel Limozin et Alain Marty La session commence par une découverte de SharePoint à travers la mise en place d'un environnement SharePoint pour la gestion des Sessions animées par BeWise. Le besoin est très ba...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice PERSPECTIVE 3.0 POUR SILVERLIGHT 5.0PERSPECTIVE 3.0 POUR SILVERLIGHT 5.0 par odewit
Je viens de publier la version 3.0 de Perspective pour Silverlight, qui regroupe un portage sous Silverlight 5.0 des fonctionnalités de Perspective 2.0, le framework 3D de haut-niveau introduit récemment et de nouveaux exemples de code. En voici la li...
Cliquez pour lire la suite de l'article par odewit TECHDAYS PARIS 2012 : TOP 10 DES BEST PRACTICES POUR SQL SERVERTECHDAYS PARIS 2012 : TOP 10 DES BEST PRACTICES POUR SQL SERVER par ROMELARD Fabrice
Speaker : Nadia Ben El Kadi Configuration machine La session commence par la toute première question à se poser lors de la mise en place d'environnement SQL Server, la configuration des machines : Type de mac...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice TECHDAYS PARIS 2012 : KINECT + OFFICE 365 UN BON GESTE POUR VOTRE SITECHDAYS PARIS 2012 : KINECT + OFFICE 365 UN BON GESTE POUR VOTRE SI par ROMELARD Fabrice
Speakers : Fabrice Barbin, Samuel Blanchard, Julien Lo Presti Titre Prometteur et attractif invitant à voir comment lier le composant ludique Kinect dans le cadre d'une structure IT classique, notamment au travers de la plat...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice TECHDAYS PARIS 2012 : PLEINIèRE DU PREMIER JOURTECHDAYS PARIS 2012 : PLEINIèRE DU PREMIER JOUR par ROMELARD Fabrice
KeyNotes du premier jour pour les développeurs. La session est principalement axée sur une des principales directions prise par Microsoft à travers tous ses nouveaux produits : Cloud privé ou public (Solution Azure) ...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Forum
PYVISA PROBLèMEPYVISA PROBLèME par sandrine44
Cliquez pour lire la suite par sandrine44
Logiciels
Academy System (17.2.1.0)ACADEMY SYSTEM (17.2.1.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System Easy-Planning (1.0.0.1)EASY-PLANNING (1.0.0.1)Basé sur les mêmes principes que MyPlanning, Easy-Planning permet de créer des plannings sous la ... Cliquez pour télécharger Easy-Planning COLLECTOR PLUS (3.00B)COLLECTOR PLUS (3.00B)COLLECTOR PLUS version 3.00B est un logiciel utilisant une base de données alimentée par :
- L... Cliquez pour télécharger COLLECTOR PLUS PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA TV DEVIENS HELLLOOO FLASH
LA TV SUR VOTRE ORDINATEUR.
Toute une plateforme Multi... Cliquez pour télécharger PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO LettresFaciles 2011 (8.0.0.1)LETTRESFACILES 2011 (8.0.0.1)LettresFaciles est un logiciel facilitant la création et la rédaction de lettres types.
Son inte... Cliquez pour télécharger LettresFaciles 2011
|