#!/usr/bin/python
# -*- coding: Utf-8 -*-

import sys, os, string, Image, ImageFilter, ImageOps, ImageEnhance
from random import randrange
from numpy import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from gui_modules_image.image_base import Base
from gui_modules_lecture.affichage_image.afficheurImage import VisionneurImagePourEKD


class FiltresAvecSpin(QFrame):
	"""Widget de réglage à 1, 2 ou 3 boites de spins"""
	def __init__(self, ligne1=('',('','','')), ligne2=None, ligne3=None):
        	QFrame.__init__(self)
		
		grid = QGridLayout(self)
		
		if not ligne2: # 1 seul spin
			self.spin = QSpinBox()
			self.spin.setRange(ligne1[1][0], ligne1[1][1])
			self.spin.setValue(ligne1[1][2])
			self.curseur = QSlider(Qt.Horizontal)
			self.curseur.setRange(ligne1[1][0], ligne1[1][1])
			self.curseur.setValue(ligne1[1][2])
			grid.addWidget(self.spin,0,0)
			grid.addWidget(self.curseur,0,1)
			grid.addWidget(QLabel(ligne1[0]),0,2)
			self.connect(self.spin,SIGNAL("valueChanged(int)"), self.spinChange)
			self.connect(self.curseur,SIGNAL("sliderMoved(int)"), self.curseurBouge)
		elif not ligne3: # 2 spins
			self.spin1 = QSpinBox()
			self.spin2 = QSpinBox()
			self.spin1.setRange(ligne1[1][0], ligne1[1][1])
			self.spin1.setValue(ligne1[1][2])
			self.spin2.setRange(ligne2[1][0], ligne2[1][1])
			self.spin2.setValue(ligne2[1][2])
			self.curseur1 = QSlider(Qt.Horizontal)
			self.curseur1.setRange(ligne1[1][0], ligne1[1][1])
			self.curseur1.setValue(ligne1[1][2])
			self.curseur2 = QSlider(Qt.Horizontal)
			self.curseur2.setRange(ligne2[1][0], ligne2[1][1])
			self.curseur2.setValue(ligne2[1][2])
			grid.addWidget(self.spin1,0,0)
			grid.addWidget(self.curseur1,0,1)
			grid.addWidget(QLabel(ligne1[0]),0,2)
			grid.addWidget(self.spin2,1,0)
			grid.addWidget(self.curseur2,1,1)
			grid.addWidget(QLabel(ligne2[0]),1,2)
			self.connect(self.spin1,SIGNAL("valueChanged(int)"), self.spinChange1Bis)
			self.connect(self.curseur1,SIGNAL("sliderMoved(int)"), self.curseurBouge1Bis)
			self.connect(self.spin2,SIGNAL("valueChanged(int)"), self.spinChange2Bis)
			self.connect(self.curseur2,SIGNAL("sliderMoved(int)"), self.curseurBouge2Bis)
		else: # 3 spins
			self.spin1 = QSpinBox()
			self.spin2 = QSpinBox()
			self.spin3 = QSpinBox()
			self.spin1.setRange(ligne1[1][0], ligne1[1][1])
			self.spin1.setValue(ligne1[1][2])
			self.spin2.setRange(ligne2[1][0], ligne2[1][1])
			self.spin2.setValue(ligne2[1][2])
			self.spin3.setRange(ligne3[1][0], ligne3[1][1])
			self.spin3.setValue(ligne3[1][2])
			self.curseur1 = QSlider(Qt.Horizontal)
			self.curseur1.setRange(ligne1[1][0], ligne1[1][1])
			self.curseur1.setValue(ligne1[1][2])
			self.curseur2 = QSlider(Qt.Horizontal)
			self.curseur2.setRange(ligne2[1][0], ligne2[1][1])
			self.curseur2.setValue(ligne2[1][2])
			self.curseur3 = QSlider(Qt.Horizontal)
			self.curseur3.setRange(ligne3[1][0], ligne3[1][1])
			self.curseur3.setValue(ligne3[1][2])
			grid.addWidget(self.spin1,0,0)
			grid.addWidget(self.curseur1,0,1)
			grid.addWidget(QLabel(ligne1[0]),0,2)
			grid.addWidget(self.spin2,1,0)
			grid.addWidget(self.curseur2,1,1)
			grid.addWidget(QLabel(ligne2[0]),1,2)
			grid.addWidget(self.spin3,2,0)
			grid.addWidget(self.curseur3,2,1)
			grid.addWidget(QLabel(ligne3[0]),2,2)
			self.connect(self.spin1,SIGNAL("valueChanged(int)"), self.spinChange1Bis)
			self.connect(self.curseur1,SIGNAL("sliderMoved(int)"), self.curseurBouge1Bis)
			self.connect(self.spin2,SIGNAL("valueChanged(int)"), self.spinChange2Bis)
			self.connect(self.curseur2,SIGNAL("sliderMoved(int)"), self.curseurBouge2Bis)
			self.connect(self.spin3,SIGNAL("valueChanged(int)"), self.spinChange3Bis)
			self.connect(self.curseur3,SIGNAL("sliderMoved(int)"), self.curseurBouge3Bis)

		grid.setAlignment(Qt.AlignCenter)
	
	def spinChange(self, i):
		"""modifie le curseur lorsque le curseur bouge"""
		self.curseur.setValue(i)
	
	def curseurBouge(self, i):
		"""Quand on change la position du curseur la valeur du spin est automatiquement modifiée"""
		self.spin.setValue(i)

	def spinChange1Bis(self, i):
		"""modifie le curseur lorsque le curseur bouge"""
		self.curseur1.setValue(i)
	
	def curseurBouge1Bis(self, i):
		"""Quand on change la position du curseur la valeur du spin est automatiquement modifiée"""
		self.spin1.setValue(i)

	def spinChange2Bis(self, i):
		"""modifie le curseur lorsque le curseur bouge"""
		self.curseur2.setValue(i)
	
	def curseurBouge2Bis(self, i):
		"""Quand on change la position du curseur la valeur du spin est automatiquement modifiée"""
		self.spin2.setValue(i)
		
	def spinChange3Bis(self, i):
		"""modifie le curseur lorsque le curseur bouge"""
		self.curseur3.setValue(i)
	
	def curseurBouge3Bis(self, i):
		"""Quand on change la position du curseur la valeur du spin est automatiquement modifiée"""
		self.spin3.setValue(i)
	

class FiltresAvec9Spin(QFrame):
	"""Widget de réglage à 9 boites de spin"""
	def __init__(self, txt1='', txt2=None):
        	QFrame.__init__(self)
		
		grid = QGridLayout(self)
		self.spin = [[0]*3,[0]*3,[0]*3]
		for k in range(3):
			for l in range(3):
				self.spin[k][l]=QSpinBox()
				self.spin[k][l].setRange(0, 99)
				self.spin[k][l].setValue(50)
				grid.addWidget(self.spin[k][l], k+1, l+1)
		
		grid.addWidget(QLabel(_(u"Couleur n°1")), 0, 1)
		grid.addWidget(QLabel(_(u"Couleur n°2")), 0, 2)
		grid.addWidget(QLabel(_(u"Couleur n°3")), 0, 3)
		grid.addWidget(QLabel(_(u"Rouge")), 1, 0)
		grid.addWidget(QLabel(_(u"Vert")), 2, 0)
		grid.addWidget(QLabel(_(u"Bleu")), 3, 0)
		grid.setAlignment(Qt.AlignCenter)


class FiltresAvecCombo(QFrame):
	"""Widget de réglage contenant une boite de combo"""
	def __init__(self, txt, liste):
        	QFrame.__init__(self)
		
		hbox = QHBoxLayout(self)
		hbox.addWidget(QLabel(txt))
		self.combo = QComboBox()
		
		font =QFont()
		fm = QFontMetricsF(font)
		hauteurIcone = fm.height() - 2 # icones espacées de 2 pixels
		
		for i in liste:
			if len(i)!=3: self.combo.addItem(i[0],QVariant(i[1]))
			else:
				pixmap = QPixmap(hauteurIcone, hauteurIcone)
				color = QColor(i[2][0],i[2][1],i[2][2])
				pixmap.fill(color)
				self.combo.addItem(QIcon(pixmap),i[0],QVariant(i[1]))
		hbox.addWidget(self.combo)
		hbox.setAlignment(Qt.AlignCenter)


class Image_FiltresImage(QWidget):
	"""# -----------------------------------
	# Cadre accueillant les widgets de :
	# Image >> Filtres image
	# -----------------------------------"""
	def __init__(self, parent):
        	QWidget.__init__(self)
		
		# ----------------------------
		# Quelques paramètres de base
		# ----------------------------
		
		#=== Création des répertoires temporaires ===#
		self.repTampon = '/tmp/ekd/tampon/image_filtres_image/'
		if os.path.isdir(self.repTampon) is False:
        		os.makedirs(self.repTampon)
		if os.path.isdir(self.repTampon+'redim/') is False:
        		os.makedirs(self.repTampon+'redim/')
		
		#=== Variable contenant les titres du log ===#
		self.infosImgTitre = []
		txt = _(u"Image(s) chargée(s)")
		a='#'*36
		b = a + '\n# ' + txt + '\n' + a + '\n'
		txt=_(u"Image(s) convertie(s)")
		c = a + '\n# ' + txt + '\n' + a + '\n'
		self.infosImgTitre.append(b)
		self.infosImgTitre.append(c)
		
		#=== Drapeaux ===#
		# Une conversion (même partielle) a-t-elle eu lieu après le chargement des images? (1: vrai)
		self.conversionImg = 0
		# Des images ont été chargées au moins une fois? (1: vrai)
		self.imgChargees = 0
		# Liste à 2 élements:
			# l'utilisateur vient d'afficher une nouvelle image <-> le curseur vient d'être déplacé?
			# indice de l'onglet qui vient d'afficher cette image
		self.nvImgAffichee = [0, 0] # le 2ème 0 n'a pas de sens pour l'instant
		# Forcer l'affichage de l'image dans le prochain onglet sélectionné (1: vrai)
		self.forcerAffichageImg = 0
		
		# Identifiant des filtres utilisant partiellement ou intégralement un module python durant la conversion
		self.filtresPython=['illustration_niveau_gris','traits_fins&couleur','emboss','sharpen','niveau_gris','cmyk','ombre_lumiere','couleurs_personnalisees','vieux_films','couleurs_predefinies', 'amelior_des_bords', 'debruitage', 'seuillage', 'evanescence', 'imitation_bd', 'negatif', 'encadre_photo']
		
		self.statusBar = parent.statusBar()
		
		# Fonctions communes à plusieurs cadres du module Image
		self.base = Base()
		# Paramètres de configuration
		self.config = parent.config
		self.listeImgSource = []
		self.listeImgDestin = []
		
		self.process = QProcess()
		self.connect(self.process, SIGNAL('finished(int)'), self.finConversion)
		
		# Boite d'alignement vertical
		vbox=QVBoxLayout(self)
		
		# ----------------------------------------
		# Bouton de sélection des images sources
		# ----------------------------------------
		
		#=== Bouton de sélection des images seq A et B ===#
		hbox = QHBoxLayout()
		self.boutOuvrirSource = QPushButton(_(u"Charger les images sources"))
		self.boutOuvrirSource.setFocusPolicy(Qt.NoFocus)
		hbox.addWidget(self.boutOuvrirSource)
		vbox.addLayout(hbox)
		
		self.connect(self.boutOuvrirSource, SIGNAL("clicked()"), self.ouvrirImages)
		
		self.tabwidget=QTabWidget()
		
		#------------------
		# Onglet Réglages
		#------------------
		
		self.framReglage=QFrame()
		vboxReglage=QVBoxLayout(self.framReglage)
		
		#=== Stacked ===#
		
		self.stacked = QStackedWidget()
		self.stacked.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed))
		
		#=== Instanciation des widgets du stacked  ===#
		
		# Widgets du stacked sans réglage
		stacked_sansReglage = QFrame()
		vboxStacked = QVBoxLayout(stacked_sansReglage)
		txt=_(u"Pas de réglages ici")
		vboxStacked.addWidget(QLabel("<center>%s</center>" %txt))
		
		# Widgets du stacked avec un combo
		liste = [	(_(u"Impulse"),		"impulse"),\
				(_(u"Laplacian"),	"laplacian"),\
				(_(u"Poisson"),		"poisson")]
		stacked_pointillisme = FiltresAvecCombo(_(u"Sélection des couleurs"), liste)
		liste = [	(_(u"Rouge vif"),		"rouge_vif",		(198,0,0)),\
				(_(u"Rouge primaire"),		"rouge_primaire",	(199,0,101)),\
				(_(u"Vert perroquet"),		"vert_perroquet",	(0,199,0)),\
				(_(u"Vert acide et clair"),	"vert_acide_clair",	(146,198,1)),\
				(_(u"Bleu roi"),		"bleu_roi",		(0,145,254)),\
				(_(u"Bleu indigo"),		"bleu_indigo",		(145,145,255)),\
				(_(u"Bleu turquoise"),		"bleu_turquoise",	(145,255,255)),\
				(_(u"Jaune or"),		"jaune_or",		(234,198,0)),\
				(_(u"Jaune orange"),		"jaune_orange",		(255,197,0)),\
				(_(u"Saumon"),			"saumon",		(234,163,145)),\
				(_(u"Marron très clair"),	"marron_tres_clair",	(205,158,116)),\
				(_(u"Terre argileuse"),		"terre argileuse",	(243,159,123)),\
				(_(u"Gris colore rouge"),	"gris_colore_rouge",	(220,162,161)),\
				(_(u"Gris colore vert"),	"gris_colore_vert",	(162,200,161)),\
				(_(u"Gris colore bleu"),	"gris_colore_bleu",	(161,162,206)),\
				(_(u"Gris colore jaune"),	"gris_colore_jaune",	(200,200,162))]
		stacked_couleursPredef = FiltresAvecCombo(_(u"Type"), liste)
		liste = [	(_(u"Fond blanc, lignes noires"),	"fond_blanc_lignes_noires"),\
				(_(u"Fond noir, lignes blanches"),	"fond_noir_lignes_blanches")]
		stacked_evanescence = FiltresAvecCombo(_(u"Fond, forme"), liste)
		liste = [	(_(u"Négatif couleur"),	"negatif_couleur"),\
				(_(u"Négatif noir et blanc"),	"negatif_n_et_b")]
		stacked_negatif = FiltresAvecCombo(_(u"Type de négatif"), liste)
		
		#'''
		# Widgets du stacked avec un ou plusieurs combos et boite(s) de spin
		liste = [	(_(u"Noir"),		"noir"),\
				(_(u"Gris"),		"gris"),\
				(_(u"Blanc"),		"blanc"),\
				(_(u"Rouge"),	        "rouge"),\
				(_(u"Vert"),		"vert"),\
				(_(u"Bleu"),		"bleu"),\
				(_(u"Jaune"),		"jaune")]
		stacked_encadrePhoto = FiltresAvecCombo(_(u"Couleur du cadre"), liste)
		#'''
		
		# Widgets du stacked avec une seule boite de spin
		stacked_sepia = FiltresAvecSpin((_(u"% de sepia"),(50,99,60)))
		stacked_traitsNoirs = FiltresAvecSpin((_(u"valeur de charcoal"),(1,70,1)))
		stacked_peuCouleurs = FiltresAvecSpin((_(u"valeur de edge"),(30,90,40)))
		stacked_peintHuile = FiltresAvecSpin((_(u"valeur de la peinture à l'huile"),(1,20,1)))
		stacked_gamma = FiltresAvecSpin((_(u"valeur de gamma"),(0,20,1)))
		stacked_fonceClair = FiltresAvecSpin((_(u"1: Noir; 100: Normal; 400: Surexposé"),(1,400,100)))
		stacked_peintEau = FiltresAvecSpin((_(u"valeur de la liquidité"),(4,16,6)))
		stacked_basRelief = FiltresAvecSpin((_(u"Netteté du bas-relief"),(1,16,1)))
		
		# Widgets du stacked avec 2 boites de spin
		stacked_crayonPapier = FiltresAvecSpin((_(u"valeur de charcoal"),(1,70,1)),(_(u"valeur de spread"),(1,10,1)))
		stacked_blur = FiltresAvecSpin((_(u"radius"),(1,16,1)),(_("sigma"),(1,16,1)))
		stacked_traitCoulFond = FiltresAvecSpin((_(u"précision du trait (1: Net; 20: Flou)"),(1,20,1)),(_(u"largeur du trait (1 : Fin; 20 : Gras)"),(1,20,1)))
		stacked_seuillage = FiltresAvecSpin((_(u"seuillage bas"),(1,255,1)),(_(u"seuillage haut"),(1,255,128)))
		
		# Widgets du stacked avec 3 boites de spin
		stacked_imitationBd = FiltresAvecSpin((_(u"intensité du trait"),(10,40,28)),(_(u"réduction des couleurs"),(1,4,2)),(_(u"contraste des couleurs"),(1,8,6)))
		
		# Widgets du stacked avec 9 boites de spins
		stacked_couleursPersonnal = FiltresAvec9Spin()
		
		#=== Ajout de widgets au stacked ===#
		
		# Widgets du stacked sans réglage
		indexStacked_sansReglage = self.stacked.addWidget(stacked_sansReglage)
		
		# Widgets du stacked avec un combo
		indexStacked_pointillisme = self.stacked.addWidget(stacked_pointillisme)
		indexStacked_couleursPredef = self.stacked.addWidget(stacked_couleursPredef)
		indexStacked_evanescence = self.stacked.addWidget(stacked_evanescence)
		indexStacked_negatif = self.stacked.addWidget(stacked_negatif)
		
		# Widgets du stacked avec un/plusieurs combo(s) + boite(s) de spin
		indexStacked_encadrePhoto = self.stacked.addWidget(stacked_encadrePhoto)
		
		# Widgets du stacked avec une seule boite de spin
		indexStacked_sepia = self.stacked.addWidget(stacked_sepia)
		indexStacked_traitsNoirs = self.stacked.addWidget(stacked_traitsNoirs)
		indexStacked_peuCouleurs = self.stacked.addWidget(stacked_peuCouleurs)
		indexStacked_peintHuile = self.stacked.addWidget(stacked_peintHuile)
		indexStacked_gamma = self.stacked.addWidget(stacked_gamma)
		indexStacked_fonceClair = self.stacked.addWidget(stacked_fonceClair)
		indexStacked_peintEau = self.stacked.addWidget(stacked_peintEau )
		indexStacked_basRelief = self.stacked.addWidget(stacked_basRelief)
		
		# Widgets du stacked avec 2 boites de spin
		indexStacked_crayonPapier = self.stacked.addWidget(stacked_crayonPapier)
		indexStacked_blur = self.stacked.addWidget(stacked_blur)
		indexStacked_traitCoulFond = self.stacked.addWidget(stacked_traitCoulFond)
		indexStacked_seuillage = self.stacked.addWidget(stacked_seuillage)
		
		# Widgets du stacked avec 3 boites de spin
		indexStacked_imitationBd = self.stacked.addWidget(stacked_imitationBd)
		
		# Widgets du stacked avec 9 boites de spins
		indexStacked_couleursPersonnal = self.stacked.addWidget(stacked_couleursPersonnal)
		
		# boite de combo
		self.comboReglage=QComboBox()
		# Paramètres de la liste de combo: [(nom entrée, identifiant, index du stacked,
		# instance stacked),...]
		self.listeComboReglage=[\
		(_(u'Vieux Films (bandes + poussières)'),	'vieux_films',		indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Sepia'),					'sepia',		indexStacked_sepia,\
				stacked_sepia),\
		(_(u'Dessin 1: Traits noirs'),			'traits_noirs',		indexStacked_traitsNoirs,\
				stacked_traitsNoirs),\
		(_(u'Dessin 2: Crayon à papier'),		'crayon_papier',	indexStacked_crayonPapier,\
				stacked_crayonPapier),\
		(_(u'Dessin 3: Monochrome'),			'monochrome',		indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Dessin 4: Avec un peu de couleur'),	'peu_couleur',		indexStacked_peuCouleurs,\
				stacked_peuCouleurs),\
		(_(u"Peinture à l'Huile"),			'peinture_huile',	indexStacked_peintHuile,\
				stacked_peintHuile),\
		(_(u'Blur - Floutage'),				'floutage',		indexStacked_blur,\
				stacked_blur),\
		(_(u'Gamma'),					'gamma',		indexStacked_gamma,\
				stacked_gamma),\
		(_(u'Dessin 5: Traits de couleurs + Fond noir'),'trait_couleur_fond_noir',indexStacked_traitCoulFond,\
				stacked_traitCoulFond),\
		(_(u'Pointillisme'),				'pointillisme',		indexStacked_pointillisme,\
				stacked_pointillisme),\
		(_(u'Foncé-Clair'),				'fonce_clair',		indexStacked_fonceClair,\
				stacked_fonceClair),\
		(_(u"Peinture-à-l'eau"),			'peinture_eau',		indexStacked_peintEau,\
				stacked_peintEau),\
		(_(u'Dessin 6: Illustration en niveaux de gris'),'illustration_niveau_gris',indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Dessin 7: Traits très fins + couleur'),	'traits_fins&couleur',	indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Emboss'),					'emboss',		indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Sharpen (Détails)'),			'sharpen',		indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Niveaux de Gris'),				'niveau_gris',		indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Conversion en CMYK'),			'cmyk',			indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Couleurs prédéfinies'),			'couleurs_predefinies',	indexStacked_couleursPredef,\
				stacked_couleursPredef),\
		(_(u'Création de couleurs personnalisées'),	'couleurs_personnalisees',indexStacked_couleursPersonnal,\
				stacked_couleursPersonnal),\
		(_(u'Craie blanche sur tableau noir'),		'craie_blanche',	indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Bas-relief ou pierre sculptée'),		'bas_relief',		indexStacked_basRelief,\
				stacked_basRelief),\
		(_(u'Filtre Noir-Blanc (Ombre-Lumière)'),	'ombre_lumiere',	indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Amélioration des bords (image plus nette)'),'amelior_des_bords',	indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Réduction du bruit (débruitage)'),		'debruitage',		indexStacked_sansReglage,\
				stacked_sansReglage),\
		(_(u'Dessin 8: seuillage des images'),		'seuillage',		indexStacked_seuillage,\
				stacked_seuillage),\
		(_(u'Dessin 9: evanescence'),			'evanescence',		indexStacked_evanescence,\
				stacked_evanescence),\
		(_(u'Dessin 10: imitation bande dessinée'),	'imitation_bd',		indexStacked_imitationBd,\
				stacked_imitationBd),\
		(_(u'Négatif (inverse les couleurs/valeurs)'),	'negatif',		indexStacked_negatif,\
				stacked_negatif),\
		(_(u'Encadrement photographique'),		'encadre_photo',	indexStacked_encadrePhoto,\
				stacked_encadrePhoto),\
		]
		
		# Insertion des codecs de compression dans la boite de combo
		for i in self.listeComboReglage:
                	self.comboReglage.addItem(i[0])
		self.connect(self.comboReglage, SIGNAL("activated(int)"), self.changerComboReglage)
		
		hbox = QHBoxLayout()
		hbox.addWidget(QLabel(_(u'Type')))
		hbox.addWidget(self.comboReglage)
		hbox.setAlignment(Qt.AlignHCenter)
		
		vboxReglage.addLayout(hbox)
		vboxReglage.addWidget(self.stacked)
		vboxReglage.addStretch()
		
		#----------------
		# Onglet de log
		#----------------
		
		self.zoneAffichInfosImg = QTextEdit("")
		self.zoneAffichInfosImg.setReadOnly(True)
		self.framInfos=QFrame()
		vboxInfIm=QVBoxLayout(self.framInfos)
		vboxInfIm.addWidget(self.zoneAffichInfosImg)
		
		# -------------------------------------------------
		# Onglets d'affichage image source et destination
		# -------------------------------------------------
		
		# Là où s'afficheront les images
		self.afficheurImgSource=VisionneurImagePourEKD()
		self.afficheurImgDestination=VisionneurImagePourEKD()
		
		self.connect(self.tabwidget, SIGNAL("currentChanged(int)"), self.fctTab)
		
		vbox.addWidget(self.tabwidget)
		
		self.indexTabImgReglage = self.tabwidget.addTab(self.framReglage, _(u'Réglages'))
		self.indexTabImgSource = self.tabwidget.addTab(self.afficheurImgSource, _(u'Images sources'))
		self.indexTabImgDestin = self.tabwidget.addTab(self.afficheurImgDestination, _(u'Images après traitement'))
		self.indexTabImgInfos = self.tabwidget.addTab(self.framInfos, _(u'Infos'))
		
		# -------------------------------------------
		# widgets du bas : curseur + ligne + boutons
		# -------------------------------------------
		
		# Curseur de parcours des images source ou destination
		self.curseur = QSlider(Qt.Horizontal)
		self.curseur.setEnabled(False)
		
		
		# Drapeau servant à ne pas afficher 2 fois la même image
		self.verrouillerValueChange = 0
		self.connect(self.curseur,SIGNAL("sliderReleased()"), self.curseurRelache)
		self.connect(self.curseur,SIGNAL("sliderMoved(int)"), self.curseurBouge)
		self.connect(self.curseur,SIGNAL("sliderPressed()"), self.curseurPresse)
		self.connect(self.curseur,SIGNAL("valueChanged(int)"), self.curseurChange)
		
		
		
		#self.connect(self.curseur,SIGNAL("sliderReleased()"), self.curseurRelache)
		vbox.addWidget(self.curseur)
		
		# Boutons
		boutAide=QPushButton(_(u" Aide"))
		boutAide.setIcon(QIcon("Icones/icone_aide_128.png"))
		self.connect(boutAide, SIGNAL("clicked()"), self.afficherAide)
		
		self.boutAppliquer=QPushButton(_(u" Appliquer et sauver"))
		self.boutAppliquer.setIcon(QIcon("Icones/icone_appliquer_128.png"))
		
		# Bouton inactif au départ
		self.boutAppliquer.setEnabled(False)
		
		self.connect(self.boutAppliquer, SIGNAL("clicked()"), self.appliquer0)
		
		# Ligne de séparation juste au dessus des boutons
		ligne = QFrame()
		ligne.setFrameShape(QFrame.HLine)
		ligne.setFrameShadow(QFrame.Sunken)
		vbox.addWidget(ligne)
		vbox.addSpacing(-5)	# la ligne doit être plus près des boutons
		
		hbox=QHBoxLayout()
		hbox.addWidget(boutAide)
		hbox.addStretch()
		hbox.addWidget(self.boutAppliquer)
		vbox.addLayout(hbox)
		
		#-----------------------------
		# Barre de progression
		#-----------------------------
		
		self.progress=QProgressDialog(_(u"Conversion en cours..."), _(u"Arrêter"), 0, 100)
		self.progress.setWindowTitle(_(u'EnKoDeur-Mixeur. Fenêtre de progression'))
		self.progress.setMinimumWidth(500)
		self.progress.setMinimumHeight(100)
		self.connect(self.progress, SIGNAL("canceled()"), self.arretProgression)
		
		
		# affichage de la boîte principale
		self.setLayout(vbox)
	
	
	def curseurBouge(self, i):
		"""Montre le nom de l'image qui serait affichée si le curseur associée était relâché"""
		if self.tabwidget.currentIndex() == self.indexTabImgSource:
			self.statusBar.showMessage(self.listeImgSource[i])
		# Affiche l'image de destination le cas échéant
		self.affichImgDestin(i, verrou=1)
	
	def curseurPresse(self):
		self.verrouillerValueChange = 1
	
	def curseurChange(self, i):
		"Permet un changement de l'image avec les flèches gauche et droite \
		et avec un simple clic sur une partie du curseur"
		if not self.verrouillerValueChange:
			if self.tabwidget.currentIndex() == self.indexTabImgSource:
				self.afficheurImgSource.setImage(self.listeImgSource[i])
				self.statusBar.showMessage(self.listeImgSource[i])
				self.nvImgAffichee = [1, self.indexTabImgSource]
			# Affiche l'image de destination le cas échéant
			self.affichImgDestin(i)
	
	def curseurRelache(self):
		"""Affichage des images dans les 2 onglets prévus à cet effet"""
		self.verrouillerValueChange = 0
		i = self.curseur.value()
		print "Position %d du curseur principal" %i
		
		# Affichage d'une image dans l'onglet "images sources"
		if self.tabwidget.currentIndex() == self.indexTabImgSource:
			self.afficheurImgSource.setImage(self.listeImgSource[i])
			self.nvImgAffichee = [1, self.indexTabImgSource]
		
		self.affichImgDestin(i)
		
		print "[Nouvelle Image affichée?, indice d'onglet] :", self.nvImgAffichee, '\n'
	
	
	def affichImgDestin(self, i, verrou = 0):
		"""Affichage d'une image dans l'onglet "image après traitement" quand une conversion,
		même partielle a eu lieu"""
		# Le verrou sert à ne pas afficher d'image dans le cas de l'appel du signal du curseur sliderMoved
		if self.tabwidget.currentIndex() == self.indexTabImgDestin and self.conversionImg:
			if self.progress.wasCanceled(): # ... elle n'est pas achevée...
				if i > len(self.listeImgDestin)-1: # ... on sort du domaine valide du curseur
					if not verrou: self.afficheurImgDestination.setImage()
					self.statusBar.clearMessage()
				else: # on affiche une image convertie
					if not verrou: self.afficheurImgDestination.setImage(self.listeImgDestin[i])
					self.statusBar.showMessage(self.listeImgDestin[i])
			else: # La conversion a été entièrement réalisée
				if not verrou: self.afficheurImgDestination.setImage(self.listeImgDestin[i])
				self.statusBar.showMessage(self.listeImgDestin[i])
			self.nvImgAffichee = [1, self.indexTabImgDestin]
	
	
	def changerComboReglage(self, i):
		"""L'entrée sélectionnée de la boîte de combo modifie le QFrame de réglage du codec associée"""
		self.stacked.setCurrentIndex(self.listeComboReglage[i][2])
	
	
	def fctTab(self, i):
		"""Affichage d'une nouvelle image dans le QPixmap de l'onglet appelée si les conditions l'exigent. Accessoirement: rafraichissement du QPixmap pour que l'image soit affichée au milieu de la fenêtre et grisage/dégrisage du curseur principal"""
		
		# [bidouillage] Comme on n'arrive pas à afficher les images d'accueils
		# centrées de façon 'propre', en attendant on bidouille pour y
		# arriver: *.setTailleFenetre()
		
		print "Entrée : [Nouvelle Image affichée?, indice d'onglet] :", self.nvImgAffichee
		j = self.curseur.value()
		
		if i==self.indexTabImgReglage:
			self.curseur.setEnabled(False)
			self.statusBar.clearMessage()
		
		elif i==self.indexTabImgSource:
			print "Vous êtes sur l'onglet \"Images Sources\""
			if self.imgChargees:
				print "Des images sources ont déjà été chargées"
				self.curseur.setEnabled(True)
				if self.forcerAffichageImg == 1:
					print "Des images viennent d'être chargées -> affichage de la 1ère image du lot source"
					self.afficheurImgSource.setImage(self.listeImgSource[0])
					self.forcerAffichageImg = 0
					self.statusBar.showMessage(self.listeImgSource[0])
					self.nvImgAffichee[0] = 1 # pour avoir un nouvel affichage dans l'autre onglet
				elif self.nvImgAffichee == [1, self.indexTabImgDestin]:
					print "Le curseur a été déplacé dans l'onglet \"Images après traitement\" <-> une nouvelle image a été affichée dans l'onglet précédent.\n -> nouvelle image dans l'onglet \"Images Sources\""
					self.afficheurImgSource.setImage(self.listeImgSource[j])
					self.statusBar.showMessage(self.listeImgSource[j])
					self.nvImgAffichee[0] = 0
				else:
					print "pas de nouvel affichage (pas utile)"
					self.statusBar.showMessage(self.listeImgSource[j])
			else:
				print "Pas d'images sources chargées"
				self.afficheurImgSource.setTailleFenetre()
				self.statusBar.clearMessage()
			self.nvImgAffichee[1]=self.indexTabImgSource # dernier onglet sélectionnée contenant 1 QPixMap
		
		elif i==self.indexTabImgDestin:
			print "Vous êtes sur l'onglet \"Images après traitement\""
			if not self.imgChargees or not self.conversionImg:
				print "Des images sources n'ont pas déjà été chargées ou la conversion n'a pas eu lieu après le chargement des dernières images sources"
				self.afficheurImgDestination.setTailleFenetre()
				self.curseur.setEnabled(False)
				self.statusBar.clearMessage()
				self.nvImgAffichee[0] = 0
			else:
				print "Des images sources ont déjà été chargées et les dernières images chargées ont été converties"
				self.curseur.setEnabled(True)
				if self.forcerAffichageImg==1:
					print "La conversion vient d'avoir lieu -> affichage de la 1ère image du lot de destination"
					self.afficheurImgDestination.setImage(self.listeImgDestin[0])
					self.forcerAffichageImg = 0
					self.statusBar.showMessage(self.listeImgDestin[0])
					self.nvImgAffichee[0] = 1 # pour avoir un nouvel affichage dans l'autre onglet
				elif self.nvImgAffichee == [1, self.indexTabImgSource]:
					print "Le curseur a été déplacé dans l'onglet \"Images Sources\" <-> une nouvelle image a été affichée dans l'onglet précédent OU on force l'affichage de l'image"
					if j > len(self.listeImgDestin)-1:
						print "L'indice du curseur correspond à une image qui n'a pas pu être convertie car l'opération a été stoppée avant la fin\n  -> affichage de l'image d'accueil"
						self.afficheurImgDestination.setImage()
						self.statusBar.clearMessage()
					else:
						print "-> Nouvelle image dans l'onglet \"Images après traitement\""
						self.afficheurImgDestination.setImage(self.listeImgDestin[j])
						self.statusBar.showMessage(self.listeImgDestin[j])
					self.nvImgAffichee[0] = 0
					self.forcerAffichageImg = 0
				else:
					print "pas de nouvel affichage (pas utile)"
					if j > len(self.listeImgDestin)-1: self.statusBar.clearMessage()
					else: self.statusBar.showMessage(self.listeImgDestin[0])
			self.nvImgAffichee[1]=self.indexTabImgDestin # dernier onglet sélectionnée contenant 1 QPixMap
		
		elif i==self.indexTabImgInfos:
			self.curseur.setEnabled(False)
			self.statusBar.clearMessage()
		
		print "Sortie : [Nouvelle Image affichée?, indice d'onglet] :", self.nvImgAffichee, '\n'
	
	
	def metaFctTab(self, i):
		"""Changement d'onglet (conçu pour sélectionner les onglets "Images Source" après le chargement de nouvelles images sources ou "Images Après Traitement" après la conversion). But: s'assurer que la fonction associée au QTabWidget (affichage d'images, grisage/dégrisage du curseur...) sera bien appliquée même si on est déjà sur le bon onglet"""
		if self.tabwidget.currentIndex()!=i:
			self.tabwidget.setCurrentIndex(i)
		else: self.fctTab(i)
	
	
	def logFinal(self, titreFiltre):
		"""Affichage des informations de conversion"""
		a='#'*36
		# On ne récupère pas l'ancien % car il est arrondi
		pourCent=round(float(len(self.listeImgDestin))/len(self.listeImgSource)*100)
		pourCent = "%.0f" %pourCent
		b = a + '\n# ' + _(u'Filtre utilisé: ') + titreFiltre + '\n' + a + '\n'
		c = _(u"nombre d'images converties / nombre d'images sources")+" = "+str(len(self.listeImgDestin))+" / "\
		+str(len(self.listeImgSource))+" = " + pourCent +" %\n\n"
		
		# Le dernier '\n' est parfois nécessaire pour voir la dernière ligne!
		self.zoneAffichInfosImg.setText(b+c+self.infosImgTitre[0]+\
		"\n".join(self.listeImgSource)+'\n\n'+self.infosImgTitre[1]+"\n".join(self.listeImgDestin)+'\n')
	
	
	def ouvrirImages(self):
		"""Récupération du chemin des images séquence A sélectionnées + quelques opérations supplémentaires"""
		
		# Ouvrir images séquence A
		rep = self.base.getRepSource(self.listeImgSource, self.config)
		chemin_sequence_A=QFileDialog.getOpenFileNames(None, _(u"Ouvrir images séquence A"), rep, ("JPEG (*.jpg *.JPG *.jpeg *.JPEG);;PNG (*.png *.PNG);;GIF (*.gif *.GIF);;BMP (*.bmp *.BMP);;SGI (*.sgi *.SGI);;TIF (*.tif *.TIF);;TARGA (*.tga *.TGA);;PNM (*.pnm *.PNM);;PPM (*.ppm *.PPM)"))
		
		# Si pas de fichier sélectionné -> sortir de la fonction
		if chemin_sequence_A.count()==0: return
		
		# Convertir les differents fichiers selectionnes
		# en une liste de chaines de caracteres
		self.listeImgSource=[str(chemin_sequence_A[i_seqA]) for i_seqA in range(chemin_sequence_A.count())]
		self.listeImgSource.sort()
		
		self.base.setRepSource(self.listeImgSource, self.config)
		
		# Condition à respecter pour qu'une redimension ait lieu
		self.imgChargees = 1
		self.conversionImg = 0
		self.forcerAffichageImg = 1
		
		# Définition du domaine de validité du curseur
		self.curseur.setRange(0, len(self.listeImgSource)-1)
		self.curseur.setValue(0)
		
		# Changement d'onglet et fonctions associées
		self.metaFctTab(self.indexTabImgSource)
		
		# Activer le bouton 'appliquer'
		self.boutAppliquer.setEnabled(True)
		
		# Onglet de log
		self.zoneAffichInfosImg.setText(self.infosImgTitre[0]+"\n".join(self.listeImgSource))
	
	
	def stat_dim_img(self):
		"""Calcul statistique des dimensions des images les plus présentes dans le lot"""
		
		# Ouverture et mise ds une liste des dimensions des images
		listePrepaRedim=[Image.open(aA).size for aA in self.listeImgSource]
		
		# Merci beaucoup à Marc Keller de la liste: python at aful.org de m'avoir
		# aidé pour cette partie (les 4 lignes en dessous)
		dictSeq={}.fromkeys(listePrepaRedim, 0)
		for cle in listePrepaRedim: dictSeq[cle]+=1
		self.lStatDimSeq=sorted(zip(dictSeq.itervalues(), dictSeq.iterkeys()), reverse=1)
		self.dimStatImg=self.lStatDimSeq[0][1]
		
		print "Toutes les dimensions des images (avec le nbre d'images):", self.lStatDimSeq
		print 'Dimension des images la plus presente dans la sequence:', self.dimStatImg
		print "Nombre de tailles d'images différentes dans le lot :", len(self.lStatDimSeq)
		
		if len(self.lStatDimSeq)>1: return 0
		else: return 1
	
	
	def redim_img(self):
		"""Si l'utilisateur charge des images avec des tailles complètement différentes --> les images de la séquence  peuvent être redimensionnées"""
		
		if not self.stat_dim_img():
			reply = QMessageBox.warning(self, 'Message',
			_(u"Vos images ne sont pas toutes de la même taille. Voulez-vous redimensionner les images de sortie à la taille la plus répandue dans la séquence?"), QMessageBox.Yes, QMessageBox.No)
			if reply == QMessageBox.No:
				return
			
			# Les images de tailles différentes à la plus répandue sont redimensionnées
			# dans un répertoire temporaire.
			# Les images redimensionnées voient leur chemin modifié dans la liste des
			# chemins des images sources. Les autres chemins ne changent pas.
			index=0
			for chemImg in self.listeImgSource:
				obImg=Image.open(chemImg)
				if obImg.size!=self.dimStatImg:
					pass
				sRedim=obImg.resize(self.dimStatImg)
				chemSortie = self.repTampon+'redim/'+os.path.basename(chemImg)
				sRedim.save(chemSortie)
				self.listeImgSource[index] = chemSortie
				index += 1
	
	
	def appliquerCouleursPredef(self):
		"""Conversion des images pour le filtre: Couleurs Prédéfinies"""
		indexCombo = self.listeComboReglage[self.i][3].combo.currentIndex()
		entreeCombo = str(self.listeComboReglage[self.i][3].combo.itemData(indexCombo).toStringList()[0])
		
		if entreeCombo=="rouge_vif":
			couleur_Img_Predef=(
			1.0, 0.3, 0.0, 0,
			0.0, 0.0, 0.0, 0,
			0.0, 0.0, 0.0, 0)
		elif entreeCombo=="rouge_primaire":
			couleur_Img_Predef=(
			1.0, 0.3, 0.0, 0,
			0.0, 0.0, 0.0, 0,
			0.7, 0.0, 0.0, 0)
		elif entreeCombo=="vert_perroquet":
			couleur_Img_Predef=(
			0.0, 0.0, 0.0, 0,
			1.0, 0.3, 0.0, 0,
			0.0, 0.0, 0.0, 0)
		elif entreeCombo=="vert_acide_clair":
			couleur_Img_Predef=(
			1.0, 0.0, 0.0, 0,
			1.0, 0.3, 0.0, 0,
			0.0, 0.0, 0.0, 0)
		elif entreeCombo=="bleu_roi":
			couleur_Img_Predef=(
			0.0, 0.0, 0.0, 0,
			1.0, 0.0, 0.0, 0,
			1.0, 1.0, 0.0, 0)
		elif entreeCombo=="bleu_indigo":
			couleur_Img_Predef=(
			1.0, 0.0, 0.0, 0,
			1.0, 0.0, 0.0, 0,
			1.0, 1.0, 0.0, 0)
		elif entreeCombo=="bleu_turquoise":
			couleur_Img_Predef=(
			1.0, 0.0, 0.0, 0,
			1.0, 1.0, 0.0, 0,
			1.0, 1.0, 0.0, 0)
		elif entreeCombo=="jaune_or":
			couleur_Img_Predef=(
			0.64, 0.64, 0.10, 0,
			0.56, 0.56, 0.10, 0,
			0.0, 0.0, 0.0, 0)
		elif entreeCombo=="jaune_orange":
			couleur_Img_Predef=(
			1.0, 0.5, 0.5, 0,
			1.0, 0.3, 0.0, 0,
			0.0, 0.0, 0.0, 0)
		elif entreeCombo=="saumon":
			couleur_Img_Predef=(
			1.0, 0.5, 0.0, 0,
			1.0, 0.1, 0.0, 0,
			1.0, 0.0, 0.0, 0)
		elif entreeCombo=="marron_tres_clair":
			couleur_Img_Predef=(
			0.95, 0.38, 0.0, 0,
			0.90, 0.15, 0.0, 0,
			0.48, 0.26, 0.0, 0)
		elif entreeCombo=="terre argileuse":
			couleur_Img_Predef=(
			0.96, 0.58, 0.0, 0,
			0.56, 0.44, 0.0, 0,
			0.46, 0.32, 0.0, 0)
		elif entreeCombo=="gris_colore_rouge":
			couleur_Img_Predef=(
			0.68, 0.68, 0.0, 0,
			0.50, 0.50, 0.0, 0,
			0.50, 0.50, 0.0, 0)
		elif entreeCombo=="gris_colore_vert":
			couleur_Img_Predef=(
			0.50, 0.50, 0.0, 0,
			0.62, 0.62, 0.0, 0,
			0.50, 0.50, 0.0, 0)
		elif entreeCombo=="gris_colore_bleu":
			couleur_Img_Predef=(
			0.50, 0.50, 0.0, 0,
			0.50, 0.50, 0.0, 0,
			0.64, 0.64, 0.0, 0)
		elif entreeCombo=="gris_colore_jaune":
			couleur_Img_Predef=(
			0.62, 0.62, 0.0, 0,
			0.62, 0.62, 0.0, 0,
			0.50, 0.50, 0.0, 0)
		
		for self.j in self.listeIndex:
			self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
			obImg = Image.open(self.listeImgSource[self.j])
			convert = obImg.convert("RGB", couleur_Img_Predef)
			convert.save(self.cheminCourantSauv)
			if not self.opReccurApresApp(): return
	
	
	def appliquerVieuxFilms(self):
		"""Conversion des images pour le filtre: Vieux Films"""
		listePous=[
		'Filtre_vf/Poussier/pous_001.png','Filtre_vf/Poussier/pous_002.png',
		'Filtre_vf/Poussier/pous_003.png','Filtre_vf/Poussier/pous_004.png',
		'Filtre_vf/Poussier/pous_005.png','Filtre_vf/Poussier/pous_006.png',
		'Filtre_vf/Poussier/pous_007.png','Filtre_vf/Poussier/pous_008.png',
		'Filtre_vf/Poussier/pous_009.png','Filtre_vf/Poussier/pous_010.png',
		'Filtre_vf/Poussier/pous_011.png','Filtre_vf/Poussier/pous_012.png',
		'Filtre_vf/Poussier/pous_013.png','Filtre_vf/Poussier/pous_014.png',
		'Filtre_vf/Poussier/pous_015.png','Filtre_vf/Poussier/pous_016.png',
		'Filtre_vf/Poussier/pous_017.png','Filtre_vf/Poussier/pous_018.png',
		'Filtre_vf/Poussier/pous_019.png','Filtre_vf/Poussier/pous_020.png',
		'Filtre_vf/Poussier/pous_021.png','Filtre_vf/Poussier/pous_022.png',
		'Filtre_vf/Poussier/pous_023.png','Filtre_vf/Poussier/pous_024.png',
		'Filtre_vf/Poussier/pous_025.png','Filtre_vf/Poussier/pous_026.png']
		
		for self.j in self.listeIndex:
			os.system("convert -blur 1%x1% -fx intensity ""\""+self.listeImgSource[self.j]+"\" "+self.repTampon+"vf_vieux_films1")
			
			img0=Image.open(self.listeImgSource[self.j])
			taille=img0.size
			
			os.system("convert "+listePous[randrange(len(listePous))]+" -resize "+ str(taille[0])+'x'+str(taille[1])+"! "+self.repTampon+"vf_vieux_films2")
			
			img1 = Image.open(self.repTampon+"vf_vieux_films2")
			img2 = Image.open(self.repTampon+"vf_vieux_films1")
			compos = Image.composite(img1,img2,img1)
			
			self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
			compos.save(self.cheminCourantSauv)
			
			if not self.opReccurApresApp(): return
			self.j += 1
	
	
	def appliquerSeuillage(self):
		""" Dessin 8: seuillage (avec intégration de syntaxe Numpy) """
		for self.j in self.listeIndex:
			# Ouverture des images
			obImg = Image.open(self.listeImgSource[self.j])
			# Récup réglages de seuillage bas et seuillage haut
			spin1 = self.listeComboReglage[self.i][3].spin1.value() # seuil bas
			spin2 = self.listeComboReglage[self.i][3].spin2.value() # seuil haut
			# La valeur de seuil bas ne doit jamais être supérieure ou égale à la valeur de
			# seuil haut (produirait des images sans interêt) --> dans ce cas le processus
			# s'arrête et un message avertit l'utilisateur. 
			if spin1>=spin2:
				erreur=QMessageBox(self)
				erreur.setText(_(u"Attention, <b>la valeur de seuillage bas doit obligatoirement être inférieure à la valeur de seuillage haut</b>. La conversion demandée ne sera pas effectuée. Refaites vos réglages correctement et recommencez l'opération."))
				erreur.setWindowTitle(_(u"Erreur de réglage"))
				erreur.setIcon(QMessageBox.Warning)
				erreur.exec_()
				break
			else: pass
			# Conversion et sauvegarde en niveaux de gris
			imageNDG = obImg.convert("L")
			# Recup dimensions de l'image
			wSeuil, hSeuil = imageNDG.size
			# Filtre egalisateur pour renforcer les zones claires et les zones foncées
			egaliseNDG_Seuil = ImageOps.equalize(imageNDG)
			# Creation d'une nouvelle image
			nouvImgNDG_Seuil = Image.new("L", (wSeuil, hSeuil))
			# Insertion data ds nouvImgNDG_Seuil
			nouvImgNDG_Seuil.putdata(egaliseNDG_Seuil.getdata())
			# Récup des données contenues ds l'image et mises dans un tableau par Numpy
			dataNDG_Seuil=array(nouvImgNDG_Seuil)
			# Aplatissement du tableau pour traitement
			aplatNDG_Seuil=dataNDG_Seuil.flat
			# Condition: (apres parcours de chaque element du tableau)
			# ==> correspond en python classique a : 
			# if aplatNDG_Seuil>=spin1 and aplatNDG_Seuil<=spin2:
			# Les pixels blancs seront placés ici.
			condSeuil=(aplatNDG_Seuil>=spin1)&(aplatNDG_Seuil<=spin2)
			# Selon la condition, remplacement de chaque element/pixel
			# soit par 0 --> noir, soit par 255 --> blanc .
			idSeuil=where(condSeuil, 0, 255)
			# Creation d'une nouvelle image
			nouvImgBinaire=Image.new("L", (wSeuil, hSeuil))
			# Insertion data ds nouvImgBinaire et conversion en liste classique
			nouvImgBinaire.putdata(idSeuil.tolist())
			# Sauvegarde
			self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
			nouvImgBinaire.save(self.cheminCourantSauv)
			# Fin
			if not self.opReccurApresApp(): return
			self.j += 1
	
	
	def appliquerEvanescence(self):
		""" Dessin 9: traits noirs, fond blanc (avec intégration de syntaxe Numpy) """
		for self.j in self.listeIndex:
			# Récupération de l'index et l'entrée du combo de sélection
			indexCombo = self.listeComboReglage[self.i][3].combo.currentIndex()
			entreeCombo = str(self.listeComboReglage[self.i][3].combo.itemData(indexCombo).toStringList()[0])
			# Ouverture des images. Conversion et sauvegarde en niveaux de gris
			obImg = Image.open(self.listeImgSource[self.j]).convert("L")
			# Recup dimensions de l'image
			w, h = obImg.size
			# Kernel 5x5 Réduction du Bruit
			imKernel = obImg.filter(ImageFilter.Kernel((5, 5), (-2, -2, -2, -2, -2, -1, -1, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, -1, -1, -2, -2, -2, -2, -2)))
			imKernel.save(self.repTampon+'_tmp_g546gf546ezr53ww7i.png', 'PNG')
			# Ouverture de l'image temporaire
			ouvImg = Image.open(self.repTampon+'_tmp_g546gf546ezr53ww7i.png')
			# Filtre egalisateur pour renforcer les zones claires et les zones foncées
			egalise = ImageOps.equalize(ouvImg)
			# Creation d'une nouvelle image
			nouvImg = Image.new("L", (w, h))
			# Insertion data ds nouvImg
			nouvImg.putdata(egalise.getdata())
			# Récup des données contenues ds l'image et mises dans un tableau par Numpy
			data = array(nouvImg)
			# Aplatissement du tableau pour traitement
			aplat = data.flat
			# Condition: (apres parcours de chaque element du tableau)
			condition=(aplat>=1)&(aplat<=255)
			# Selon la condition, remplacement de chaque element/pixel
			# soit par 255 --> blanc, soit par 0 --> noir
			if entreeCombo=='fond_blanc_lignes_noires': idCond = where(condition, 255, 0)
			elif entreeCombo=='fond_noir_lignes_blanches': idCond = where(condition, 0, 255)
			# Creation d'une nouvelle image
			nouvImgBinaire=Image.new("L", (w, h))
			# Insertion data ds nouvImgBinaire et conversion en liste classique
			nouvImgBinaire.putdata(idCond.tolist())
			# Sauvegarde
			self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
			nouvImgBinaire.save(self.cheminCourantSauv)
			# Fin
			if not self.opReccurApresApp(): return
			self.j += 1
			# Purge du répertoire tampon
			os.remove(self.repTampon+'_tmp_g546gf546ezr53ww7i.png')
	
	
	def appliquerImitationBd(self):
		""" Dessin 10: imitation bande dessinée (avec intégration [un peu] de syntaxe Numpy) """
		for self.j in self.listeIndex:
		# Récup réglages ci-dessous
			spin1 = self.listeComboReglage[self.i][3].spin1.value() # intensité des traits
			spin2 = self.listeComboReglage[self.i][3].spin2.value() # réduction des couleurs
			spin3 = self.listeComboReglage[self.i][3].spin3.value() # contraste de couleurs
			# Ouverture des images. Conversion et sauvegarde en niveaux de gris
			obImg = Image.open(self.listeImgSource[self.j]).convert("L")
			# Recup dimensions de l'image
			w, h = obImg.size
			
			# Partie 1 ------ Détection du contour des formes et traçage des futurs traits noirs ----
			# Kernel 5x5 Réduction du Bruit + ajout de la valeur de spin1 au centre de la matrice
			imKernel = obImg.filter(ImageFilter.Kernel((5, 5), (-2, -2, -2, -2, -2, -1, -1, 0, 0, 0, 0, 0, spin1, 0, 0, 0, 0, 0, -1, -1, -2, -2, -2, -2, -2)))
			imKernel.save(self.repTampon+'tmp_gds568ec4u5hg53g7s9m4rt.png', 'PNG')
			# Ouverture de l'image temporaire
			ouvImg = Image.open(self.repTampon+'tmp_gds568ec4u5hg53g7s9m4rt.png')
			# Filtre egalisateur pour renforcer les zones claires et les zones foncées
			egalise = ImageOps.equalize(ouvImg)
			# Creation d'une nouvelle image
			nouvImg = Image.new("L", (w, h))
			# Insertion data ds nouvImg
			nouvImg.putdata(egalise.getdata())
			# Récup des données contenues ds l'image et mises dans un tableau par Numpy
			data = array(nouvImg)
			# Aplatissement du tableau pour traitement
			aplat = data.flat
			# Condition: (apres parcours de chaque element du tableau)
			condition = (aplat>=1)&(aplat<=255)
			# Selon la condition, remplacement de chaque element/pixel
			# soit par 255 --> blanc, soit par 0 --> noir
			idCond = where(condition, 255, 0)
			# Creation d'une nouvelle image
			nouvImgBinaire = Image.new("L", (w, h))
			# Insertion data ds nouvImgBinaire et conversion en liste classique
			nouvImgBinaire.putdata(idCond.tolist())
			# Recup des donnees
			listeAlpha_1=list(nouvImgBinaire.getdata())
			# Creation de la liste newListRGBAbin
			newListRGBAbin=[]
			for parcListe in listeAlpha_1:
				# Si on a des pixels blancs et transparents dans listeAlpha_1 alors on injecte 
				# des pixels blancs transparents mais ce  coup-ci en mode RGBA .
				if parcListe==255: newListRGBAbin.append((255, 255, 255, 0))
				# (Autre) si on a des pixels noirs et opaques dans listeAlpha_1
				# alors on injecte des pixels noirs opaques mais ce coup-ci en
				# mode RGBA .
				else: newListRGBAbin.append((0, 0, 0, 255))
				
			# Creation d'une nouvelle image
			nouvImgRGBA=Image.new("RGBA", (w, h))
			# Insertion data ds nouvImgRGBA
			nouvImgRGBA.putdata(newListRGBAbin)
			# Sauvegarde image temporaire
			nouvImgRGBA.save(self.repTampon+'tmp_gds568ec4u5hg53g7s9m4rt.png', 'PNG')
			# Attention il faut diviser par 10.0 la valeur de spin3 (c'est à dire contraste 
			# de couleurs). On divise par 10.0 et pas 10 !.
			spin3=float(spin3/10.0)
			
			# Partie 2 ------ Réduction/postérisation/contraste des couleurs du fond de l'image -----
			# Ouverture de l'image principale dans le lot
			imPrinc=Image.open(self.listeImgSource[self.j])
			# Application du filtre pour la reduction des couleurs
			imPosterize=ImageOps.posterize(imPrinc, spin2)
			# Conversion en RGBA pour pouvoir compositer ...
			imPosterize.convert('RGBA')
			imPosterize.save(self.repTampon+'tmp_gds89gfdt39xfg6d9qxx1f.png', 'PNG')
			# Ouverture de l'image posterizee pour poursuite du traitement (application contraste)
			imPostTraitC=Image.open(self.repTampon+'tmp_gds89gfdt39xfg6d9qxx1f.png')
			# Application du filtre contraste et sauvegarde du fichier temporaire
			imContraste=ImageEnhance.Contrast(imPostTraitC)
			imContraste.enhance(spin3).save(self.repTampon+'tmp_gds486fsf68q2wx5k7u1oop.png', 'PNG')
			# Ouverture de l'image posterizee ensuite contrastée poursuite du traitement ...
			imOpc=Image.open(self.repTampon+'tmp_gds486fsf68q2wx5k7u1oop.png')
			# Conversion en RGBA pour pouvoir compositer ...
			imOpc.convert('RGBA')
			
			# Partie finale --- Compositing entre les traits de la partie 1 et couleurs de partie 2 -
			# Attention il s'agit bien de l'image tampon: tmp_gds568ec4u5hg53g7s9m4rt.png
			# C'est l'image qui contient les traits noirs (contours des objets)
			# Traits noirs + le fond blanc a été remplacé par un fond transparent
			imFondTransp=Image.open(self.repTampon+'tmp_gds568ec4u5hg53g7s9m4rt.png')
			# Compositing (traitement final)
			compoContCoul=Image.composite(imFondTransp, imOpc, imFondTransp)
			
			# Sauvegarde
			self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
			compoContCoul.save(self.cheminCourantSauv)
			
			# Purge des fichiers dans le rep tampon
			os.remove(self.repTampon+'tmp_gds568ec4u5hg53g7s9m4rt.png')
			os.remove(self.repTampon+'tmp_gds89gfdt39xfg6d9qxx1f.png')
			os.remove(self.repTampon+'tmp_gds486fsf68q2wx5k7u1oop.png')

			# Fin
			if not self.opReccurApresApp(): return
			self.j += 1
	
	
	def appliquerNegatif(self):
		""" Negatif: inverse les couleurs (ou les valeurs en cas de conversion en noir et blanc) """
		for self.j in self.listeIndex:
			# Récupération de l'index et l'entrée du combo de sélection
			indexCombo = self.listeComboReglage[self.i][3].combo.currentIndex()
			entreeCombo = str(self.listeComboReglage[self.i][3].combo.itemData(indexCombo).toStringList()[0])
			# Ouverture des images
			obImg = Image.open(self.listeImgSource[self.j])
			if entreeCombo=='negatif_couleur': 
				negatif = ImageOps.invert(obImg)
			elif entreeCombo=='negatif_n_et_b':
				obImg = obImg.convert("L")
				negatif = ImageOps.invert(obImg)	
			# Sauvegarde
			self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
			negatif.save(self.cheminCourantSauv)
			# Fin
			if not self.opReccurApresApp(): return
			self.j += 1
	
	
	def appliquerEncadrePhoto(self):
		""" Encadrement photographique: appose un cadre autour des images """
		for self.j in self.listeIndex:
			# Récupération de l'index et l'entrée du combo de sélection
			indexCombo = self.listeComboReglage[self.i][3].combo.currentIndex()
			entreeCombo = str(self.listeComboReglage[self.i][3].combo.itemData(indexCombo).toStringList()[0])
			# Ouverture des images
			obImg = Image.open(self.listeImgSource[self.j])
			if entreeCombo=='noir': couleur = (0, 0, 0)
			elif entreeCombo=='gris': couleur = (128, 128, 128)
			elif entreeCombo=='blanc': couleur = (255, 255, 255)
			elif entreeCombo=='rouge': couleur = (255, 0, 0)
			elif entreeCombo=='vert': couleur = (0, 255, 0)
			elif entreeCombo=='bleu': couleur = (0, 0, 255)
			elif entreeCombo=='jaune': couleur = (255, 255, 0)
			# Application du filtre
			cadre = ImageOps.expand(obImg, 40, couleur)
			# Sauvegarde
			self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
			cadre.save(self.cheminCourantSauv)
			# Fin
			if not self.opReccurApresApp(): return
			self.j += 1
	
	
	def arretProgression(self):
		"""Si le filtre appliqué est 100 % shell, alors la conversion est immédiatement stoppée après un clic sur le bouton de la QProgessDialog. Pas la peine d'attendre la fin de la conversion de l'image en cours comme pour les autres types de filtres."""
		if self.listeComboReglage[self.i][1] in self.filtresPython: return
		self.terminerFiltreShell = 1
		self.process.kill()
		if len(self.listeImgDestin)!=0:
			self.conversionImg = 1
			self.forcerAffichageImg = 1
			self.logFinal(self.listeComboReglage[self.i][0])
			self.tabwidget.setCurrentIndex(self.indexTabImgInfos)
		else: # Onglet de log -> on remet les infos de départ
			self.zoneAffichInfosImg.setText(self.infosImgTitre[0]+"\n".join(self.listeImgSource))
	
	
	def finConversion(self, statutDeSortie):
		"""Choses à faire à la fin de l'encodage d'une image quand le filtre sélectionné est constitué d'une seule commande shell"""
		
		if statutDeSortie==1:
			print "Problème lors de la conversion!"
			messageAide=QMessageBox(self)
			messageAide.setText(_(u"Une erreur s'est produite durant la conversion"))
			messageAide.setWindowTitle(_(u"Aide"))
			messageAide.setIcon(QMessageBox.Warning)
			messageAide.exec_()
			self.logFinal(self.listeComboReglage[self.i][0])
			self.tabwidget.setCurrentIndex(self.indexTabImgInfos)
			return
		
		# On ne continue pas si l'utilisateur l'a décidé
		elif self.terminerFiltreShell: return
		
		# On passe à l'image suivante s'il en reste
		elif self.opReccurApresApp():
			self.appliquer()
	
	
	def opReccurApresApp(self):
		"""Opérations à effectuer après chaque appel du moteur."""
		if self.listeComboReglage[self.i][1] in self.filtresPython:
			modulePython = 1 # conversion python (+ shell pour certains filtres)
		else: modulePython = 0 # conversion 100% shell
		
		self.listeImgDestin.append(self.cheminCourantSauv)
		pourCent=int((float(self.j+1)/self.nbrImg)*100)
		
		self.progress.setValue(pourCent)
		#!!!Rafraichissement indispensable pour la transmission immédiate du signal QProgressDialog().wasCanceled
		if modulePython: QApplication.processEvents()
		
		# Incrémentation de l'indice du fichier source pour une conversion 100% commande shell
		if not modulePython: self.j += 1
		
		# Opérations de fin de conversion
		if pourCent==100:
			# Condition à respecter pour qu'un affichage d'une nouvelle image ait lieu dans l'onglet "Images après traitement"
			self.conversionImg = 1
			self.forcerAffichageImg = 1
			# Boite de dialogue d'information
			messageAide=QMessageBox(self)
			messageAide.setText(_(u"Le filtre a été appliqué avec succès!"))
			messageAide.setWindowTitle(self.listeComboReglage[self.i][0])
			messageAide.setIcon(QMessageBox.Information)
			messageAide.exec_()
			# Mise-à-jour du log
			self.logFinal(self.listeComboReglage[self.i][0])
			# Changement d'onglet et fonctions associées
			self.metaFctTab(self.indexTabImgDestin)
			return 0
		
		# Opérations à faire lors de l'arrêt de la conversion suite au clic sur le bouton annuler de la barre de progression
		elif self.progress.wasCanceled():
			if modulePython:
				# Condition à respecter pour qu'un affichage d'une nouvelle image ait lieu dans l'onglet "Images après traitement"
				self.conversionImg = 1
				self.forcerAffichageImg = 1
				# Mise-à-jour du log
				self.logFinal(self.listeComboReglage[self.i][0])
				# Affichage de l'onglet d'infos
				self.tabwidget.setCurrentIndex(self.indexTabImgInfos)
			return 0
		
		return 1
	
	
	def appliquer0(self):
		"""Préparation de la conversion"""
		
		# Redimensionner les images de tailles différentes?
		self.redim_img()
		
		rep = self.base.getRepSource(self.listeImgSource, self.config)
		self.cheminSauv=str(QFileDialog.getSaveFileName(None, _(u"Sauver"), rep, _(u"Tous les fichiers *.*")))
		
		if self.cheminSauv=='': return
		
		print 'Chemin+nom de sauvegarde:', self.cheminSauv
		
		# Liste des fichiers de destination
		self.listeImgDestin = []
		
		self.curseur.setValue(0)
		
		# Extension/format des images
		self.ext = os.path.splitext(self.listeImgSource[0])[1]
		
		# Liste des indices des images [0,1,2,...,nombre d'images-1]
		self.listeIndex = range(len(self.listeImgSource))
		
		# Nombre d'images sources
		self.nbrImg = len(self.listeImgSource)
		
		# Récupération de l'identifiant du codec
		self.i = self.comboReglage.currentIndex()
		
		# Indice de l'image à convertir
		self.j = 0
		
		# drapeau (réinitialisation): terminer le filtre avec commande 100% shell?
		self.terminerFiltreShell = 0
		
		self.progress.reset() # wasCanceled est remis à 0 -> la conversion ne s'arrête pas à la 1ère img
		self.progress.show()
		self.progress.setValue(0)
		QApplication.processEvents()
		
		# Faire en sorte que la boite de dialogue ait le temps de s'afficher correctement
		QTimer.singleShot(0, self.appliquer)
	
	
	def appliquer(self):
		"""Conversion des images"""
		
		# L'incrémentation de l'indice de l'image source se fait dans cette fonction si le filtre choisie
		# contient un moteur module python, ou dans opReccurApresApp() pour 1 filtre 100% commande shell
		print "Indice de l'image à encoder :", self.j
		self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
		
		#------------------------------
		# Filtres 100% commande shell
		#------------------------------
		
		if self.listeComboReglage[self.i][1] in ['sepia','traits_noirs','peu_couleur','peinture_huile',\
					'gamma','fonce_clair','peinture_eau','bas_relief']:
			spin = str(self.listeComboReglage[self.i][3].spin.value())
			if self.listeComboReglage[self.i][1]=='sepia':
				self.process.start("convert -sepia-tone "+spin+"% -monitor "+"\""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
			elif self.listeComboReglage[self.i][1]=='traits_noirs':
				self.process.start("convert -charcoal "+spin+" -monochrome "+"\""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
			elif self.listeComboReglage[self.i][1]=='peu_couleur':
				self.process.start("convert -enhance -equalize -edge "+spin+" -colorize 6,12,20 "+"\""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
			elif self.listeComboReglage[self.i][1]=='peinture_huile':
				self.process.start("convert -paint "+spin+" \""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
			elif self.listeComboReglage[self.i][1]=='gamma':
				self.process.start("convert -gamma "+spin+" \""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
			elif self.listeComboReglage[self.i][1]=='fonce_clair':
				self.process.start("convert -modulate "+spin+" \""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
			elif self.listeComboReglage[self.i][1]=='peinture_eau':
				self.process.start("convert -noise "+spin+" -gamma 1.4 "+"\""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
			elif self.listeComboReglage[self.i][1]=='bas_relief':
				self.process.start("convert -paint "+spin+" -shade 120x45 "+"\""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
		
		elif self.listeComboReglage[self.i][1] in ['crayon_papier','floutage','trait_couleur_fond_noir']:
			spin1 = str(self.listeComboReglage[self.i][3].spin1.value())
			spin2 = str(self.listeComboReglage[self.i][3].spin2.value())
			if self.listeComboReglage[self.i][1]=='crayon_papier':
				self.process.start("convert -spread "+spin2+" -charcoal "+spin1+" \""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
			elif self.listeComboReglage[self.i][1]=='floutage':
				self.process.start("convert -blur "+spin1+'%'+'x'+spin2+"% "+"\""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
			elif self.listeComboReglage[self.i][1]=='trait_couleur_fond_noir':
				self.process.start("convert -median "+spin1+" -edge "+spin2+" \""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
		
		elif self.listeComboReglage[self.i][1]=='monochrome':
			self.process.start("convert -monochrome "+"\""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
		
		elif self.listeComboReglage[self.i][1]=='pointillisme':
			indexCombo = self.listeComboReglage[self.i][3].combo.currentIndex()
			entreeCombo = str(self.listeComboReglage[self.i][3].combo.itemData(indexCombo).toStringList()[0])
			self.process.start("convert +noise "+entreeCombo+" \""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
		
		elif self.listeComboReglage[self.i][1]=='craie_blanche':
			self.process.start("convert -blur 2x2 -fx 'log(r*60*pi)' -edge 0.1 -blur 2x2 "+"\""+self.listeImgSource[self.j]+"\" "+"\""+self.cheminCourantSauv+"\"")
		
		#--------------------------------------------------------
		# Filtres utilisant notamment un module python (ex. PIL)
		#--------------------------------------------------------
		
		elif self.listeComboReglage[self.i][1]=='vieux_films':
			self.appliquerVieuxFilms()
		
		elif self.listeComboReglage[self.i][1]=='illustration_niveau_gris':
			for self.j in self.listeIndex:
				self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
				obImg = Image.open(self.listeImgSource[self.j])
				convert = obImg.convert("1")
				convert.save(self.cheminCourantSauv)
				if not self.opReccurApresApp(): return
		
		elif self.listeComboReglage[self.i][1]=='traits_fins&couleur':
			for self.j in self.listeIndex:
				self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
				obImg = Image.open(self.listeImgSource[self.j])
				convert = obImg.filter(ImageFilter.EDGE_ENHANCE_MORE)
				convert.save(self.cheminCourantSauv)
				if not self.opReccurApresApp(): return
		
		elif self.listeComboReglage[self.i][1]=='emboss':
			for self.j in self.listeIndex:
				self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
				obImg = Image.open(self.listeImgSource[self.j])
				convert = obImg.filter(ImageFilter.EMBOSS)
				convert.save(self.cheminCourantSauv)
				if not self.opReccurApresApp(): return
		
		elif self.listeComboReglage[self.i][1]=='sharpen':
			for self.j in self.listeIndex:
				self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
				obImg = Image.open(self.listeImgSource[self.j])
				convert = obImg.filter(ImageFilter.SHARPEN)
				convert.save(self.cheminCourantSauv)
				if not self.opReccurApresApp(): return
		
		elif self.listeComboReglage[self.i][1]=='niveau_gris':
			for self.j in self.listeIndex:
				self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
				obImg = Image.open(self.listeImgSource[self.j])
				convert = obImg.convert("L")
				convert.save(self.cheminCourantSauv)
				if not self.opReccurApresApp(): return
		
		elif self.listeComboReglage[self.i][1]=='cmyk':
			for self.j in self.listeIndex:
				self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
				obImg = Image.open(self.listeImgSource[self.j])
				convert = obImg.convert("CMYK")
				convert.save(self.cheminCourantSauv)
				if not self.opReccurApresApp(): return
				
		elif self.listeComboReglage[self.i][1]=='amelior_des_bords':
			for self.j in self.listeIndex:
				self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
				obImg = Image.open(self.listeImgSource[self.j])
				# Application de la matrice d'amélioration des bords. Matrice trouvee ici :
				# http://blogs.codes-sources.com/tkfe/archive/2005/04/15/6004.aspx
				convert = obImg.filter(ImageFilter.Kernel((3, 3), (-1, -2, -1, -2, 16, -2, -1, -2, -1)))
				convert.save(self.cheminCourantSauv)
				if not self.opReccurApresApp(): return
				
		elif self.listeComboReglage[self.i][1]=='debruitage':
			for self.j in self.listeIndex:
				self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
				obImg = Image.open(self.listeImgSource[self.j])
				# Application de la matrice de débruitage. Attention !!! ne fonctionne pas
				# avec les images GIF (.gif)
				convert = obImg.filter(ImageFilter.Kernel((5, 5), (2, 4, 5, 4, 2, 4, 9, 12, 9, 4, 5, 12, 15, 12, 5, 4, 9, 12, 9, 4, 2, 4, 5, 4, 2)))
				convert.save(self.cheminCourantSauv)
				if not self.opReccurApresApp(): return
		
		elif self.listeComboReglage[self.i][1]=='evanescence':
			self.appliquerEvanescence()
		
		elif self.listeComboReglage[self.i][1]=='seuillage':
			self.appliquerSeuillage()
			
		elif self.listeComboReglage[self.i][1]=='imitation_bd':
			self.appliquerImitationBd()
			
		elif self.listeComboReglage[self.i][1]=='negatif':
			self.appliquerNegatif()
			
		elif self.listeComboReglage[self.i][1]=='encadre_photo':
			self.appliquerEncadrePhoto()
		
		elif self.listeComboReglage[self.i][1]=='couleurs_predefinies':
			self.appliquerCouleursPredef()
		
		elif self.listeComboReglage[self.i][1]=='ombre_lumiere':
			for self.j in self.listeIndex:
				self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
				os.system("convert -fx 'cos(3.22*pi*R)*100' "+"\""+self.listeImgSource[self.j]+"\" "+self.repTampon+"vf_ombre_lumiere")
				obImg = Image.open(self.repTampon+"vf_ombre_lumiere")
				convert = obImg.filter(ImageFilter.SMOOTH_MORE)
				convert.save(self.cheminCourantSauv)
				if not self.opReccurApresApp(): return
		
		elif self.listeComboReglage[self.i][1]=='couleurs_personnalisees':
			listeCouleurImgPerso=[]
			for k in range(3):
				for l in range(3):
					listeCouleurImgPerso.append(float('0.'+str(self.listeComboReglage[self.i][3].spin[k][l].value())))
				listeCouleurImgPerso.append(0)
			
			print listeCouleurImgPerso
			
			for self.j in self.listeIndex:
				self.cheminCourantSauv = self.cheminSauv+'_'+string.zfill((self.j+1), 6)+self.ext
				obImg=Image.open(self.listeImgSource[self.j])
				convert = obImg.convert("RGB", listeCouleurImgPerso)
				convert.save(self.cheminCourantSauv)
				if not self.opReccurApresApp(): return
	
	
	def afficherAide(self):
		"""Boîte de dialogue de l'aide"""
		messageAide=QMessageBox(self)
		messageAide.setText(_(u"Blablablabla ... blabla."))
		messageAide.setWindowTitle(_(u"Aide"))
		messageAide.setIcon(QMessageBox.Information)
		messageAide.exec_()