#-*-coding:utf8-*-

#############################################
# Script réalisé dans le cadre du papier
# concernant l'utilisation de plusieurs
# fonctions chaotiques (pas seulement la 
# négation vectorielle) pour le tatouage.
#
# On utilise 3 fonctions différentes, on tatoue
# dans le domaine ondelette.
#############################################

print(" * Importations")
from dwt_marquage import Marquage_DWT
from outilsBase import conversion, getBit, setBit
from random import randint
from copy import deepcopy
import Image as im
from ImageChops import difference
from evaluation import Evaluation

print

def matrice_to_bits(matrice):
    '''
    Renvoie la matrice des écritures binaires de matrice.
    Les coefficients floants deviennent des chaînes (str) de bits.
    '''
    (m,n) = matrice.shape
    retour = []
    for l in range(m):
        ligne = []
        for c in range(n):
            ligne.append(conversion(str(matrice[l,c]),2))
        retour.append(ligne)
    return retour


def matrice_lscs(matrice,lscs):
    '''
    Matrice est une liste de listes, lscs est une liste.

    A partir d'une matrice de coefficients binaires, vus comme
    des chaines de caractères, extrait les bits dont les positions
    sont données par la liste lscs.
    
    Dans la liste lscs, un entier positif signifie devant la virgule,
    un entier négatif signifie derrière. Le premier bit devant la 
    virgule est le bit 1, le premier bit derrière la virgule est le -1.

    Le retour est une liste de bits (entiers).
    '''
    m,n = len(matrice), len(matrice[0])
    retour = []
    for l in range(m):
        for c in range(n):
            if '.' not in matrice[l][c]:
                ent,dec = matrice[l][c].replace('-',''),'0'
            else:
                ent,dec = matrice[l][c].replace('-','').split('.')
            ent,dec = list(ent),list(dec)
            ent.reverse()
            for lsc in lscs:
                if lsc > 0 and len(ent)>=lsc:
                    retour.append(ent[lsc-1])
                elif lsc<0 and len(dec)>=abs(lsc):
                    retour.append(dec[abs(lsc)-1])
                else:
                    retour.append('0')
    return [int(k) for k in retour][:-3]


def embarque(liste,matrice,lscs):
    m,n = len(matrice), len(matrice[0])
    retour = []
    cpt = 0
    for l in range(m):
        for c in range(n):
            if '-' in matrice[l][c]:
                signe = '-'
            else:
                signe = ''
            if '.' not in matrice[l][c]:
                ent,dec = matrice[l][c].replace('-',''),'0'
            else:
                ent,dec = matrice[l][c].replace('-','').split('.')
            ent,dec = list(ent),list(dec)
            ent.reverse()
            maximum = max([abs(k) for k in lscs])
            ent = list(''.join(ent).zfill(maximum+2))
            dec = list(''.join(dec).zfill(maximum+2))
            print dec
            for lsc in lscs:
                if lsc > 0:
                    ent[lsc-1] = str(liste[cpt])
                else:
                    dec[abs(lsc)-1] = str(liste[cpt])
                cpt += 1
            ent.reverse()
            ent = ''.join(ent)
            dec = ''.join(dec)
            print ent+'.'+dec



def f(L):
    assert len(L)%4 == 1
    n = len(L)/4
    retour = [int(not L[k]) for k in range(n)]
    retour.extend([L[k-n] for k in range(n,2*n)])
    retour.extend([int(L[k-2*n])*int(not L[k+1]) for k in range(2*n,4*n)])
    retour.extend([int(not L[2*n])])
    return retour


def f(L):
    return [int(not k) for k in L]

def f(L):
    retour = [int(not L[0])]
    retour.extend([L[k-1] for k in range(1,len(L))])
    return retour    

def embarque2(liste,matrice,lscs):
    m,n = len(matrice), len(matrice[0])
    retour = deepcopy(matrice)
    cpt = 0
    for l in range(m):
        for c in range(n):
            for lsc in lscs:
                try:
                    retour[l,c] = setBit(str(retour[l,c]),lsc, liste[cpt])
                    cpt += 1
                except:
                    pass
    return retour

print(" * Construction")
unMarquage = Marquage_DWT(hote = 'lena.png',
                          famille = 'db1')
print

coefficient = 'D2'
LSCs = [3,2,1]

print("Coefficients DWT : "+coefficient)
print("LSCS : "+str(LSCs))
print
print(" * Extraction du coefficient DWT.")
matrice = unMarquage.get_matrice_DWT(coefficient)

print(" * Extraction des LSCs")
mat = matrice_lscs(matrice_to_bits(matrice),LSCs)
mat0 = matrice_lscs(matrice_to_bits(matrice),LSCs)

print(" * Itérations")
for k in range(6000):
    mat2 = f(mat)
    strat = randint(0,len(mat)-1)
    mat[strat] = int(mat2[strat])

# Calcul du nombre de différences dans la matrice DWT
cpt = 0
for k in range(len(mat)):
    if mat[k] != mat0[k]:
        cpt += 1
print(" * Différences : "+str(cpt)+"/"+str(len(mat)))

print(" * Tatouage de la matrice extraite")
matrice_tatouee = embarque2(mat,matrice,LSCs)

print(" * Embarquement dans l'hôte")
unMarquage.set_matrice_DWT(coefficient, matrice_tatouee)

#print(" * Affichage de l'hôte marqué")
#unMarquage.get_hote_marque().show()
#raw_input('   (Appuyez sur une touche)')  

#print(" * Affichage des différences")
#maximum = 
#difference(im.open('lena.png'),unMarquage.get_hote_marque()).show()

unMarquage.get_hote_marque().save('lena_dwt_shift.pdf')

uneEva = Evaluation(im.open('lena.png'),
                    unMarquage.get_hote_marque())

print 'PSNR = ',uneEva.PSNR()

