Lösungen

Aufgabe: Ziffern-Histogramm berechnen

Die folgende Funktion berechnet ein Histogramm der übergebenen Liste von Ziffern.

def digit_histogram(digits):
  counts = [0,0,0,0,0,0,0,0,0,0]

  for digit in digits:
    counts[digit] = counts[digit] + 1
    
  return counts

Aufgabe: Grauwerte berechnen

Die Funktion luminosity berechnet einen gewichteten Mittelwert der drei Farbkanäle und rundet das Ergebnis anschließend zu einer ganzen Zahl.

def luminosity(color):
    r = color[0]
    g = color[1]
    b = color[2]

    return round(0.3*r + 0.59*g + 0.11*b)

Wir können sie in der Prozedur desaturate anstelle von average verwenden.

Aufgabe: Histogramm zeichnen

Die Funktion render_histogram erzeugt ein Bild der Größe 256 mal 256 Pixel. Sie berechnet einen Skalierungsfaktor in Abhängigkeit der größten im Histogram vorkommenden Anzahl, damit diese genau am oberen Bildrand dargestellt wird. In einer Schleife wird dann für jeden Grauwert mit einer weiteren Schleife eine vertikale Linie gezeichnet, die die im Histogram gespeicherte Anzahl anzeigt.

def render_histogram(histogram):
    width = 256
    height = 256

    image = Image.new("RGB", (width, height), (255,255,255))

    scaling = max(histogram) / height
    for x in range(0,width):
        for z in range(1,round(histogram[x] / scaling)):
            y = max(0,height-z)
            image.putpixel((x,y), (0,0,0))

    return image

Aufgabe: Kontrastveränderung programmieren

Die Funktion contrast_adjustment berechnet eine Abbildung von Grauwerten in Grauwerte mit Hilfe einer Geradengleichung für die geforderte Gerade. Jeder neue Grauwert wird nach seiner Berechnung auf den zulässigen Wertebereich von 0 bis 255 beschränkt und dann in die zurückgegebene Abbildung eingetragen.

def contrast_adjustment(factor):
    gray_map = [0] * 256
    
    for gray in range(0,256):
        new_gray = round(factor * gray + 128 * (1-factor))

        new_gray = max(0, new_gray)
        new_gray = min(new_gray, 255)

        gray_map[gray] = new_gray

    return gray_map

Die Prozedur save_with_changed_contrast liest ein Bild aus einer gegebenen Datei ein, berechnet dann mit contrast_adjustment eine Abbildung zwischen Grauwerten aus dem gegbeenen Faktor, wendet diese auf das eingelesene Bild an und speichert das Ergebnis unter einem neuen Namen.

def save_with_changed_contrast(base_name, factor):
    image = Image.open(base_name + ".jpg")
    gray_map = contrast_adjustment(factor)
    change_pixels(image, gray_map)
    image.save(base_name + "_cont" + str(factor) + ".jpg")

Bonusaufgabe: Kunst nachbauen

Hier ist ein Programm, das 1000 Farben zufällig auf einem schwarzen Bild aus 1600 Blöcken verteilt.

from PIL import Image
from random import randint

black = (0,0,0)

img_size = 400
block_size = 10

colored_blocks = Image.new("RGB", (img_size,img_size), black)

block_count = img_size / block_size

spectrum_colors = [None] * 1000

for r in range(0,10):
  for g in range(0,10):
    for b in range(0,10):
      spectrum_colors[100*r+10*g+b] = (25*r,25*g,25*b)

def fill_square(img,from_x,from_y,size,color):
  for x in range(from_x,from_x+size):
    for y in range(from_y,from_y+size):
      img.putpixel((x,y), color)

for i in range(0,len(spectrum_colors)):
    color = spectrum_colors[i]
    rx = block_size * randint(0, block_count-1)
    ry = block_size * randint(0, block_count-1)
    fill_square(colored_blocks,rx,ry,block_size,color)

colored_blocks.save("colored_blocks.png")