import matplotlib.pyplot as plt

## Exercice 1

damier = []
for i in range(10):
    ligne = []
    for j in range(10):
        if (i+j) % 2 == 0:
            ligne.append(1)
        else:
            ligne.append(0)
    damier.append(ligne)
plt.imshow(damier, cmap='gray')
plt.show()

# ou avec des listes par compréhension :

damier = [[(i+j) % 2 for j in range(10)] for i in range(10)]
plt.imshow(damier, cmap='gray')
plt.show()


## Exercice 2 (avec des listes par compréhension)

def degrade_vertical(n):
    return [[i/n for j in range(n)] for i in range(n)]

plt.imshow(degrade_vertical(1000), cmap='gray')
plt.show()

def degrade_horizontal(n):
    return [[j/n for j in range(n)] for i in range(n)]

plt.imshow(degrade_horizontal(1000), cmap='gray')
plt.show()

def degrade_diagonal(n):
    return [[(i+j)/(2*n) for j in range(n)] for i in range(n)]

plt.imshow(degrade_diagonal(1000), cmap='gray')
plt.show()


## Exercice 3

def france(n):  # 2*n lignes, 3*n colonnes
    drapeau = []
    for i in range(2*n):
        ligne = []
        for j in range(n):
            ligne.append([0, 0, 1.0])      # bleu 
        for j in range(n):
            ligne.append([1.0, 1.0, 1.0])  # blanc
        for j in range(n):
            ligne.append([0.8, 0, 0])      # rouge
        drapeau.append(ligne)
    return drapeau

plt.imshow(france(500))
plt.show()


def japon(n):  # 2*n lignes, 3*n colonnes
    drapeau = []
    a, b = n, 3*n//2      # coordonnées du centre
    r_carre = 9*n**2//25  # rayon du disque : 3/10 de la hauteur
    for i in range(2*n):
        ligne = []
        for j in range(3*n):
            if (i-a)**2 + (j-b)**2 > r_carre:
                ligne.append([1.0, 1.0, 1.0])
            else:
                ligne.append([0.7, 0, 0])
        drapeau.append(ligne)
    return drapeau

plt.imshow(japon(500))
plt.show()


chaton = plt.imread('chaton.png')
plt.imshow(chaton)
plt.show()

## Exercice 4

# 1)

def negatif_pixel(p):
    return [1-p[0], 1-p[1], 1-p[2]]

def negatif(img):
    neg = []
    n, p = len(img), len(img[0])
    for i in range(n):
        ligne = []
        for j in range(p):
            ligne.append(negatif_pixel(img[i][j]))
        neg.append(ligne)
    return neg

plt.imshow(negatif(chaton))
plt.show()

# ou avec des listes par compréhension :

def negatif(img):
    return [[[1 - img[i][j][k] for k in range(3)] for j in range(len(img[0]))]
            for i in range(len(img))]

plt.imshow(negatif(chaton))
plt.show()


# 2)

def daltonien_pixel(p):
    return [p[1], p[0], p[2]]

def daltonien(img):
    dalt = []
    n, p = len(img), len(img[0])
    for i in range(n):
        ligne = []
        for j in range(p):
            ligne.append(daltonien_pixel(img[i][j]))
        dalt.append(ligne)
    return dalt

plt.imshow(daltonien(chaton))
plt.show()


## Exercice 5

from math import sqrt

def augmenter_luminosite_pixel(p):
    return [sqrt(p[0]), sqrt(p[1]), sqrt(p[2])]

def augmenter_luminosite(img):
    nv_img = []
    n, p = len(img), len(img[0])
    for i in range(n):
        ligne = []
        for j in range(p):
            ligne.append(augmenter_luminosite_pixel(img[i][j]))
        nv_img.append(ligne)
    return nv_img

plt.imshow(augmenter_luminosite(chaton))
plt.show()


## Exercice 6 (faire des schémas pour comprendre les indices)

# 1)

def renversement_vertical(img):
    nv_img = []
    n, p = len(img), len(img[0])
    for i in range(n):
        ligne = []
        for j in range(p):
            ligne.append(img[i][p-1-j])
        nv_img.append(ligne)
    return nv_img

plt.imshow(renversement_vertical(chaton))
plt.show()

# ou simplement :

def renversement_vertical(img):
    nv_img = []
    for i in range(len(img)):
        nv_img.append(img[i][::-1])
    return nv_img

plt.imshow(renversement_vertical(chaton))
plt.show()


# 2)

def renversement_horizontal(img):
    nv_img = []
    n, p = len(img), len(img[0])
    for i in range(n):
        ligne = []
        for j in range(p):
            ligne.append(img[n-1-i][j])
        nv_img.append(ligne)
    return nv_img

plt.imshow(renversement_horizontal(chaton))
plt.show()

# ou simplement :

def renversement_horizontal(img):
    return img[::-1]

plt.imshow(renversement_horizontal(chaton))
plt.show()


# 3)

def rotation_gauche(img):
    nv_img = []
    n, p = len(img), len(img[0])
    for i in range(p):
        ligne = []
        for j in range(n):
            ligne.append(img[j][p-1-i])
        nv_img.append(ligne)
    return nv_img

plt.imshow(rotation_gauche(chaton))
plt.show()


## Exercice 7

def convolution(img, mat):
    somme_coeffs = 0
    for k in range(3):
        for l in range(3):
            somme_coeffs += mat[k][l]
    if somme_coeffs == 0:  # si la somme est nulle, on ne divise pas
        somme_coeffs = 1
    n, p = len(img), len(img[0])
    conv = []
    for i in range(1, n-1):  # on ne tient pas compte des pixels sur les bords
        ligne = []
        for j in range(1, p-1):
            pixel = []
            for c in range(3):  # pour chaque couleur (R, G, B)
                s = 0           # on calcule la moyenne pondérée des pixels voisins
                for k in range(3):
                    for l in range(3):
                        s += img[i-1+k][j-1+l][c] * mat[k][l]
                pixel.append(s / somme_coeffs)
            ligne.append(pixel)
        conv.append(ligne)
    return conv

# Noter que s / somme_coeffs peut être < 0 ou > 1.
# imshow remplace ces valeurs par 0 ou 1 (Clipping input data to the valid
# range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

m1 = [[1, 1, 1], [1, 1, 1], [1, 1, 1]]  # floutage
plt.imshow(convolution(chaton, m1))
plt.show()

m2 = [[0, -1, 0], [-1, 5, -1], [0, -1, 0]]  # augmentation du contraste
plt.imshow(convolution(chaton, m2))
plt.show()

m3 = [[0, 1, 0], [1, -4, 1], [0, 1, 0]]  # détection de contours
plt.imshow(convolution(chaton, m3))
plt.show()

m4 = [[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]  # détection de contours
plt.imshow(convolution(chaton, m4))
plt.show()
