import os
import matplotlib.pyplot as plt
import numpy as np

#   Définir le répertoire de travail avant toute chose

os.chdir("C:/Users/franc/Documents/MP2122/IPT")   # A compléter

#------------------------------------------------------------------------------
#  Lecture d'un fichier image au format png. Sous Pyzo le type des 
#  des éléments des matrices R, V et B est float 32 bits (flottants simple
#  précision compris entre 0 et 255.
# ----------------------------------------------------------------------------
#
def getImage(nomFichier) :
    """Cette fonction renvoie un triplet de 3 matrices R, V et B de même
    dimension L x C qui correspondent aux trois couleurs de base
    rouge, vert et bleu de l'image. Cette image est située dans le fichier
    nomFichier d'extension .png obligatoire. L'image possède L lignes et C
    colonnes de pixels."""
    
    npImage = plt.imread(nomFichier)
    npImage = 255*npImage    # Lecture avec Pyzo

    R = npImage[ : , : ,0]
    V = npImage[ : , : ,1]
    B = npImage[ : , : ,2]
    
    return R, V, B

#------------------------------------------------------------------------------
#     fonction qui enregistre un fichier image au format png.
#------------------------------------------------------------------------------

def saveImage(nomFichier, R, V, B) :
    """ Enregistre l'image contenue dans les trois matrices R, V et B, de type
    (ligne, colonne) dans un fichier nomFichier d'extension .png obligatoire.
    
    Cette fonction ne retourne rien. """
    
    n = R.shape
    npImage = np.zeros( (n[0], n[1], 3 ))
    
    npImage[ : , : , 0] = R/255
    npImage[ : , : , 1] = V/255
    npImage[ : , : , 2] = B/255
    
    plt.imsave(nomFichier, npImage)
    
#-----------------------------------------------------------------------------
#-------------------  Début du programme -------------------------------------
#-----------------------------------------------------------------------------

#-------- Extraction des matrices R, V et B ----------------------------------

R, V, B = getImage("lena.png")
Z = np.zeros(R.shape)  # Matrice de zéros de la même taille que R, V ou B

saveImage("lenaR.png", R, Z, Z)
saveImage("lenaV.png", Z, V, Z)
saveImage("lenaB.png", Z, Z, B)

#--------------------- Ecriture d'une image ----------------------------------
#     On travaille directement sur les vecteurs lignes de la matrice
#-----------------------------------------------------------------------------

#--------------------- Matrice R ---------------------------------------------

R = np.array([ [200,200,200,200,200,200,200,255,255,255],
               [200,200,200,200,200,200,200,255,255,255],
               [200,200,200,200,200,200,200,255,255,255],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [200,200,200,200,200,200,200,200,200,200] ])
               
#--------------------- Matrice V ---------------------------------------------

V = np.array([ [0,0,0,0,0,0,0,255,255,255],
               [0,0,0,0,0,0,0,255,255,255],
               [0,0,0,0,0,0,0,255,255,255],
               [255,255,255,255,255,255,255,255,255,255],
               [255,255,255,255,255,255,255,255,255,255],
               [255,255,255,255,255,255,255,255,255,255],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0] ])                

#--------------------- Matrice B ---------------------------------------------

B = np.array([ [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0,0],
               [200,200,200,200,200,200,200,200,200,200],
               [200,200,200,200,200,200,200,200,200,200],
               [200,200,200,200,200,200,200,200,200,200],
               [0,0,0,0,0,0,0,0,0,0] ])  

saveImage("imageCouleur.png", R, V, B)
 
# #------------- Image en niveaux de gris --------------------------------------
 
R,V,B = getImage("lena.png")
G = 0.11*R + 0.59*V + 0.30*B
saveImage("lenaG.png",G,G,G)

##--------------------------- Symétries ---------------------------------------
 
#        Symétrie par rapport à un axe vertical passant par le centre
#        de l'image. Il faut permuter les vecteur colonnes

def vertSym(M) :
    S = np.zeros(M.shape)
    L, C = M.shape
    for i in range(L) :
        for j in range(C) :
            S[i,C-1-j] = M[i,j]  # Echanger les vecteurs colonnes
    return S
 
#----------  Symétrie par rapport à un axe horizontal passant par le centre ----
#----------  de l'image.
 
def horizSym(M) :
    S = np.zeros(M.shape)
    L, C = M.shape
    for i in range(L) :
        for j in range(C) :
            S[L-1-i,j]  = M[i,j]   # Echanger les vecteurs lignes
    return S
  
G1, G2, G3 = getImage("lenaG.png")   # G1, G2, G3 matrices identiques
Z = np.zeros( G1.shape)
  
Gsym = vertSym(G1) 
saveImage("lenaVSym.png", Gsym, Gsym, Gsym)

Gsym = horizSym(G1)
saveImage("lenaHSym.png", Gsym, Gsym, Gsym)

#-----------La dernière image est réalisée avec la matrice transposée -------
 
MatTranspo = G1.T   # Transposition de G1
saveImage("lenaTranspo.png", MatTranspo, MatTranspo, MatTranspo)  

#------------------------------------------------------------------------------
#-----------------------    Quantification   ----------------------------------
#------------------------------------------------------------------------------

def quantifie2niveaux(M) :
    L,C = M.shape
    S = np.zeros((L,C)) 
    for i in range(L) :
        for j in range(C) :
            if M[i,j] <= 127 : S[i,j] = 0
            else : S[i,j] = 255
    return S

G1, G2, G3  = getImage("lenaG.png")
Gq = quantifie2niveaux(G1)
saveImage("lenaQuantif.png", Gq,Gq,Gq)

#------------------------------------------------------------------------------
#----------------------- Floutage ---------------------------------------------
#------------------------------------------------------------------------------

def floutage(M) :
    L, C = M.shape  # Nombre de lignes et de colonnes de M
    Mflou = np.zeros((L,C))
    for i in range(1, L-1) :        # Ne pas considérer les lignes 0 et L-1
        for j in range(1, C-1) :    # Ne pas considérer les colonnes 0 et C-1
            Mflou[i,j] = 1/9 * ( M[i-1, j-1] + M[i-1, j] + M[i-1, j+1] + M[i, j-1]\
            + M[i, j] + M[i, j+1] + M[i+1, j-1] + M[i+1, j] + M[i+1, j+1])
    return Mflou 
# le signe \ (antislash) permet d'écrire une instruction sur plusieurs lignes         
    
G1, G2, G3 = getImage("lenaG.png")
Gflou = floutage(G1)
saveImage("lenaFlou.png", Gflou, Gflou, Gflou)    
 
 
#------------------------------------------------------------------------------
#----------------------- Détection des contours -------------------------------
#------------------------------------------------------------------------------

import math as m     # On a besoin de la racine carrée m.sqrt

def contours(M) :
    L, C = M.shape  # Récupération du nombre de lignes et de colonnes de M
    Mcontour = np.zeros( (L,C) )  # Initialisation
    for i in range(1, L-1) :         # Ne pas considérer les lignes 0 et L-1
        for j in range(1, C-1) :     # Ne pas considérer les colonnes 0 et C-1
            Mcontour[i,j] = m.sqrt( (M[i, j+1] - M[i, j-1])**2 + (M[i-1, j] - M[i+1, j])**2 )
    return Mcontour
 
G1, G2, G3 = getImage("lenaG.png")
Gcont = contours(G1)
saveImage("lenaC.png", Gcont, Gcont, Gcont)    

#----------  On prend le négatif de l'image des contours ---------------------
Gcont = 255 - Gcont
saveImage("lenaCInv.png", Gcont, Gcont, Gcont)
    