#Importation du module nécessaire pour les fonctions de traitement d'image
import PIL.Image
import matplotlib.pyplot as plt
import numpy as np
import matplotlib


#Fonctions à analyser : 

def conversion(code):
    '''
    fonction qui, à  partir d'un code binaire donné renvoie
    le nombre correspondant
    :: param : code : str
    :: return : int
    '''
    nombre = 0
    for symbole in code:
        nombre = 2*nombre + int(symbole)
    return nombre

def caractere(nombre):
    '''
    fonction qui renvoie le caractère de la table ASCII
    associé au nombre donné en paramètre
    :: param : nombre : int (compris entre 0 et 255)
    :: return : str
    '''
    assert 0<=nombre<=255, 'le nombre doit être entre 0 et 255'
    return chr(nombre)

def decode(ecriture_binaire,taille):
    '''
    fonction qui affiche la phrase codée en binaire par ecriture_binaire
    en associant une lettre à chaque bloc de taille bits
    :: param : ecriture_binaire : str composée de 0 et de 1
    :: param : taille : int (nombre de bits utilisés par symbole)
    :: return : str
    '''
    nbre_symb = len(ecriture_binaire) // taille
    phrase = ''
    i = 0
    for k in range(nbre_symb):
        nbre_binaire = ecriture_binaire[i:i+taille]
        nbre_decimal = conversion(nbre_binaire)
        phrase = phrase + caractere(nbre_decimal)
        i = i + taille
    print(phrase)

def creer_image(source,destination,code):
    '''
    crée une image nommée destination à partir de source en modifiant
    les bits de poids faible de la composante rouge des pixels de la
    première ligne pour y insérer le code donné
    :: param : source : str (image de base)
    :: param : destination : str (nom de l'image après modification)
    :: param : code : str (code écrit en binaire à insérer dans l'image)
    '''
    n = len(code)
    image = PIL.Image.open(source)
    largeur,hauteur = image.size
    for x in range(min(n,largeur)):
        r,v,b = image.getpixel((x,0))
        new_r = conversion(bin(r)[2:9]+code[x])
        image.putpixel((x,0),(new_r,v,b))
    image.save(destination)

def afficher_image(source):
    '''
    fonction qui affiche l'image donnée en fichier source
    :: param : source : str (nom du fichier)
    '''
    image = PIL.Image.open(source)
    image.show()

def lire_image(source):
    '''
    fonction qui renvoie la liste composée des bits de poids faible
    de la couleur rouge sur la première ligne à partir du fichier
    image source
    :: param : source : str (nom de l'image)
    :: return : str (composée de 0 et de 1)
    '''
    image = PIL.Image.open(source)
    largeur, hauteur = image.size
    code = ''
    for x in range(largeur):
        r,v,b = image.getpixel((x,0))
        bit = str(r%2)
        code = code + bit
    return code

def steganalyse(image):
    '''
    fonction qui applique un filtre modulo 8 sur la couleur bleue des pixels
    pour faire apparaître le message caché et affiche ensuite l'image modifiée.
    :: param : str (nom de l'image)
    '''
    image_path = image # endroit où se trouve l'image
    pil_image = PIL.Image.open(image_path) # on charge l'image
    im_array = np.asarray(pil_image) # image = 3 tableaux de pixels
    im_rouge = np.copy(im_array[:,:,0]) # tableau couleur rouge
    im_vert = np.copy(im_array[:,:,1]) # tableau couleur vert
    im_bleu = np.copy(im_array[:,:,2]) # tableau couleur bleu
    im_bleu = im_bleu%8 # on filtre les données sur la couleur bleu (modulo 8)
    plt.figure(figsize=(10,10)) 
    plt.imshow(im_bleu) # on choisit l'image à afficher
    plt.show()# on affiche l'image




