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
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
Problème avec draw.text du module PIL [ par MasterID ]
|
Derniers Blogs
ENUMERABLECOLLECTIONENUMERABLECOLLECTION par Matthieu MEZIL
Prenons le scénario suivant. On utilise MVVM. On a les deux classes suivantes dans le model : public class Child { } public class Parent { private ObservableCollection < Child > _children; public ObservableCollection < Child > Children { get {...
Cliquez pour lire la suite de l'article par Matthieu MEZIL [HS] CHROME 6 + MOI = COUP DE GUEULE ![HS] CHROME 6 + MOI = COUP DE GUEULE ! par JeremyJeanson
Attention, le poste qui suit n'est pas la complainte d'une personne : Qui n'aime pas Chrome. D'un anti Google. D'un développeur qui a un poil énorme dans la main. Ceux qui me fréquentent savent que je change de navigateur favori tous les 2 ou 3 mois afin ...
Cliquez pour lire la suite de l'article par JeremyJeanson [WP7] UTILISER UN WRAPPANEL DANS UNE APPLICATION WINDOWS PHONE 7[WP7] UTILISER UN WRAPPANEL DANS UNE APPLICATION WINDOWS PHONE 7 par Audrey
Lors de la réalisation de ma 2ème application Windows Phone 7, j'ai souhaité utiliser un WrapPanel pour afficher plusieurs photos. Mais le contrôle WrapPanel ne fait pas parti de la liste des contrôles inclus dans le SDK de la version Beta des outils pour...
Cliquez pour lire la suite de l'article par Audrey [WP7] BESOIN D'AVOIR DES DONNéES EN CACHE[WP7] BESOIN D'AVOIR DES DONNéES EN CACHE par Nicolas
Les développeurs ASP.NET ont l'habitude de mettre des données en cache pour éviter de requêter a chaque fois la base de données. Et il est toujours utilie de penser que vos utilisateurs mobiles n'ont pas troujours une super connexion 3G/WIFI et un for...
Cliquez pour lire la suite de l'article par Nicolas [TFS] COMMENT FORCER LA SAISIE D'UN AREA OU ITERATION[TFS] COMMENT FORCER LA SAISIE D'UN AREA OU ITERATION par cyril
Lorsque l'on créé un Work Item dans TFS, il est possible de le classer dans un "area" et dans une "iteration". Dans la plupart des types de projet, un "area" correspond à une catégorie, une "iteration" à un numéro de version. Il est possible de cré...
Cliquez pour lire la suite de l'article par cyril
Forum
RE : PYTHON 3.0RE : PYTHON 3.0 par aera group
Cliquez pour lire la suite par aera group RE : PYTHON 3.0RE : PYTHON 3.0 par xeolin
Cliquez pour lire la suite par xeolin RE : PYTHON 3.0RE : PYTHON 3.0 par aera group
Cliquez pour lire la suite par aera group
Logiciels
uTorrent (2.0.4)UTORRENT (2.0.4)C'est un client BitTorrent très puissant et très performant. Comme son nom l'indique, uTorrent (m... Cliquez pour télécharger uTorrent Bureau de Gestion - ERP Devis Facturation (2.02)BUREAU DE GESTION - ERP DEVIS FACTURATION (2.02)- Version gratuite du 10/06/2010
Le Bureau de Gestion est un logiciel dédié à la gestion de l'en... Cliquez pour télécharger Bureau de Gestion - ERP Devis Facturation 4Videosoft Transfert iPod Mac (3.2.08)4VIDEOSOFT TRANSFERT IPOD MAC (3.2.08)4Videosoft Transfert iPod-Mac caractérise principalement à transférer les fichiers iPod vers Mac.... Cliquez pour télécharger 4Videosoft Transfert iPod Mac 4Videosoft HD Convertisseur (3.3.08)4VIDEOSOFT HD CONVERTISSEUR (3.3.08)Etant le meilleur HD Vidéo Convertisseur, 4Videosoft HD Convertisseur, vous pouvez regarder la vi... Cliquez pour télécharger 4Videosoft HD Convertisseur 4Videosoft Transfert iPad Mac (3.2.08)4VIDEOSOFT TRANSFERT IPAD MAC (3.2.08)4Videosoft Transfert iPad-Mac est un logiciel managérial iPad professionnel qui a des fonctions i... Cliquez pour télécharger 4Videosoft Transfert iPad Mac
|