## Placez les images .png (ex. monarch.png) dans le même dossier que ce fichier.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as img
from os import chdir
from math import sqrt
from random import randint

chdir(r"C:\Users\Prenom\Documents\TP10")  # adapter le chemin

def affiche(image):
    plt.imshow(image)
    plt.show()


## Pixel par pixel
# Tester avec une copie : saturation(image.copy(), "R") pour ne pas écraser l'original.

def saturation(image, couleur):
    n, p, _ = np.shape(image)
    for i in range(n):
        for j in range(p):
            if couleur == "R":
                image[i, j, 0] = 1.0
            elif couleur == "V":
                image[i, j, 1] = 1.0
            elif couleur == "B":
                image[i, j, 2] = 1.0
    return image

def coloration(image, couleur):
    n, p, _ = np.shape(image)
    for i in range(n):
        for j in range(p):
            if couleur == "R":
                image[i, j, 1] = 0.0
                image[i, j, 2] = 0.0
            elif couleur == "V":
                image[i, j, 0] = 0.0
                image[i, j, 2] = 0.0
            elif couleur == "B":
                image[i, j, 0] = 0.0
                image[i, j, 1] = 0.0
    return image

def negatif(image):
    n, p, _ = np.shape(image)
    for i in range(n):
        for j in range(p):
            for k in range(3):
                image[i, j, k] = 1 - image[i, j, k]
    return image

def luminosite(pixel):
    return (pixel[0] + pixel[1] + pixel[2]) / 3

def niveaux_de_gris(image):
    n, p, _ = np.shape(image)
    for i in range(n):
        for j in range(p):
            L = luminosite(image[i, j])
            image[i, j] = [L, L, L]
    return image

def noir_et_blanc(image, seuil=0.5):
    n, p, _ = np.shape(image)
    for i in range(n):
        for j in range(p):
            if luminosite(image[i, j]) < seuil:
                image[i, j] = [0.0, 0.0, 0.0]
            else:
                image[i, j] = [1.0, 1.0, 1.0]
    return image


## Déplacement de pixels

def miroir(image):
    n, p, _ = np.shape(image)
    image_miroir = np.zeros((n, p, 3))
    for i in range(n):
        for j in range(p):
            image_miroir[i, j] = image[i, p - 1 - j]
    return image_miroir

def rotation(image):
    # Quart de tour horaire : (i, j) -> (j, n-1-i)
    n, p, _ = np.shape(image)
    image_rotation = np.zeros((p, n, 3))
    for i in range(n):
        for j in range(p):
            image_rotation[j, n - 1 - i] = image[i, j]
    return image_rotation


## Convolution

def convolution(image, filtre):
    n, p, _ = np.shape(image)
    image_filtre = np.copy(image)
    for i in range(1, n - 1):
        for j in range(1, p - 1):
            for k in range(3):
                v = np.sum(image[i - 1:i + 2, j - 1:j + 2, k] * filtre)
                v = min(v, 1.0)
                v = max(v, 0.0)
                image_filtre[i, j, k] = v
    return image_filtre

def floutage(image):
    filtre = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]]) / 9
    return convolution(image, filtre)

def contours(image):
    filtre = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])
    return convolution(image, filtre)


## Pour aller plus loin

def mystere(n, p):
    # Drapeau français (bleu, blanc, rouge en colonnes).
    image = np.zeros((n, p, 3))
    for i in range(n):
        for j in range(p):
            if j < p // 3:
                image[i, j] = [0, 0, 1]
            elif j < 2 * p // 3:
                image[i, j] = [1, 1, 1]
            else:
                image[i, j] = [1, 0, 0]
    plt.imshow(image)
    plt.show()

def marcheur(n, p, N):
    image = np.ones((n, p, 3))
    i, j = n // 2, p // 2
    image[i, j] = [0, 0, 0]
    for k in range(N):
        x = randint(1, 4)
        if x == 1 and j > 0:
            j = j - 1
        elif x == 2 and j < p - 1:
            j = j + 1
        elif x == 3 and i > 0:
            i = i - 1
        elif x == 4 and i < n - 1:
            i = i + 1
        image[i, j] = [0, 0, 0]
    return image

def distance(pixel1, pixel2):
    return sqrt((pixel1[0] - pixel2[0]) ** 2 + (pixel1[1] - pixel2[1]) ** 2 + (pixel1[2] - pixel2[2]) ** 2)

def meme_couleur(pixel1, pixel2, epsilon):
    return distance(pixel1, pixel2) < epsilon

def nb_pixels(image, couleur, epsilon):
    n, p, _ = np.shape(image)
    cpt = 0
    for i in range(n):
        for j in range(p):
            if meme_couleur(image[i, j], couleur, epsilon):
                cpt = cpt + 1
    return cpt
