summaryrefslogtreecommitdiffstats
path: root/macrofusion.py
diff options
context:
space:
mode:
authorsalvadh0r <dhor@toxic.net.pl>2011-11-12 06:26:01 +0100
committersalvadh0r <dhor@toxic.net.pl>2011-11-12 06:26:01 +0100
commitd83f8eb66841f08966cea2257f8b75ccb787935c (patch)
tree06206b9d7176255794c01b5797f2034712598efd /macrofusion.py
downloadmacrofusion-code-d83f8eb66841f08966cea2257f8b75ccb787935c.zip
macrofusion-code-d83f8eb66841f08966cea2257f8b75ccb787935c.tar.gz
macrofusion-code-d83f8eb66841f08966cea2257f8b75ccb787935c.tar.bz2
new file: CHANGELOG
new file: LICENSE new file: README new file: TODO new file: debian/README.Debian new file: debian/README.source new file: debian/changelog new file: debian/compat new file: debian/control new file: debian/copyright new file: debian/docs new file: debian/emacsen-install.ex new file: debian/emacsen-remove.ex new file: debian/emacsen-startup.ex new file: debian/init.d.ex new file: debian/macrofusion.cron.d.ex new file: debian/macrofusion.default.ex new file: debian/macrofusion.doc-base.EX new file: debian/macrofusion.install new file: debian/manpage.1.ex new file: debian/manpage.sgml.ex new file: debian/manpage.xml.ex new file: debian/menu.ex new file: debian/postinst.ex new file: debian/postrm.ex new file: debian/preinst.ex new file: debian/prerm.ex new file: debian/rules new file: debian/source/format new file: debian/watch.ex new file: images/logoMF.png new file: images/logoSplash.png new file: locale/fr/LC_MESSAGES/MacroFusion.mo new file: locale/fr/LC_MESSAGES/MacroFusion.po new file: locale/pl/LC_MESSAGES/MacroFusion.mo new file: locale/pl/LC_MESSAGES/MacroFusion.po new file: macrofusion.desktop new file: macrofusion.pot new file: macrofusion.py new file: ui/DOFuseInterface.glade new file: ui/Progress.glade
Diffstat (limited to 'macrofusion.py')
-rwxr-xr-xmacrofusion.py725
1 files changed, 725 insertions, 0 deletions
diff --git a/macrofusion.py b/macrofusion.py
new file mode 100755
index 0000000..32aa10d
--- /dev/null
+++ b/macrofusion.py
@@ -0,0 +1,725 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+# Licence : GPLv3 voir : http://gplv3.fsf.org/
+
+try:
+ import os, sys
+ import os.path
+ import subprocess
+ import shutil
+ import gobject
+ import time
+ import threading
+ import multiprocessing
+ import re
+ import ConfigParser
+except:
+ print('An error occured. Python or one of its sub modules is absent...\nIt would be wise to check your python installation.')
+ sys.exit(1)
+
+try:
+ import Image
+except:
+ print('Python Imaging Library is missing.')
+
+try:
+ import gtk
+ import gtk.glade
+ import pygtk
+ pygtk.require("2.0")
+except:
+ print('gtk2, pygtk or libglade is missing.')
+ sys.exit(1)
+
+
+APP = 'MacroFusion'
+
+if os.path.exists('/usr/share/mfusion/ui/DOFuseInterface.glade') \
+ and os.path.exists('/usr/share/mfusion/ui/Progress.glade') \
+ and os.path.exists('/usr/share/pixmaps/macrofusion/logoMF.png') \
+ and os.path.exists('/usr/share/pixmaps/macrofusion/logoSplash.png'):
+ # print ("System wide install!")
+ DIR = '/usr/share/locale/'
+ IMG = '/usr/share/pixmaps/macrofusion/'
+ UI = '/usr/share/mfusion/ui/'
+elif os.path.exists(sys.path[0] + "/ui/DOFuseInterface.glade"):
+ # print ("Local run!")
+ DIR = sys.path[0] + '/locale/'
+ IMG = sys.path[0] + '/images/'
+ UI = sys.path[0] + '/ui/'
+else:
+ print ("That's me, your MacroFusion. Make your mind - local or system wide install?")
+ sys.exit(1)
+
+import locale
+import gettext
+for module in (gettext, gtk.glade):
+ module.bindtextdomain(APP, DIR)
+ module.textdomain(APP)
+locale.setlocale(locale.LC_ALL, '')
+#gettext.bindtextdomain(APP, DIR)
+#gettext.textdomain(APP)
+#gettext.install(APP)
+_ = gettext.gettext
+
+
+
+gobject.threads_init() #Pour que les threads soient lancés au moment opportun.
+
+
+
+def toggled_cb(cell, path, user_data):
+ model, column = user_data
+ model[path][column] = not model[path][column]
+ return
+
+def creer_miniature(chemin,taille):
+ outfile=donnees.previs_dossier + '/' + os.path.split(chemin)[1]
+ try:
+ im = Image.open(chemin)
+ im.thumbnail(taille)
+ im.save(outfile, "JPEG")
+ except IOError:
+ print _("Generating %s thumbnail failed.") % infile
+ return outfile
+
+
+
+####################################################
+########Classe des données##########################
+####################################################
+
+class Donnees:
+ """Données utiles"""
+ def __init__(self):
+ self.install_dossier=sys.path[0] #On recupere le dossier d'install
+
+ self.home_dossier = (os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config')) + '/mfusion'
+ # self.home_dossier = os.environ['HOME'] #On créé les dossiers pour mettre les preview
+ self.enfuse_dossier = self.home_dossier
+ self.previs_dossier = self.enfuse_dossier + "/preview"
+ if not os.path.isdir(self.enfuse_dossier):
+ os.makedirs(self.enfuse_dossier)
+ if not os.path.isdir(self.previs_dossier):
+ os.makedirs(self.previs_dossier)
+
+ self.default_folder=os.path.expanduser('~/')
+ self.default_file=""
+
+ def check_install(self, name):
+ a=False
+ for dir in os.environ['PATH'].split(":"):
+ prog = os.path.join(dir, name)
+ if os.path.exists(prog):
+ a=True
+ return a
+
+##############################################################
+###########Classe de l'interface##############################
+##############################################################
+
+
+class Interface:
+ """Interface pour le logiciel d'exposition-fusion enfuse"""
+
+ def __init__(self):
+
+ # Set default icon
+ gtk.window_set_default_icon_from_file(IMG + 'logoMF.png')
+
+
+ self.cpus = multiprocessing.cpu_count()
+ if not donnees.check_install("enfuse"):
+ self.messageinthebottle(_("Can't find Enfuse.\nPlease check enblend/enfuse is installed.\nStopping..."))
+ sys.exit()
+
+ # Check cpus
+ if self.cpus>1 and donnees.check_install("enfuse-mp"):
+ print _("Will use all the powers of your CPU!")
+ self.enfuser = "enfuse-mp"
+ else:
+ self.enfuser = "enfuse"
+
+
+ #Set the Glade file
+ self.gui=gtk.glade.XML(fname=UI + "DOFuseInterface.glade", domain=APP)
+
+
+ #Dans la foulee on chope la fenetre principale, ca sert a rien c'est pour
+ #montrer qu'on peut le faire c'est tout ^^
+ self.win=self.gui.get_widget("mainwindow")
+ self.win.set_title('MacroFusion')
+
+ #On chope le reste, et ca, ca va servir...
+ self.listeimages = self.gui.get_widget("listeimages")
+ self.buttonajoutfichiers = self.gui.get_widget("buttonajoutfichiers")
+ self.buttonenleverfichier = self.gui.get_widget("buttonenleverfichier")
+ self.statusbar = self.gui.get_widget("status1")
+ self.statusbar.push(1, _("CPU Cores: %s") % self.cpus)
+
+ self.hscaleexp = self.gui.get_widget("hscaleexp")
+ self.ajus_exp = gtk.Adjustment(value=1, lower=0, upper=1, step_incr=0.1, page_incr=0.1, page_size=0)
+ self.hscaleexp.set_adjustment(self.ajus_exp)
+ self.spinbuttonexp = self.gui.get_widget("spinbuttonexp")
+ self.spinbuttonexp.set_digits(1)
+ self.spinbuttonexp.set_value(1)
+ self.spinbuttonexp.set_adjustment(self.ajus_exp)
+
+ self.hscalecont = self.gui.get_widget("hscalecont")
+ self.ajus_cont = gtk.Adjustment(value=0, lower=0, upper=1, step_incr=0.1, page_incr=0.1, page_size=0)
+ self.hscalecont.set_adjustment(self.ajus_cont)
+ self.spinbuttoncont = self.gui.get_widget("spinbuttoncont")
+ self.spinbuttoncont.set_digits(1)
+ self.spinbuttoncont.set_value(0)
+ self.spinbuttoncont.set_adjustment(self.ajus_cont)
+
+ self.hscalesat = self.gui.get_widget("hscalesat")
+ self.ajus_sat = gtk.Adjustment(value=0.2, lower=0, upper=1, step_incr=0.1, page_incr=0.1, page_size=0)
+ self.hscalesat.set_adjustment(self.ajus_sat)
+ self.spinbuttonsat = self.gui.get_widget("spinbuttonsat")
+ self.spinbuttonsat.set_digits(1)
+ self.spinbuttonsat.set_value(0.2)
+ self.spinbuttonsat.set_adjustment(self.ajus_sat)
+
+ self.hscalemu = self.gui.get_widget("hscalemu")
+ self.ajus_mu = gtk.Adjustment(value=0.5, lower=0, upper=1, step_incr=0.01, page_incr=0.1, page_size=0)
+ self.hscalemu.set_adjustment(self.ajus_mu)
+ self.spinbuttonmu = self.gui.get_widget("spinbuttonmu")
+ self.spinbuttonmu.set_digits(2)
+ self.spinbuttonmu.set_value(0.5)
+ self.spinbuttonmu.set_adjustment(self.ajus_mu)
+
+ self.hscalesigma = self.gui.get_widget("hscalesigma")
+ self.ajus_sigma = gtk.Adjustment(value=0.2, lower=0, upper=1, step_incr=0.01, page_incr=0.1, page_size=0)
+ self.hscalesigma.set_adjustment(self.ajus_sigma)
+ self.spinbuttonsigma = self.gui.get_widget("spinbuttonsigma")
+ self.spinbuttonsigma.set_digits(2)
+ self.spinbuttonsigma.set_value(0.2)
+ self.spinbuttonsigma.set_adjustment(self.ajus_sigma)
+
+ self.buttonpreview = self.gui.get_widget("buttonpreview")
+ self.checkbuttontiff = self.gui.get_widget("checkbuttontiff")
+ self.checkbuttonjpeg = self.gui.get_widget("checkbuttonjpeg")
+ self.buttonfusion = self.gui.get_widget("buttonfusion")
+ self.buttonbeforeafter = self.gui.get_widget("buttonbeforeafter")
+ self.buttonedit = self.gui.get_widget("buttoneditw")
+
+ self.imagepreview = self.gui.get_widget("imagepreview")
+ self.imagepreview.set_from_file(IMG + "logoSplash.png")
+
+ self.progressbar = self.gui.get_widget("progressbar")
+
+ self.checkbuttonexif = self.gui.get_widget("checkbuttonexif")
+
+ if not donnees.check_install('exiftool'):
+ self.messageinthebottle(_("Exiftool missing!\n\n Cannot copy exif info."))
+
+ #valeurs des options et configurations :
+ self.check_pyramidelevel = self.gui.get_widget("check_pyramidelevel")
+ self.spinbuttonlevel = self.gui.get_widget("spinbuttonlevel")
+ self.check_hardmask = self.gui.get_widget("check_hardmask")
+ self.check_contwin = self.gui.get_widget("check_contwin")
+ self.spinbuttoncontwin = self.gui.get_widget("spinbuttoncontwin")
+
+ self.check_courb = self.gui.get_widget("check_courb")
+ self.check_prctcourb = self.gui.get_widget("check_prctcourb")
+ self.spinbuttoncourb = self.gui.get_widget("spinbuttoncourb")
+ self.check_detecbord = self.gui.get_widget("check_detecbord")
+ self.spinbuttonEdge = self.gui.get_widget("spinbuttonEdge")
+ # self.spinbuttonEdge.set_value(self.conf.getint('prefs', 'w'))
+
+ self.spinbuttonLceS = self.gui.get_widget("spinbuttonLceS")
+ self.spinbuttonLceF = self.gui.get_widget("spinbuttonLceF")
+ self.check_lces = self.gui.get_widget("check_lces")
+ self.check_lcef = self.gui.get_widget("check_lcef")
+
+ self.check_ciecam = self.gui.get_widget("check_ciecam")
+ self.check_desatmeth = self.gui.get_widget("check_desatmeth")
+ self.combobox_desatmet = self.gui.get_widget("combobox_desatmet")
+ self.spinbuttonlargeurprev = self.gui.get_widget("spinbuttonlargeurprev")
+ self.spinbuttonhauteurprev = self.gui.get_widget("spinbuttonhauteurprev")
+ self.checkbuttoncache = self.gui.get_widget("checkbuttoncache")
+ self.spinbuttoncache = self.gui.get_widget("spinbuttoncache")
+ self.checkbuttonbloc = self.gui.get_widget("checkbuttonbloc")
+ self.spinbuttonbloc = self.gui.get_widget("spinbuttonbloc")
+ self.checkbuttontaillefinale = self.gui.get_widget("checkbuttontaillefinale")
+ self.spinbuttonlargeurfinale = self.gui.get_widget("spinbuttonlargeurfinale")
+ self.spinbuttonhauteurfinale = self.gui.get_widget("spinbuttonhauteurfinale")
+ self.spinbuttonxoff = self.gui.get_widget("spinbuttonxoff")
+ self.spinbuttonyoff = self.gui.get_widget("spinbuttonyoff")
+ self.checkbuttonjpegorig = self.gui.get_widget("checkbuttonjpegorig")
+ self.hscalecomprjpeg = self.gui.get_widget("hscalecomprjpeg")
+ self.combtiff = self.gui.get_widget("combtiff")
+
+ self.combobox_desatmet.set_active(0)
+ self.combtiff.set_active(0)
+
+# Read values from config
+ self.conf = ConfigParser.ConfigParser()
+ if os.path.isfile(donnees.enfuse_dossier + '/mfusion.cfg'):
+ self.conf.read(donnees.enfuse_dossier + '/mfusion.cfg')
+ if self.conf.has_option('prefs', 'pwidth'):
+ self.spinbuttonlargeurprev.set_value(self.conf.getint('prefs', 'pwidth'))
+ if self.conf.has_option('prefs', 'pheight'):
+ self.spinbuttonhauteurprev.set_value(self.conf.getint('prefs', 'pheight'))
+ if self.conf.has_option('prefs', 'cachebutton'):
+ self.checkbuttoncache.set_active(self.conf.getboolean('prefs', 'cachebutton'))
+ if self.conf.has_option('prefs', 'cachesize'):
+ self.spinbuttoncache.set_value(self.conf.getint('prefs', 'cachesize'))
+ if self.conf.has_option('prefs', 'blocbutton'):
+ self.checkbuttonbloc.set_active(self.conf.getboolean('prefs', 'blocbutton'))
+ if self.conf.has_option('prefs', 'blocsize'):
+ self.spinbuttonbloc.set_value(self.conf.getint('prefs', 'blocsize'))
+ if self.conf.has_option('prefs', 'outsize'):
+ self.checkbuttontaillefinale.set_active(self.conf.getboolean('prefs', 'outsize'))
+ if self.conf.has_option('prefs', 'outwidth'):
+ self.spinbuttonlargeurfinale.set_value(self.conf.getint('prefs', 'outwidth'))
+ if self.conf.has_option('prefs', 'outheight'):
+ self.spinbuttonhauteurfinale.set_value(self.conf.getint('prefs', 'outheight'))
+ if self.conf.has_option('prefs', 'xoff'):
+ self.spinbuttonxoff.set_value(self.conf.getint('prefs', 'xoff'))
+ if self.conf.has_option('prefs', 'yoff'):
+ self.spinbuttonyoff.set_value(self.conf.getint('prefs', 'yoff'))
+ if self.conf.has_option('prefs', 'jpegdef'):
+ self.checkbuttonjpegorig.set_active(self.conf.getboolean('prefs', 'jpegdef'))
+ if self.conf.has_option('prefs', 'jpegcompr'):
+ self.hscalecomprjpeg.set_value(self.conf.getfloat('prefs', 'jpegcompr'))
+ if self.conf.has_option('prefs', 'tiffcomp'):
+ self.combtiff.set_active(self.conf.getint('prefs', 'tiffcomp'))
+
+ #On relie les signaux (cliques sur boutons, cochage des cases, ...) aux fonctions appropriées
+ dic = { "on_mainwindow_destroy" : self.exit_app,
+ "on_buttonannuler_clicked" : self.exit_app,
+ "on_menufilequit_activate" : self.exit_app,
+ "on_menufileopen_activate" : self.ouverture,
+ "on_buttonajoutfichiers_clicked" : self.ajout,
+ "on_menufileadd_activate" : self.ajout,
+ "on_buttonenleverfichier_clicked" : self.ttenlever,
+ "on_menufileenlever_activate" : self.enlever,
+ "on_menufilettenlever_activate" : self.ttenlever,
+ "on_buttonpreview_clicked" : self.preview,
+ "on_menufilesave_activate" : self.fusion,
+ "on_buttonfusion_clicked" : self.fusion,
+ "on_buttoneditw_clicked" : self.sendto,
+ "on_buttonbeforeafter_pressed" : self.baswitch,
+ "on_buttonbeforeafter_released" : self.baswitch,
+ "on_imagemenuitem10_activate" : self.apropos
+ }
+ #Auto-connection des signaux
+ self.gui.signal_autoconnect(dic)
+
+ #initialisation de la liste d'images a fusionner
+ self.inittreeview()
+
+ def exit_app(self, action):
+ # cancel = self.autosave_image()
+ # if cancel:
+ # return True
+ self.stop_now = True
+ self.closing_app = True
+ self.save_settings()
+ self.cleanup()
+ sys.exit(0)
+
+ def cleanup(self):
+ for self.files in os.walk(donnees.previs_dossier):
+ for self.filename in self.files[2]:
+ os.remove(donnees.previs_dossier + "/" + self.filename)
+
+ def inittreeview(self):
+ """initialisation de la liste d'images a importer"""
+ self.liststoreimport = gtk.ListStore(bool, str, str) #création de la listestore qui contiendra les noms d'images
+ self.listeimages.set_model(self.liststoreimport) #on donne la liststore au l'afficheur treeview
+
+ self.colonneselect = gtk.TreeViewColumn('') #Premiere colonne :
+ self.listeimages.append_column(self.colonneselect) #on l'ajoute au TreeView
+ self.select=gtk.CellRendererToggle() #On creer le cellrender pour avoir des boutons toggle
+ self.colonneselect.pack_start(self.select, True) #on met le cellrender dans la colonne
+ self.colonneselect.add_attribute(self.select, 'active', 0) #on met les boutons actifs par défaut
+
+ self.colonneimages = gtk.TreeViewColumn(_('Image')) #deuxieme colonne, titre 'Image'
+ self.listeimages.append_column(self.colonneimages) #on rajoute la colonne dans le treeview
+ self.cell = gtk.CellRendererText() #Ce sera des cellules de texte
+ self.colonneimages.pack_start(self.cell, True) #que l'on met dans la colonne
+ self.colonneimages.add_attribute(self.cell, 'text', 1) #et on specifie que c'est du texte simple
+
+ self.select.connect("toggled", toggled_cb, (self.liststoreimport, 0)) #Pour que les boutons de selection marchent
+
+
+ def ouverture(self, widget):
+ FenOuv=Fenetre_Ouvrir(self.liststoreimport,0)
+ self.liststoreimport=FenOuv.get_model()
+ #self.raffraichissementlisteimages()
+
+ def ajout(self, widget):
+ FenOuv=Fenetre_Ouvrir(self.liststoreimport,1)
+ self.liststoreimport=FenOuv.get_model()
+ #self.raffraichissementlisteimages()
+
+ def raffraichissementlisteimages(self):
+ #self.listeimages.set_model(self.liststoreimport)
+ self.treeselectionsuppr=self.listeimages.get_selection() #pour récupérer quels fichiers sont selectionnés
+ self.treeselectionsuppr.set_mode(gtk.SELECTION_MULTIPLE) #Pour pouvoir en selectionner plusieurs
+
+ def enlever(self, widget):
+ self.treeselectionsuppr=self.listeimages.get_selection() #pour récupérer quels fichiers sont selectionnés
+ self.treeselectionsuppr.set_mode(gtk.SELECTION_MULTIPLE) #Pour pouvoir en selectionner plusieurs
+ (model, pathlist) = self.treeselectionsuppr.get_selected_rows()
+ for i in pathlist:
+ treeiter = model.get_iter(i)
+ self.liststoreimport.remove(treeiter)
+
+ def ttenlever(self, widget):
+ self.liststoreimport.clear()
+
+ def preview(self, widget):
+ self.taille=(self.spinbuttonlargeurprev.get_value(), self.spinbuttonhauteurprev.get_value())
+ self.name=donnees.previs_dossier + "/" + "preview.jpg"
+ item=0
+ if len(self.liststoreimport)>0:
+ self.ref=zip(*self.liststoreimport)[0]
+ for item in self.ref:
+ if item:
+ item=-1
+ self.thread_preview = Thread_Preview(self.taille, self.get_options(), self.liststoreimport)
+ self.thread_preview.start()
+ timer = gobject.timeout_add (100, self.pulsate)
+ break
+ if item==0:
+ self.messageinthebottle(_("Please add some images!\n\n Can't fuse anything."))
+
+ def get_options(self):
+ options=["--exposure-weight=" + str(self.spinbuttonexp.get_value()),
+ "--exposure-mu=" + str(self.spinbuttonmu.get_value()),
+ "--exposure-sigma=" + str(self.spinbuttonsigma.get_value()),
+ "--saturation-weight=" + str(self.spinbuttonsat.get_value()),
+ "--contrast-weight=" + str(self.spinbuttoncont.get_value())]
+ if self.check_pyramidelevel.get_active():
+ options.append('-l ' + str(self.spinbuttonlevel.get_value_as_int()))
+ if self.check_hardmask.get_active():
+ options.append('--hard-mask')
+ if self.check_contwin.get_active():
+ options.append('--contrast-window-size=' + str(self.spinbuttoncontwin.get_value_as_int()))
+ if self.check_courb.get_active():
+ if self.check_prctcourb.get_active():
+ options.append('--contrast-min-curvature=' + str(self.spinbuttoncourb.get_value()) + "%")
+ else:
+ options.append('--contrast-min-curvature=' + str(self.spinbuttoncourb.get_value()))
+ if self.check_detecbord.get_active():
+ opts='--contrast-edge-scale=' + str(self.spinbuttonEdge.get_value()) + ':'
+ if self.check_lces.get_active():
+ opts+=str(self.spinbuttonLceS.get_value()) + '%:'
+ else:
+ opts+=str(self.spinbuttonLceS.get_value()) + ':'
+
+ if self.check_lcef.get_active():
+ opts+=str(self.spinbuttonLceF.get_value()) + '%'
+ else:
+ opts+=str(self.spinbuttonLceF.get_value()) + ''
+
+ options.append(opts)
+
+
+ # + str(self.spinbuttonLceF.get_value()) + '%')
+ if self.check_ciecam.get_active():
+ options.append('-c')
+ if self.check_desatmeth.get_active():
+ opt={-1:None, 0:"average", 1:'l-star', 2:'lightness', 3:'value', 4:'luminance'}
+ options.append('--gray-projector=' + opt[self.combobox_desatmet.get_active()])
+ if not self.checkbuttoncache.get_active():
+ options.append('-m ' + str(self.spinbuttoncache.get_value_as_int()))
+ if not self.checkbuttonbloc.get_active():
+ options.append('-b ' + str(self.spinbuttonbloc.get_value_as_int()))
+ if not self.checkbuttontaillefinale.get_active():
+ options.append('-f ' + str(self.spinbuttonlargeurfinale.get_value_as_int()) + 'x' + str(self.spinbuttonhauteurfinale.get_value_as_int()) + 'x' + str(self.spinbuttonxoff.get_value_as_int()) + 'x' + str(self.spinbuttonyoff.get_value_as_int()))
+ if self.name.endswith(('.tif', '.tiff', '.TIF', '.TIFF')):
+ tiffopt={0:"NONE", 1:"PACKBITS", 2:"LZW", 3:"DEFLATE"}
+ options.append("--compression=" + tiffopt[self.combtiff.get_active()])
+ if self.name.endswith(('.jpg', '.jpeg', '.JPG', '.JPEG')) and (not self.checkbuttonjpegorig.get_active()):
+ options.append("--compression=" + str(int(self.hscalecomprjpeg.get_value())))
+ return options
+
+ def pulsate(self):
+ if self.thread_preview.isAlive(): #Tant que le thread est en cours,
+ self.progressbar.set_text(_("Calculating preview..."))
+ self.progressbar.pulse() #on fait pulser la barre
+ return True #et on renvoie True pour que gobject.timeout recommence
+ else:
+ self.progressbar.set_fraction(1)
+ self.progressbar.set_text(_("Preview generated"))
+ self.imagepreview.set_from_file(donnees.previs_dossier + "/" + "preview.jpg")
+ return False
+
+ def baswitch(self, widget):
+ if (not int(self.buttonbeforeafter.get_relief())) and (os.path.exists(donnees.previs_dossier + "/preview_.jpg")):
+ self.buttonbeforeafter.props.relief = gtk.RELIEF_NONE
+ self.imagepreview.set_from_file(donnees.previs_dossier + "/preview_.jpg")
+ elif os.path.exists(donnees.previs_dossier + "/preview_.jpg"):
+ self.buttonbeforeafter.props.relief = gtk.RELIEF_NORMAL
+ self.imagepreview.set_from_file(donnees.previs_dossier + "/preview.jpg")
+ # self.buttonbeforeafter.set_label("gfdgdf")
+
+
+
+ def fusion(self,widget):
+ FenPar=Fenetre_Parcourir()
+ self.name = FenPar.get_name()
+ if self.name:
+ if not re.search('.jpeg$|.jpg$|.tiff$', self.name, flags=re.IGNORECASE):
+ self.name+=".jpg"
+ self.enroute('')
+
+ def sendto(self, widget):
+ self.name=(donnees.previs_dossier + "/sendto.jpg")
+
+ if self.enroute(self.name) == -1:
+ self.messageinthebottle(_("No preview, no output, no edit.\n\n Game Over."))
+ return
+
+ def messageinthebottle(self, message):
+ self.messaga=gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_OK, message_format=_(message))
+ if self.messaga.run() == gtk.RESPONSE_OK:
+ self.messaga.destroy()
+
+ def enroute(self, issend):
+ self.issend=issend
+ self.liste_images=[]
+ for item in self.liststoreimport:
+ if item[0]:
+ self.liste_images.append(item[2])
+ if self.liste_images.count(self.name):
+ self.messageinthebottle(_("Can't overwrite input image!\n\n Please change the output filename."))
+ return -1
+ if len(self.liste_images) == 0:
+ self.messageinthebottle(_("Please add some images!\n\n Can't fuse anything."))
+ return -1
+ command=[Gui.enfuser, "-o", self.name] + self.get_options() + self.liste_images
+ ProFus=Progress_Fusion(command, self.issend)
+
+
+ def apropos(self, widget):
+ self.fen=AproposFen()
+
+ def save_settings(self):
+ conf = ConfigParser.ConfigParser()
+ conf.add_section('prefs')
+ # conf.set('prefs', 'w', self.spinbuttonEdge.get_value_as_int())
+ conf.set('prefs', 'pwidth', self.spinbuttonlargeurprev.get_value_as_int())
+ conf.set('prefs', 'pheight', self.spinbuttonhauteurprev.get_value_as_int())
+ conf.set('prefs', 'cachebutton', self.checkbuttoncache.get_active())
+ conf.set('prefs', 'cachesize', self.spinbuttoncache.get_value_as_int())
+ conf.set('prefs', 'blocbutton', self.checkbuttonbloc.get_active())
+ conf.set('prefs', 'blocsize', self.spinbuttonbloc.get_value_as_int())
+ conf.set('prefs', 'outsize', self.checkbuttontaillefinale.get_active())
+ conf.set('prefs', 'outwidth', self.spinbuttonlargeurfinale.get_value_as_int())
+ conf.set('prefs', 'outheight', self.spinbuttonhauteurfinale.get_value_as_int())
+ conf.set('prefs', 'xoff', self.spinbuttonxoff.get_value_as_int())
+ conf.set('prefs', 'yoff', self.spinbuttonyoff.get_value_as_int())
+ conf.set('prefs', 'jpegdef', self.checkbuttonjpegorig.get_active())
+ conf.set('prefs', 'jpegcompr', int(self.hscalecomprjpeg.get_value()))
+ conf.set('prefs', 'tiffcomp', str(self.combtiff.get_active()))
+
+ if not os.path.exists(donnees.enfuse_dossier):
+ os.makedirs(donnees.enfuse_dossier)
+ conf.write(file(donnees.enfuse_dossier + '/mfusion.cfg', 'w'))
+
+ # Also, save accel_map:
+ # gtk.accel_map_save(self.config_dir + '/accel_map')
+
+ return
+
+####################################################################
+###########Classe pour choisir les images a fusionner###############
+####################################################################
+
+class Fenetre_Ouvrir:
+ """La classe qui ouvre la fenetre de choix de fichiers, et qui retourne le ListStore par la methode get_model"""
+ def __init__(self,model,bitajout):
+ """Lance la fenetre de selection et créé la listsore a partir des fichiers selectionnés"""
+ self.filtre=gtk.FileFilter()
+ self.filtre.add_mime_type("image/jpeg")
+ self.filtre.add_mime_type("image/tiff")
+ self.liststoreimport=model #on repart de l'ancien modele
+ if bitajout:
+ self.fenetre_ouvrir = gtk.FileChooserDialog(_("Add images..."),
+ None,
+ gtk.FILE_CHOOSER_ACTION_OPEN,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
+ self.fenetre_ouvrir.set_select_multiple(True)
+ self.fenetre_ouvrir.set_current_folder(donnees.default_folder)
+ self.fenetre_ouvrir.set_filter(self.filtre)
+ else:
+ self.fenetre_ouvrir = gtk.FileChooserDialog(_("Open images..."),
+ None,
+ gtk.FILE_CHOOSER_ACTION_OPEN,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
+ self.fenetre_ouvrir.set_select_multiple(True)
+ self.fenetre_ouvrir.set_current_folder(donnees.default_folder)
+ self.fenetre_ouvrir.set_filter(self.filtre)
+ self.liststoreimport.clear() #On remet le model a 0 (oublie des anciennes images)
+
+ if(self.fenetre_ouvrir.run() == gtk.RESPONSE_OK):
+ self.fichiers = self.fenetre_ouvrir.get_filenames()
+ donnees.default_file=self.fichiers[0]
+ for fichier in self.fichiers:
+ self.liststoreimport.append([1,os.path.basename(fichier),fichier])
+ donnees.default_folder=self.fenetre_ouvrir.get_current_folder()
+ self.fenetre_ouvrir.destroy()
+
+ def get_model(self):
+ """ Retourne la liststore """
+ if self.liststoreimport:
+ return self.liststoreimport
+ else:
+ return None
+
+
+#####################################################################
+#########Classe pour la fenetre pour choisir le fichier final########
+#####################################################################
+
+class Fenetre_Parcourir:
+ """La classe qui ouvre la fenetre de choix pour enregistrer le fichier"""
+ def __init__(self):
+
+ self.fenetre_ouvrir = gtk.FileChooserDialog(_("Save file..."),
+ None,
+ gtk.FILE_CHOOSER_ACTION_SAVE,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK))
+ self.fenetre_ouvrir.set_current_folder(donnees.default_folder)
+ # self.fenetre_ouvrir.set_filename(donnees.default_file)
+ self.fenetre_ouvrir.set_current_name('output.jpg')
+ self.fenetre_ouvrir.set_do_overwrite_confirmation(True)
+ if (self.fenetre_ouvrir.run() == gtk.RESPONSE_OK):
+ self.resultat=self.fenetre_ouvrir.get_filename()
+
+ self.fenetre_ouvrir.destroy()
+
+ def get_name(self):
+ try:
+ return self.resultat
+ except AttributeError:
+ return ""
+
+
+
+#####################################################################
+#########Thread pour la prévisualisation#############################
+#####################################################################
+
+class Thread_Preview(threading.Thread):
+ def __init__(self, taille, options, liste):
+ threading.Thread.__init__ (self)
+ self.taille=taille
+ self.options=options
+ self.liste=liste
+
+ def run(self):
+ images_a_fusionner=[]
+
+ for item in self.liste:
+ if item[0]:
+ chemin_miniature=creer_miniature(item[2],(int(self.taille[0]), int(self.taille[1])))
+ images_a_fusionner.append(chemin_miniature)
+ if os.path.exists(donnees.previs_dossier + "/preview.jpg"):
+ shutil.copy(donnees.previs_dossier + "/" + "preview.jpg", donnees.previs_dossier + "/" + "preview_.jpg")
+ command=[Gui.enfuser, "-o", donnees.previs_dossier + "/" + "preview.jpg"] + self.options + images_a_fusionner
+ # print (command)
+ preview_process=subprocess.Popen(command, stdout=subprocess.PIPE)
+ preview_process.wait()
+
+
+
+#######################################################################
+#########Fenetre de progression lors de la fusion finale###############
+#######################################################################
+
+class Progress_Fusion:
+ def __init__(self, command, issend):
+ self.issend=issend
+ self.progress = gtk.glade.XML(fname=UI + "Progress.glade", domain=APP)
+ self.progress_win = self.progress.get_widget("dialog1")
+ self.progress_label = self.progress.get_widget("progress_label")
+ self.info_label = self.progress.get_widget("info_label")
+ self.progress_bar = self.progress.get_widget("progressbar1")
+ self.progress_stop_button = self.progress.get_widget("stop_button")
+ self.dic1 = {"on_stop_button_clicked" : self.close_progress,
+ "on_dialog1_destroy" : self.close_progress}
+ self.progress.signal_autoconnect(self.dic1)
+ self.info_label.set_text(_('Fusion images...'))
+
+ self.thread_fusion = Thread_Fusion(command, self.issend) #On prepare le thread qui va faire tout le boulot
+ self.thread_fusion.start() #On le lance
+ timer = gobject.timeout_add (100, self.pulsate)
+
+ def pulsate(self):
+ if self.thread_fusion.isAlive(): #Tant que le thread est en cours,
+ self.progress_bar.set_text(_("Fusion, please wait..."))
+ self.progress_bar.pulse() #on fait pulser la barre
+ return True #et on renvoie True pour que gobject.timeout recommence
+ else:
+ self.progress_bar.set_fraction(1)
+ self.progress_bar.set_text(_("Fused !"))
+ self.close_progress(self)
+ return False
+
+ def close_progress(self, widget):
+ self.progress_win.destroy()
+
+
+
+##############################################################################
+###########Thread de fusion des vraies images#################################
+##############################################################################
+
+class Thread_Fusion(threading.Thread):
+ def __init__(self, command, issend):
+ threading.Thread.__init__ (self)
+ self.command=command
+ self.issend=issend
+
+ def run(self):
+ fusion_process=subprocess.Popen(self.command, stdout=subprocess.PIPE)
+ fusion_process.wait()
+ # fusion_process=subprocess.call(self.command)
+ if Gui.checkbuttonexif.get_active():
+ exif_copy = subprocess.Popen(["exiftool", "-tagsFromFile", "-overwrite_original", Gui.liste_images[0], Gui.name])
+ exif_copy.wait()
+ if len(self.issend) > 0:
+ subprocess.Popen(['gimp', self.issend], stdout=subprocess.PIPE)
+
+########################################
+#### Classe de la fenêtre a propos ####
+########################################
+
+class AproposFen:
+ def __init__(self):
+ # self.about = gtk.glade.XML(donnees.install_dossier + "/Apropos.glade", domain=APP)
+ # self.aboutdialog = self.about.get_widget("aboutdialog1")
+ self.aboutdialog = gtk.AboutDialog()
+ self.aboutdialog.set_name("MacroFusion")
+ self.aboutdialog.set_modal(True)
+ self.aboutdialog.set_position(gtk.WIN_POS_CENTER)
+ self.aboutdialog.set_version('0.5')
+ self.aboutdialog.set_comments('A GTK Gui for the excellent Enfuse.\n Based on EnfuseGui by Chez Gholyo.\n\n(c) 2011 Dariusz Duma <dhor@toxic.net.pl>')
+ self.pixbuf=gtk.gdk.pixbuf_new_from_file(IMG + "logoMF.png")
+ self.aboutdialog.set_logo(self.pixbuf)
+ self.aboutdialog.connect("response", self.close_about)
+ self.aboutdialog.show()
+
+
+ def close_about(self, widget, event):
+ self.aboutdialog.destroy()
+
+
+###########################################################
+#### Initialisation et appel de la classe principale ####
+###########################################################
+
+if __name__ == "__main__":
+
+ donnees=Donnees() #Initialisation des variables
+ Gui = Interface() #Initialise l'interface
+ gtk.main() #Lance la boucle principale