# Externe Bibliotheken werden eingeladen
import argparse
import math
import numpy as np
from skimage.io import imread, imsave


### Die Argumente die mittels Konsole übergeben werden, werden in Variablen geschrieben
parser = argparse.ArgumentParser(description='Perform Median Cut Color Quantization on image.')
parser.add_argument('-c', '--colors', type=int, help='Number of colors needed in power of 2, ex: for 16 colors pass 4 because 2^4 = 16')
parser.add_argument('-i', '--input', type=str, help='path of the image to be quantized')
parser.add_argument('-o', '--output', type=str, help='output path for the quantized image')

args = parser.parse_args()

colors = args.colors
output_path = args.output
input_path = args.input
print("reducing the image to {} color palette".format(int(math.pow(2, colors))))



### Das zu verarbeitende Bild wird über die externe Methode "imread" eingelesen.
sample_img = imread(input_path)


### Diese Funktion wird immer zuletzt aufgerufen, um die tatsächlichen Änderungen am Bild zu machen ("sample_img"). 
def median_cut_quantize(img, img_arr):
    r_average = np.mean(img_arr[:, 0])
    g_average = np.mean(img_arr[:, 1])
    b_average = np.mean(img_arr[:, 2])

    for data in img_arr:
        sample_img[data[3]][data[4]] = [r_average, g_average, b_average]




### Diese Funktion ist die tatsächliche Implementierung des Median Cut 
def split_into_buckets(img, img_arr, depth):

    """ 
    Hier muss Code eingefügt werden (Aufgabe 3),
    der die Funktion terminiert bzw. "median_cut_quantize" aufruft.
    """

    """ 
    Hier muss Code eingefügt werden (Aufgabe 1),
    der die Spannweite der Farbräume berechnet und dann "space_with_highest_range" entsprechend belegt.
    """


    # Sortiert das img_arr von niedrigen zu hohen Werten im Bezug auf den zuvor gefundenen Farbraum (R,G oder B) mit der größten Spanne an Werten.
    # space_with_highest_range = {0,1 oder 2}
    # Und berechnet dann den Index des Medians, um das img_arr danach an diesem Index zu trennen.
    img_arr = img_arr[img_arr[:, space_with_highest_range].argsort()]
    median_index = int((len(img_arr) + 1) / 2)

    """ 
    Hier muss Code eingefügt werden (Aufgabe 2),
    welcher die Funktion rekursiv zweimal aufruft.
    """





### Das zu bearbeitende Bild wird hier zu einem 1-Dimensionalen Numpy Array umgeschrieben. Weil es die Bearbeitung leichter macht.
flattened_img_array = []
for rindex, rows in enumerate(sample_img):
    for cindex, color in enumerate(rows):
        flattened_img_array.append([color[0], color[1], color[2], rindex, cindex])

flattened_img_array = np.array(flattened_img_array)


### Hier wird die zuvor implementierte Logik aufgerufen
split_into_buckets(sample_img, flattened_img_array, colors)

### Und das bearbeitete Bild wird dann als neues Bild abgespeichert
imsave(output_path, sample_img)