ImageVonc.py
import os import sys import wx import wx.animate import wx.lib.platebtn as btnplat import shutil import random import PIL import struct as st from PIL import Image as PILImage from PIL import ImageTk from PIL.ExifTags import TAGS class DialogueInfos(wx.Dialog) : FENETRE = None exif = None def dicoTexte(val) : try : return unicode(val) except UnicodeDecodeError : print val return "" def dicoCommentaire(val) : return str(len(val)) + u" caractères à décoder." def dicoDate(val) : val = val.split(" ") date = val[0].split(":") heure = val[1].split(":") retour = date[2] + "/" + date[1] + "/" + date[0] + " " + heure[0] + ":" + heure[1] + ":" + heure[2][0] + heure[2][1] return retour def dicoVide(val) : return "" dicoMeta = { '36864' : ['ExifVersion', u'Version Exif', dicoTexte], '37121' : ['ComponentsConfiguration', u'Composants de configuration', dicoVide], '37122' : ['CompressedBitsPerPixel', u'Compression octet par pixel', dicoTexte], '36867' : ['DateTimeOriginal', u'Date et heure d\'origine', dicoDate], '36868' : ['DateTimeDigitized', u'Date et heure numérisés', dicoDate], '37381' : ['MaxApertureValue', u'Ouverture max', dicoTexte], '40960' : ['FlashPixVersion', u'Version de FlashPix', dicoTexte], '37383' : ['MeteringMode', u'', dicoTexte], '37384' : ['LightSource', u'Source de lumière', dicoTexte], '37385' : ['Flash', u'Flash', dicoTexte], '37386' : ['FocalLength', u'Distance focale', dicoTexte], '41996' : ['41996', u'41996', dicoTexte], '37378' : ['ApertureValue', u'Ouverture', dicoTexte], '41486' : ['FocalPlaneXResolution', u'Hauteur du foyer', dicoTexte], '271' : ['Make', u'Marque', dicoTexte], '272' : ['Model', u'Modèle', dicoTexte], '274' : ['Orientation', u'Orientation', dicoTexte], '531' : ['YCbCrPositioning', u'', dicoTexte], '41495' : ['SensingMethod', u'', dicoTexte], '33432' : ['Copyright', u'Tous droits réservés', dicoTexte], '282' : ['XResolution', u'Résolution X', dicoTexte], '283' : ['YResolution', u'Résolution Y', dicoTexte], '33434' : ['ExposureTime', u'Durée d\exposition', dicoTexte], '41728' : ['FileSource', u'', dicoVide], '40965' : ['ExifInteroperabilityOffset', u'', dicoTexte], '34850' : ['ExposureProgram', u'Programme d\'exposition', dicoTexte], '40961' : ['ColorSpace', u'Espace colorimétrique', dicoTexte], '41990' : ['41990', u'', dicoTexte], '34855' : ['ISOSpeedRatings', u'ISO', dicoTexte], '296' : ['ResolutionUnit', u'Unité de la résolution', dicoTexte], '41987' : ['41987', u'', dicoTexte], '33437' : ['FNumber', u'Indice d\'ouverture (F)', dicoTexte], '305' : ['Software', u'Logiciel', dicoTexte], '306' : ['DateTime', u'Date et heure', dicoDate], '41729' : ['SceneType', u'Type de scène', dicoVide], '41994' : ['41994', u'', dicoTexte], '40962' : ['ExifImageWidth', u'Largeur en pixels', dicoTexte], '41985' : ['41985', u'', dicoTexte], '41487' : ['FocalPlaneYResolution', u'Largeur du foyer', dicoTexte], '40963' : ['ExifImageHeight', u'Hauteur en pixels', dicoTexte], '41488' : ['FocalPlaneResolutionUnit', u'Résolution du foyer', dicoTexte], '41986' : ['41986', u'', dicoTexte], '34665' : ['ExifOffset', u'', dicoTexte], '37500' : ['MakerNote', u'', dicoVide], '37510' : ['UserComment', u'Commentaire', dicoCommentaire], '40092' : ['40092', u'', dicoTexte], '40091' : ['40091', u'', dicoTexte], '270' : ['ImageDescription', u'Description', dicoTexte], '41992' : ['41992', u'', dicoTexte], '41988' : ['41988', u'', dicoTexte], '41991' : ['41991', u'', dicoTexte], '41993' : ['41993', u'', dicoTexte], '41989' : ['41989', u'', dicoTexte], '256' : ['ImageWidth', u'Largeur', dicoTexte], '257' : ['ImageLength', u'Hauteur', dicoTexte], '258' : ['BitsPerSample', u'Bits par échantillon', dicoTexte], '259' : ['Compression', u'Compression', dicoTexte], '37520' : ['SubsecTime', u'Sous-seconde', dicoTexte], '37521' : ['SubsecTimeOriginal', u'Sous-seconde d\'origine', dicoTexte], '262' : ['PhotometricInterpretation', u'Interprétation photométrique', dicoTexte], '277' : ['SamplesPerPixel', u'Échantillons par pixel', dicoTexte], '284' : ['PlanarConfiguration', u'Configuration planaire', dicoTexte], '37382' : ['SubjectDistance', u'Distance du sujet', dicoTexte], '37522' : ['SubsecTimeDigitized', u'Sous-seconde numérisée', dicoTexte], '34853' : ['GPSInfo', u'Infos GPS', dicoTexte], '315' : ['Artist', u'Artiste', dicoTexte], '41730' : ['CFAPattern', u'', dicoTexte], '42034' : ['42034', u'', dicoTexte], '42033' : ['42033', u'', dicoTexte], '50341' : ['50341', u'', dicoTexte], '42032' : ['42032', u'', dicoTexte], '42036' : ['Lens', u'Objectif', dicoTexte], '34866' : ['34866', u'', dicoTexte], '34864' : ['34864', u'', dicoTexte], '42037' : ['42037', u'', dicoTexte], '529' : ['YCbCrCoefficients', u'', dicoTexte], '42240' : ['42240', u'', dicoTexte], '318' : ['WhitePoint', u'Point blanc', dicoTexte], '319' : ['PrimaryChromaticities', u'', dicoTexte], '' : ['', u'', dicoTexte] } def __init__(self, parent, pos=(-1,-1)): wx.Dialog.__init__(self, parent, pos=pos) self.FENETRE = parent self.exif = parent.exif self.InitInterface() self.SetSize((400, 670)) self.SetTitle(u"Informations") self.style = wx.NO_BORDER def InitBouton(self, txt="", gros=False) : btn = btnplat.PlateButton(self.panneau, wx.ID_ANY, txt, None, style=btnplat.PB_STYLE_SQUARE) if gros == 1 : btn.SetFont(wx.Font(15, wx.MODERN, wx.NORMAL, wx.BOLD)) elif gros == 2 : btn.SetFont(wx.Font(10, wx.MODERN, wx.NORMAL, wx.BOLD)) elif gros == -1 : btn.SetFont(wx.Font(9, wx.MODERN, wx.NORMAL, wx.BOLD)) else : btn.SetFont(wx.Font(8, wx.FONTFAMILY_SWISS, wx.NORMAL, wx.NORMAL)) btn.SetLabelColor(wx.Colour(230, 230, 230)) btn.SetPressColor(wx.Colour(40, 40, 40)) btn.SetBackgroundColour(wx.Colour(20, 20, 20)) return btn def InitInterface(self): self.panneau = wx.Panel(self) self.boite = wx.GridBagSizer() gros = wx.Font(15, wx.MODERN, wx.NORMAL, wx.BOLD) self.panneau.SetBackgroundColour(wx.Colour(20, 20, 20)) btnGauche = self.InitBouton(u' ◄ ', 1) self.boite.Add(btnGauche, (0,0), (1,1), wx.ALIGN_CENTER) btnGauche.Bind(wx.EVT_BUTTON, self.eveBtnGauche) self.texte = wx.TextCtrl(self.panneau, size=(-1,600), style=wx.NO_BORDER|wx.TE_MULTILINE) self.boite.Add(self.texte, (1,0), (1,1), wx.EXPAND|wx.ALL, border=5) self.texte.SetBackgroundColour(wx.Colour(40, 40, 40)) self.texte.SetForegroundColour(wx.Colour(230, 230, 230)) self.TraitementMeta() self.boite.AddGrowableCol(0) self.boite.AddGrowableCol(1) # self.boite.AddGrowableRow(0) wx.EVT_CLOSE(self, self.eveFerme) self.panneau.SetSizer(self.boite) self.Layout() def TraitementMeta(self) : exif = self.exif if not exif : self.texte.Value = 'Aucune information EXIF.' return liste = [] self.texte.Value = "" i = 1 for clef, valeur in exif.items(): if not str(clef) in self.dicoMeta : print clef, TAGS.get(clef, clef), valeur continue motdic = TAGS.get(clef, clef) motdic = self.dicoMeta[str(clef)] if motdic[1] == '' : mot = "***" + motdic[0] else : mot = motdic[1] fnc = motdic[2] ti = str(i) if i < 10 : ti = "0" + str(i) entree = ti + ". " + mot + " : " + fnc(valeur) liste.append(entree) i += 1 imax = len(liste) liste.sort() liste = '\n'.join(liste) self.texte.Value = liste + "\n" + str(imax) # print ''.join(liste) # return '' def eveBtnGauche(self, eve) : pass def eveFerme(self, eve) : self.Destroy() class Dialogue(wx.Dialog) : FENETRE = None verrsuppr = False plus = False def __init__(self, parent, pos): wx.Dialog.__init__(self, parent, pos=pos) self.FENETRE = parent self.InitInterface() self.SetSize((208, 135)) self.SetTitle(u"Contrôle") self.style = wx.NO_BORDER def InitBouton(self, txt="", gros=False, coul=[0,0,0]) : btn = btnplat.PlateButton(self.panneau, wx.ID_ANY, txt, None, style=btnplat.PB_STYLE_SQUARE) if gros == 1 : btn.SetFont(wx.Font(15, wx.MODERN, wx.NORMAL, wx.BOLD)) elif gros == 2 : btn.SetFont(wx.Font(10, wx.MODERN, wx.NORMAL, wx.BOLD)) elif gros == -1 : btn.SetFont(wx.Font(9, wx.MODERN, wx.NORMAL, wx.BOLD)) else : btn.SetFont(wx.Font(8, wx.FONTFAMILY_SWISS, wx.NORMAL, wx.NORMAL)) if coul[0] == 0 : btn.SetLabelColor(wx.Colour(230, 230, 230)) if coul[1] == 0 : btn.SetPressColor(wx.Colour(40, 40, 40)) if coul[2] == 0 : btn.SetBackgroundColour(wx.Colour(20, 20, 20)) elif coul[2] == 1 : btn.SetBackgroundColour(wx.Colour(40, 40, 40)) elif coul[2] == 2: btn.SetBackgroundColour(wx.Colour(100, 20, 20)) return btn def InitInterface(self): self.panneau = wx.Panel(self) self.boite = wx.GridBagSizer() gros = wx.Font(15, wx.MODERN, wx.NORMAL, wx.BOLD) self.panneau.SetBackgroundColour(wx.Colour(20, 20, 20)) btnGauche = self.InitBouton(u' ◄ ', 1) self.boite.Add(btnGauche, (0,0), (1,1), wx.EXPAND) btnGauche.Bind(wx.EVT_BUTTON, self.eveBtnGauche) btnDroite = self.InitBouton(u' ► ', 1) self.boite.Add(btnDroite, (0,1), (1,1), wx.EXPAND) btnDroite.Bind(wx.EVT_BUTTON, self.eveBtnDroite) btnZoomM = self.InitBouton(' - ', 2) self.boite.Add(btnZoomM, (1,0), (1,1), wx.EXPAND) btnZoomM.Bind(wx.EVT_BUTTON, self.eveBtnZoomM) btnZoomP = self.InitBouton(' + ', 2) self.boite.Add(btnZoomP, (1,1), (1,1), wx.EXPAND) btnZoomP.Bind(wx.EVT_BUTTON, self.eveBtnZoomP) btnTaille = self.InitBouton(u' Ajuster la taille ') self.boite.Add(btnTaille, (2,0), (1,1), wx.EXPAND) btnTaille.Bind(wx.EVT_BUTTON, self.eveBtnTaille) btnPleinEcran = self.InitBouton(u' Plein écran ') self.boite.Add(btnPleinEcran, (2,1), (1,1), wx.EXPAND) btnPleinEcran.Bind(wx.EVT_BUTTON, self.eveBtnPleinEcran) self.btnSupprimer = self.InitBouton(u' Supprimer ') self.boite.Add(self.btnSupprimer, (3,0), (1,1), wx.EXPAND) self.btnSupprimer.Bind(wx.EVT_BUTTON, self.eveBtnSuppr) if self.verrsuppr : self.btnSupprimer.SetBackgroundColour(wx.Colour(100, 20, 20)) btnFermer = self.InitBouton(u' Quitter ') self.boite.Add(btnFermer, (3,1), (1,1), wx.EXPAND) btnFermer.Bind(wx.EVT_BUTTON, self.eveBtnFermer) btnPlus = self.InitBouton(u' ... ', -1, [0,0,1]) self.boite.Add(btnPlus, (4,0), (1,2), wx.EXPAND) btnPlus.Bind(wx.EVT_BUTTON, self.eveBtnPlus) btnPlus.SetLabelColor(wx.Colour(100, 100, 100)) btnVerrSuppr = self.InitBouton(u' Suppr. directe ') self.boite.Add(btnVerrSuppr, (5,0), (1,1), wx.EXPAND) btnVerrSuppr.Bind(wx.EVT_BUTTON, self.eveBtnVerrSuppr) btnInfos = self.InitBouton(u' Infos ') self.boite.Add(btnInfos, (5,1), (1,1), wx.EXPAND) btnInfos.Bind(wx.EVT_BUTTON, self.eveBtnInfos) self.btnFond = self.InitBouton(u' Fond ') self.boite.Add(self.btnFond, (6,0), (1,1), wx.EXPAND) self.btnFond.Bind(wx.EVT_BUTTON, self.eveBtnFond) self.eveBtnFond(None, False) self.btnExif = self.InitBouton(u' Utiliser EXIF ') self.boite.Add(self.btnExif, (6,1), (1,1), wx.EXPAND) self.btnExif.Bind(wx.EVT_BUTTON, self.eveBtnExif) if self.FENETRE.verrexif : self.btnExif.SetBackgroundColour(wx.Colour(100, 20, 20)) self.btnAleat = self.InitBouton(u' Aléatoire') self.boite.Add(self.btnAleat, (7,0), (1,1), wx.EXPAND) self.btnAleat.Bind(wx.EVT_BUTTON, self.eveBtnAleat) if self.FENETRE.verraleat : self.btnAleat.SetBackgroundColour(wx.Colour(100, 20, 20)) self.btnFigzo = self.InitBouton(u' Figer le zoom') self.boite.Add(self.btnFigzo, (7,1), (1,1), wx.EXPAND) self.btnFigzo.Bind(wx.EVT_BUTTON, self.eveBtnFigzo) if self.FENETRE.verrzoom : self.btnFigzo.SetBackgroundColour(wx.Colour(100, 20, 20)) btnEnr = self.InitBouton(u' Exporter') self.boite.Add(btnEnr, (8,0), (1,1), wx.EXPAND) btnEnr.Bind(wx.EVT_BUTTON, self.eveBtnEnr) btnEnrLot = self.InitBouton(u' Export par lot') self.boite.Add(btnEnrLot, (8,1), (1,1), wx.EXPAND) btnEnrLot.Bind(wx.EVT_BUTTON, self.eveBtnEnrLot) self.boite.AddGrowableCol(0) self.boite.AddGrowableCol(1) # self.boite.AddGrowableRow(0) wx.EVT_CLOSE(self, self.eveFerme) self.panneau.SetSizer(self.boite) self.Layout() def eveBtnEnrLot(self, eve) : self.FENETRE.ExportLot() def eveBtnEnr(self, eve) : self.FENETRE.Exporter() def eveBtnFigzo(self, eve) : self.FENETRE.verrzoom = not self.FENETRE.verrzoom if self.FENETRE.verrzoom : self.btnFigzo.SetBackgroundColour(wx.Colour(100, 20, 20)) else : self.btnFigzo.SetBackgroundColour(wx.Colour(20, 20, 20)) self.btnFigzo.Refresh() def eveBtnAleat(self, eve) : self.FENETRE.verraleat = not self.FENETRE.verraleat if self.FENETRE.verraleat : self.btnAleat.SetBackgroundColour(wx.Colour(100, 20, 20)) else : self.btnAleat.SetBackgroundColour(wx.Colour(20, 20, 20)) self.btnAleat.Refresh() def eveBtnFond(self, eve, affecter=True) : coul = self.FENETRE.fond if affecter : if coul == 0 : coul = 20 elif coul == 20 : coul = 127 elif coul == 127 : coul = 255 elif coul == 255 : coul = 0 self.FENETRE.ModifFond(coul) self.btnFond.SetBackgroundColour(wx.Colour(coul, coul, coul)) self.btnFond.SetPressColor(wx.Colour(coul, coul, coul)) def eveBtnExif(self, eve, forcer=False) : if not forcer : self.FENETRE.verrexif = not self.FENETRE.verrexif else : self.FENETRE.verrexif = True if self.FENETRE.verrexif : self.btnExif.SetBackgroundColour(wx.Colour(100, 20, 20)) if not self.FENETRE.exif : self.FENETRE.MetaDonnees() else : self.btnExif.SetBackgroundColour(wx.Colour(20, 20, 20)) self.FENETRE.exif = None self.btnExif.Refresh() def eveBtnInfos(self, eve) : if self.FENETRE.DIALINFOS : self.FENETRE.DIALINFOS.Destroy() return self.eveBtnExif(None, True) pos = (wx.DisplaySize()[0] - 420, 20) self.FENETRE.DIALINFOS = DialogueInfos(self.FENETRE, pos) self.FENETRE.DIALINFOS.Show() def eveBtnVerrSuppr(self, eve) : self.verrsuppr = not self.verrsuppr if self.verrsuppr : self.btnSupprimer.SetBackgroundColour(wx.Colour(100, 20, 20)) else : self.btnSupprimer.SetBackgroundColour(wx.Colour(20, 20, 20)) self.btnSupprimer.Refresh() def eveBtnPlus(self, eve) : self.plus = not self.plus if self.plus : self.SetSize((208, 300)) else : self.SetSize((208, 135)) self.Layout() def eveBtnFermer(self, eve) : self.Destroy() self.FENETRE.Destroy() def eveBtnSuppr(self, eve) : self.FENETRE.Supprimer(self.verrsuppr) def eveBtnZoomP(self, eve) : self.FENETRE.AjusteZoom(100) def eveBtnZoomM(self, eve) : self.FENETRE.AjusteZoom(-100) def eveBtnPleinEcran(self, eve) : self.FENETRE.ModePleinEcran() def eveBtnTaille(self, eve) : self.FENETRE.AjusteTaille() def eveBtnGauche(self, eve) : self.FENETRE.Naviguer(-1) def eveBtnDroite(self, eve) : self.FENETRE.Naviguer(1) def eveFerme(self, eve) : self.Destroy() class Fenetre(wx.Frame) : liste = [] listeLong = 0 num = 0 echelle = 1.0 echelleOpt = 1.0 exts = ['bmp', 'gif', 'jpg', 'jpeg', 'png', 'pcx', 'pnm', 'tif', 'xpm', 'ico', 'cur', 'ani', 'tga', 'pix'] bordures = (0, 0) pleinecran = False DIALOGUE = None DIALINFOS = None posImg = (0, 0) posImgDer = (0, 0) exif = None verrexif = False verraleat = False verrzoom = False orientation = 1 fond = 20 image = None def __init__(self, parent, id, title) : wx.Frame.__init__(self, parent, id, title, size=[300, 500]) icone = wx.Icon("icone.ico", wx.BITMAP_TYPE_ICO) self.SetIcon(icone) self.SetBackgroundColour(wx.Colour(self.fond, self.fond, self.fond)) self.panneau = wx.Panel(self, -1, style=0) self.anim = None self.bitmap = wx.EmptyBitmap(1, 1) self.staticbitmap = wx.StaticBitmap(self, bitmap = self.bitmap) self.boite = wx.GridSizer() # self.boite = wx.BoxSizer() self.boite.Add(self.staticbitmap, 0, wx.ALIGN_CENTER | wx.ALL | wx.ADJUST_MINSIZE, 0) self.panneau.Bind(wx.EVT_KEY_DOWN, self.eveClavier) self.panneau.Bind(wx.EVT_MOUSEWHEEL, self.eveSourisMolette) self.panneau.Bind(wx.EVT_RIGHT_UP, self.eveSourisClicDroit) self.panneau.Bind(wx.EVT_MOTION, self.eveSourisBouge) self.panneau.Bind(wx.EVT_LEFT_DOWN, self.eveSourisClicGauche) self.panneau.Bind(wx.EVT_LEFT_UP, self.eveSourisDeclicGauche) self.panneau.Bind(wx.EVT_LEFT_DCLICK, self.eveSourisDoubleClicGauche) self.panneau.Bind(wx.EVT_MIDDLE_DOWN, self.eveSourisClicMilieu) self.SetSizerAndFit(self.boite) # self.panneau.SetSizerAndFit(self.boite) self.Listeur() wx.EVT_CLOSE(self, self.eveFerme) self.Bind(wx.EVT_SIZE, self.eveRecadre) self.Show(True) def eveSourisClicMilieu(self, eve) : self.AjusteTaille() def eveSourisDoubleClicGauche(self, eve) : self.ModePleinEcran() def eveSourisDeclicGauche(self, eve) : self.Update() def eveSourisClicGauche(self, eve) : posImage = self.staticbitmap.GetPosition() posSouris = eve.GetPosition() self.posImgDer = (posSouris[0] - posImage[0], posSouris[1] - posImage[1]) def eveSourisBouge(self, eve) : if eve.LeftIsDown() : posAns = self.posImgDer posSouris = eve.GetPosition() pos = (posSouris[0] - posAns[0], posSouris[1] - posAns[1]) self.staticbitmap.SetPosition(pos) self.Update() def eveSourisClicDroit(self, eve) : if self.DIALOGUE : self.DIALOGUE.Destroy() return posSouris = eve.GetPosition() + self.GetPosition() posSouris[0] -= 104 posSouris[1] += 10 self.DIALOGUE = Dialogue(self, pos=posSouris) self.DIALOGUE.Show() def eveSourisMolette(self, eve) : val = eve.GetWheelRotation() self.AjusteZoom(val) def eveClavier(self, eve) : touche = eve.GetKeyCode() if touche == wx.WXK_LEFT : self.Naviguer(-1) elif touche == wx.WXK_RIGHT : self.Naviguer(1) elif touche == wx.WXK_DELETE : self.Supprimer() def eveRecadre(self, eve) : taille = self.GetSize() self.panneau.SetSize(taille) self.panneau.Layout() def eveFerme(self, eve) : self.Destroy() def ModifFond(self, coul) : self.fond = coul self.SetBackgroundColour(wx.Colour(coul, coul, coul)) self.Refresh() def MetaDonnees(self, lien=None) : if not lien : lien = self.liste[self.num] if not os.path.exists(lien) : return image = PILImage.open(lien) exifbrut = None self.orientation = 1 try : exifbrut = image._getexif() except : pass if exifbrut : try : self.orientation = exifbrut[274] except KeyError : pass self.exif = exifbrut def ExportLot(self) : if not self.image : return if not self.liste : return source = self.liste[self.num] if not source : return dossier = os.path.dirname(source) dossier = os.path.abspath(dossier) dest = wx.DirDialog(self, defaultPath = dossier) retour = dest.ShowModal() if retour == 5101 : return chemin = dest.GetPath() if not chemin : return for i, f in enumerate(self.liste) : self.num = i self.Charger() nom = os.path.basename(f) nom = os.path.splitext(nom)[0] + ".png" chem = os.path.join(chemin, nom) self.image.SaveFile(chem, wx.BITMAP_TYPE_PNG) def Exporter(self) : if not self.image : return if not self.liste : return source = self.liste[self.num] if not source : return dossier = os.path.dirname(source) nom = os.path.basename(source) nom = os.path.splitext(nom)[0] ext = "PNG (*.png)|*.png" selection = wx.FileDialog(self, 'Exporter', defaultDir = dossier, defaultFile = nom, wildcard = ext, style = wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) retour = selection.ShowModal() chemin = selection.GetPath() if not chemin : return self.image.SaveFile(chemin, wx.BITMAP_TYPE_PNG) def Supprimer(self, confirme=False) : if not confirme : if not self.BoiteMessageSuppr() : return poub = os.path.normpath(os.environ['SYSTEMDRIVE'] + r"\\$Recycle.Bin\\") if not os.path.exists(poub) : return corb = os.listdir(poub) if not corb : return corb = os.path.join(poub, corb[0]) if not self.liste : return source = self.liste[self.num] fichier = os.path.basename(source) dest = os.path.join(poub, fichier) # corb, fichier # print source # print corb # print dest # os.system("del " + source) # print os.system("move " + source + " " + corb) shutil.move(source, dest) self.liste.pop(self.num) self.listeLong -= 1 if not self.listeLong : return self.num = self.num % self.listeLong self.Charger() def ModePleinEcran(self) : if not self.pleinecran : self.ShowFullScreen(True) self.pleinecran = True else : self.ShowFullScreen(False) self.pleinecran = False self.Recadre() def AjusteZoom(self, val) : self.echelle += round(val * 0.002 * self.echelle, 3) if self.echelle < 0.012 : self.echelle = 0.012 if self.echelle < 1.1 and self.echelle > 0.9 : self.echelle = 1.0 if self.echelle < self.echelleOpt + 0.037 and self.echelle > self.echelleOpt - 0.037 : self.echelle = self.echelleOpt self.Zoom() def AjusteTaille(self) : if self.echelle == self.echelleOpt : self.echelle = 1.0 else : self.echelle = self.echelleOpt self.Zoom() def Naviguer(self, n) : if not self.listeLong : return if self.verraleat : self.num = random.randint(0, self.listeLong-1) else : self.num = (self.num + n) % self.listeLong self.Charger() def BoiteMessageSuppr(self): retour = wx.MessageBox(u'Voulez-vous supprimer cette image ?', 'Confirmation', wx.YES_NO | wx.ICON_QUESTION) if retour == wx.YES : return True elif retour == wx.NO : return False return False def Recadre(self) : if not self.pleinecran : self.Fit() self.Center() self.Layout() self.Refresh() def Retaille(self) : tailleImg = self.staticbitmap.GetSize() tailleMax = wx.DisplaySize() bord = (15, 60) if self.pleinecran : bord = (0, 0) ratio = 1.0 ratio2 = 1.0 if tailleMax[0] - bord[0] < tailleImg[0] : ratio = float(tailleMax[0] - bord[0]) / float(tailleImg[0]) if tailleMax[1] - bord[1] < tailleImg[1] : ratio2 = float(tailleMax[1] - bord[1]) / float(tailleImg[1]) if ratio2 < ratio : ratio = ratio2 if ratio != 1.0 : self.echelle = ratio self.echelleOpt = ratio self.Zoom() return self.echelleOpt = 1.0 self.Recadre() def Zoom(self) : l = self.image.GetWidth() h = self.image.GetHeight() e = self.echelle # image = self.image.Rescale(l * e, h * e, 1) if (e > 1) : image = self.image.Scale(l * e, h * e, wx.IMAGE_QUALITY_NORMAL) else : image = self.image.Scale(l * e, h * e, wx.IMAGE_QUALITY_HIGH) self.bitmap = wx.BitmapFromImage(image) self.staticbitmap.SetBitmap(self.bitmap) self.Recadre() def Listeur(self) : if len(sys.argv) == 1 : return lien = os.path.relpath(sys.argv[1]) # lien = "Images\\e.jpg" dossier = os.path.split(lien) dossier = dossier[0] if dossier == "" : dossier = "." lien = '.\\' + lien contenu = os.listdir(dossier) liste = [] exts = self.exts for f in contenu : if os.path.isdir(f) : continue fex = os.path.splitext(f) if len(fex) == 1 : continue ext = (fex[1][1:]).lower() if ext in exts : liste.append(os.path.join(dossier, f)) self.num = liste.index(lien) self.liste = liste self.listeLong = len(liste) self.Charger() def Charger(self) : lien = self.liste[self.num] if not os.path.exists(lien) : return if self.verrexif : self.MetaDonnees(lien) if self.DIALINFOS : self.DIALINFOS.exif = self.exif self.DIALINFOS.TraitementMeta() self.SetTitle(os.path.os.path.basename(lien)) type = os.path.splitext(lien) type = (type[1][1:]).lower() if self.anim : self.anim.Destroy() if type == 'gif' : self.anim = wx.animate.GIFAnimationCtrl(self, wx.ID_ANY, lien, pos=(0, 0)) self.anim.Play() self.image = wx.Image(lien, wx.BITMAP_TYPE_ANY) self.bitmap = wx.BitmapFromImage(self.image) self.staticbitmap.SetBitmap(self.bitmap) elif type == 'jpg' or type == 'jpeg' : self.image = wx.Image(lien, wx.BITMAP_TYPE_ANY) self.image.InitAlpha() self.bitmap = wx.BitmapFromImage(self.image) self.staticbitmap.SetBitmap(self.bitmap) elif type == 'tga' : self.image = self.LireTGA(lien) self.bitmap = wx.BitmapFromImage(self.image) self.staticbitmap.SetBitmap(self.bitmap) elif type == 'pix' : self.image = self.LirePIX(lien) self.bitmap = wx.BitmapFromImage(self.image) self.staticbitmap.SetBitmap(self.bitmap) else : self.image = wx.Image(lien, wx.BITMAP_TYPE_ANY) if not self.image.HasAlpha() : self.image.InitAlpha() self.bitmap = wx.BitmapFromImage(self.image) self.staticbitmap.SetBitmap(self.bitmap) if self.verrzoom : self.Zoom() else : self.echelle = 1.0 self.Retaille() def LirePIX(self, lien) : # Carmageddon 2 img = wx.EmptyImage() f = open(lien, "rb") if not f : return img # En-tête f.read(16) f.read(8) type = st.unpack(">B", f.read(1))[0] # 3 : 8 bits, 5 : 16 bits, 18 : 16 bits alpha f.read(2) largeur = st.unpack(">H", f.read(2))[0] hauteur = st.unpack(">H", f.read(2))[0] f.read(6) o = st.unpack(">B", f.read(1))[0] while o : o = st.unpack(">B", f.read(1))[0] f.read(4) taille = st.unpack(">L", f.read(4))[0] # Nombre d'octets des données de pixel nbpix = st.unpack(">L", f.read(4))[0] # Nombre de pixels format = st.unpack(">L", f.read(4))[0] # Nombre de bits pour un pixel : 1 = 8 bits, 2 = 16 bits # Pixels pixel = [] img.Create(largeur, hauteur) img.InitAlpha() for i in xrange(nbpix) : x = i % largeur y = i / largeur if type == 5 : # 16 bits val = st.unpack(">H", f.read(2))[0] pixel = [] pixel.append(((val & 0xF800) >> 11) << 3) pixel.append(((val & 0x07E0) >> 5) << 2) pixel.append(((val & 0x001F) >> 0) << 3) img.SetRGB(x, y, pixel[0], pixel[1], pixel[2]) elif type == 18 : # 16 bits alpha val = st.unpack(">H", f.read(2))[0] pixel = [] pixel.append(((val & 0x0F00) >> 8) << 4) pixel.append(((val & 0x00F0) >> 4) << 4) pixel.append(((val & 0x000F) >> 0) << 4) pixel.append(((val ) >> 12) << 4) img.SetRGB(x, y, pixel[0], pixel[1], pixel[2]) img.SetAlpha(x, y, pixel[3]) return img def LireTGA(self, lien) : img = wx.EmptyImage() f = open(lien, "rb") if not f : return img palette = [] # En-tête id_taille = st.unpack("B", f.read(1))[0] apalette = st.unpack("B", f.read(1))[0] imagetype = st.unpack("B", f.read(1))[0] # ?, 8 bits nc pal, 16 24 32 bits nc BRV, 8 16 bits nc gris, idem 1 compressé, idem 2 c, idem 3 c pal_deb = st.unpack("h", f.read(2))[0] # Index de la première couleur dans la palette pal_long = st.unpack("h", f.read(2))[0] # Nombre de couleurs de la palette pal_tail = st.unpack("B", f.read(1))[0] # Nombre de bits par couleur de la palette. Il peut être de 15, 16, 24 ou 32. f.read(4) largeur = st.unpack("h", f.read(2))[0] hauteur = st.unpack("h", f.read(2))[0] format = st.unpack("B", f.read(1))[0] # Nombre de bits utilisés pour stocker un pixel de l'image f.read(1) f.read(id_taille) pixel = [] #f.seek(id_taille, f.tell()) # Palette if apalette : p_tail = pal_tail >> 3 for p in xrange(pal_long) : pixel = st.unpack("BBB", f.read(p_tail)) # pixel = f.read(p_tail) palette.append(pixel) # Image img.Create(largeur, hauteur) img.InitAlpha() chn = "" chna = "" # brut = img.GetData() for i in xrange(largeur * hauteur) : x = i % largeur if imagetype == 1 : # 8 bits non compressé avec palette index = st.unpack("B", f.read(1))[0] pixel = palette[index] o = palette[index] # if pixel == (242, 242, 242) : chn += '\xf2\xf2\xf2' # else : chn += o[2] + o[1] + o[0] y = (hauteur-1) - (i/largeur) img.SetRGB(x, y, pixel[2], pixel[1], pixel[0]) elif imagetype == 2 : # 16 24 ou 32 bits non compressé BRV if format == 16 : o = st.unpack("BB", f.read(2)) # http://tfcduke.developpez.com/tutoriel/format/tga/ val = o[0] + (o[1] << 8) pixel = [] pixel.append(((val & 0x001F) >> 0) << 3) pixel.append(((val & 0x03E0) >> 5) << 3) pixel.append(((val & 0x7C00) >> 10) << 3) # o = chr(pixel[2]) + chr(pixel[1]) + chr(pixel[0]) y = (hauteur-1) - (i/largeur) if format == 24 : # o = f.read(3) pixel = st.unpack("BBB", f.read(3)) y = (hauteur-1) - (i/largeur) elif format == 32 : # o = f.read(4) pixel = st.unpack("BBBB", f.read(4)) y = i/largeur img.SetAlpha(x, y, pixel[3]) # chna += o[3] # chn += o[2] + o[1] + o[0] # chn.extend([pixel[2], pixel[1], pixel[0]]) img.SetRGB(x, y, pixel[2], pixel[1], pixel[0]) elif imagetype == 3 : # 8 ou 16 bits non compressé gris if format == 8 : pixel = st.unpack("B", f.read(1))[0] elif format == 16 : pixel = st.unpack("h", f.read(2))[0] y = (hauteur-1) - (i/largeur) img.SetRGB(x, y, pixel, pixel, pixel) # img.SetData(img.GetData()) # if chna : img.SetAlphaData(chna) f.close() return img def main() : lec = wx.App() # App() pour console wx, (False) sans fenetre = Fenetre(None, -1, "ImageVonc") lec.MainLoop() if __name__ == "__main__" : main()