#-*- coding:utf-8 -*-
from ImageChops import difference
from Image import *
import ImageStat

from sys import exit
from os import system
from pyx import *


class Evaluation:
    '''
    Classe permettant l'évaluation du marquage. Les deux images doivent être de
    type Image
    '''
        
    def __init__(self, image1 = None, image2 = None):
        '''
        Constructeur.
        Les deux images doivent être de type Image !
        '''
        self._image1  = image1
        self._image2  = image2
        # TODO Tester l'appartenance à Image
        assert self._image1.mode == self._image2.mode
        assert self._image1.size == self._image2.size
        
    
    def _EQM(self):
        eqm = 0
        for k in range(self._image1.size[0]):
            for l in range(self._image1.size[1]):
                eqm+=(self._image1.getpixel((k,l)) - \
                                                self._image2.getpixel((k,l)))**2
        return float(eqm)/self._image1.size[0]/self._image1.size[1]
    

    def _bitsParCoef(self):
        if self._image1.mode == '1':
            return 1
        elif self._image1.mode == 'L':
            return 8
        else:
            raise ValueError("Mode non supporté pour l'évaluation")


    def PSNR(self):
        '''
        Retourne le PSNR entre deux images.
        '''
        from math import log
        densite = 2**self._bitsParCoef()-1
        if self._EQM()!=0:
            return 10*log(densite**2/self._EQM(),10)
        else:
            return "Infini"


    def differences(self):
        '''
        Renvoie le nombre de coefficients différents,
        vu comme un pourcentage.
        '''
        compteur = 0
        for k in range(self._image1.size[0]):
            for l in range(self._image1.size[1]):
                if self._image1.getpixel((k,l)) != self._image2.getpixel((k,l)):
                    compteur+=1
        return 100*float(compteur)/self._image1.size[0]/self._image1.size[1]
    
    
    def visualisationDifferences(self, facteur = 0, nom = ''):
        '''
        Visualise les différences, avec Image
        '''
        extreme = self.differencesExtremales()[1]
        if extreme == 0:
            leFacteur = 0
        elif facteur*extreme > 255:
            raise ValueError('Facteur de visualisation trop élevé')
            exit(1)
        elif facteur == 0:
            leFacteur = 255/extreme
        else:
            leFacteur = facteur
        print 'Facteur de visualisation : ', leFacteur
        if nom !='':
            difference(self._image1,self._image2).point(lambda x:leFacteur*x).save(nom)
        difference(self._image1,self._image2).point(lambda x:leFacteur*x).show()
        dd = list(difference(self._image1,self._image2).point(lambda x:leFacteur*x).getdata())
        print "Nombre de différences",len(dd)-dd.count(0),"sur",len(dd)

    
    
    def differenceMoyenne(self):
        '''
        Renvoie la différence moyenne entre les images
        '''
        stats = ImageStat.Stat(difference(self._image1,
                                          self._image2).histogram())
        if self._image1.mode == '1':
            return float(stats.mean[0])/255
        else:
            return stats.mean[0]


    def differencesExtremales(self):
        '''
        Renvoie le minimum et le maximum des différences des images
        '''
        stats = ImageStat.Stat(difference(self._image1, 
                                          self._image2).histogram())
        if self._image1.mode == '1':
            return (int(float(stats.extrema[0][0])/255),
                    int(float(stats.extrema[0][1])/255))
        else:
            return stats.extrema[0][0], stats.extrema[0][1]    
    
    
    def _differencesHistogramme(self):
        '''
        Histogramme des différences, pour differencesHistoVisu
        '''
        histo = difference(self._image1, self._image2).histogram()
        liste = []
        for l in range(1,self.differencesExtremales()[1]+1):
            liste.append((l,histo[l]))
        return liste
    
    
    def differencesHistoVisu(self):
        '''
        Affiche l'histrogramme des différences, avec PyX
        '''
        liste = []
        for k in self._differencesHistogramme():
            liste.append((k[0],k[1]))
        if len(liste) == 0:
            raise ValueError("Aucune différence")
        g = graph.graphxy(width=8, x=graph.axis.bar())
        g.plot(graph.data.points(liste, xname=0, y=2),[graph.style.bar()])
        g.writeEPSfile('histoDiff.eps')
        system('evince histoDiff.eps')
