12. Bitmapová grafika¶
Uspořádané k-tice
Jednou z nejjednodušších struktur, se kterou jsme se už setkali v případě, kdy jsme chtěli prohodit obsah dvou proměnných, jsou uspořádané k-tice (anglicky „tuple“). Podobně jako v matematice se jedná o uspořádaný soubor prvků dané velikosti. Svým způsobem jsou podobné seznamům, avšak na rozdíl od nich vytvořené k-tice už nemůžeme nikterak měnit. Pro vytvoření uspořádané k-tice používáme čárku. Při práci s uspořádanými k-ticemi můžeme použít tzv. pattern matching, kde jednotlivé prvky k-tice můžeme jednoduše přiřadit do zvláštních proměnných.
Základní vytvoření obrázku
Obrázek si v dnešním cvičení můžeme představit jako mřížku pixelů, kde každému pixelu přísluší nějaká barva. Pixel, jehož souřadnice jsou (0, 0) se nachází v levém horním rohu. Pro zápis barvy typicky používáme RGB model.
from PIL import Image
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
# Zjisti, zda je zadany bod uvnitr kruhu o danem polomeru, jehoz stred
# je uprostred ctvercoveho obrazku.
def in_circle(size: float, radius: float, x: float, y: float) -> bool:
return (x - size / 2) ** 2 + (y - size / 2) ** 2 < radius ** 2
def circle(size: int = 150, radius: int = 50) -> None:
# Vytvorime objekt pro manipulaci s obrazkem
im = Image.new("RGB", (size, size))
# Prochazime vsechny pixely naseho obrazku a kontrolujeme, zda lezi
# v kruhu
for x in range(size):
for y in range(size):
if in_circle(size, radius, x, y):
# Pixel na souradnicich (x, y) obarvime na cerno.
im.putpixel((x, y), BLACK)
else:
# Pixel na souradnicich (x, y) obarvime na bilo.
im.putpixel((x, y), WHITE)
# obrazek si muzeme zobrazit
im.show()
# nebo jej muzeme ulozit do souboru
im.save("demo_circle.png")
# Vykresli kruh o polomeru 50 na bilem ctverci o strane 150.
circle()
Abyste mohli bez problému pracovat s obrázky, musíte mít nainstalovanou
knihovnu Pillow
. Následně musíte importovat třídu Image
:
from PIL import Image
12.1. Kreslení¶
12.1.1. Čtverec¶
Na bílé pozadí o zadané velikosti nakreslete černý čtverec o zadané straně, jehož střed bude umístěn do středu obrázku.
from PIL import Image
def square(size: int = 250, a: int = 70) -> None:
pass
12.1.2. Trojúhelník¶
Na bílé pozadí o zadané velikosti nakreslete černý rovnostranný trojúhelník o dané straně, jehož těžiště bude umístěno do středu obrázku.
def triangle(size: int = 150, a: int = 50) -> None:
pass
12.1.3. Kruh¶
Na bílé pozadí o zadané velikosti nakreslete černý kruh o zadaném poloměru a se středem na zadaných souřadnicích.
def circle(size: int = 150, center: Tuple[int, int] = (75, 75), radius: int = 20) -> None:
pass
12.1.4. Elipsa¶
Na bílé pozadí o zadané velikosti nakreslete černou elipsu o zadaných poloměrech, jejíž střed bude umístěn do středu obrázku.
def ellipse(size: int = 150, radius_a: int = 50, radius_b: int = 20) -> None:
pass
12.1.5. Spirála¶
Na bílé pozadí o zadané velikosti nakreslete spirálu začínající ve středu obrázku.
def spiral(size: int = 150, turn_inc: int = 5, tstep: float = 0.05) -> None:
pass
12.1.6. Šachovnice¶
Nakreslete šachovnicový vzor o zadané velikosti obrázku a šířce pruhu.
def chessboard(size: int = 150, stripe: int = 30) -> None:
pass
12.1.7. Šachovnice s kruhy¶
Nakreslete následující obrázek, parametrem kreslící funkce je velikost obrázku, šířka šachovnicových pruhů a šířka mezikruží.
12.1.8. Překrývající se kruhy¶
Napište funkci, která vykreslí více černých kruhů. Každé překrytí kruhů invertuje pozadí kruhu. Kruhy jsou zadané pomocí seznamu, v němž každá položka je dvojice střed a poloměr, viz ukázka:
def circles_overlap(size: int, circles: List[Tuple[Tuple[int, int], int]]) -> None:
pass
circles = [
((20, 20), 40),
((200, 150), 100),
((200, 300), 140),
((300, 200), 50),
]
circles_overlap(500, circles)
12.1.9. Vlny¶
Napište funkci, která vykreslí následující obrázek. Parametrem je velikost obrázku a počet vln.
def waves(size: int, k: int) -> None:
pass
12.1.10. Vlny a čtverec¶
Napište funkci, která vykreslí následující obrázek. Parametrem je velikost obrázku, počet vln a strana čtverce, jehož střed je ve středu obrázku.
def waves_square(size: int, k: int, a: int) -> None:
pass
12.2. Transformace¶
V následujících příkladech budeme pracovat s již existujícími obrázky, a ty pak nějakým způsobem transformovat. Na rozdíl od předchozích příkladů budeme potřebovat otevřít soubor s již existujícím obrázkem:
im = Image.open(filename).convert("RGB")
# muzeme jednoduse zjistit rozmery obrazku
width, height = im.size
Podobně jako pro zápis barvy, existuje i rozhraní pro čtení barvy daného pixelu.
r, g, b = im.getpixel((0, 0))
im.putpixel((0, 0), (r + 1, g + 1, b + 1))
Pokud nemáte žádný vhodný obrázek po ruce, stáhněte si tento:
12.2.1. Odstranění barvy¶
Napište funkci, která odstraní z daného obrázku zelenou barvu (alternativně červenou nebo modrou):
def without_green(filename: str) -> None:
pass
12.2.2. Invertování barev¶
Napište funkci, která invertuje barvy v daném obrázku.
def invert_colors(filename: str) -> None:
pass
12.2.3. Stupně šedi¶
Napište funkci, která převede barevný obrázek na obrázek ve stupních šedi.
def grayscale(filename: str) -> None:
pass
12.2.4. Zrcadlení¶
Napište funkci, která daný obrázek transformuje do “zrcadlení”.
def mirror(filename: str) -> None:
pass
12.2.5. Převrácení¶
Napište funkci, která daný obrázek převrátí vzhledem k jeho vertikální ose.
def invert(filename: str) -> None:
pass
12.3. Šifry¶
12.3.1. Hledej v modré¶
Vyřešte následující obrázkovou šifru.
12.3.2. Hrany¶
Vyřešte následující obrázkovou šifru.
12.3.3. XOR se šachovnicí¶
Vyřešte následující obrázkovou šifru.
12.3.4. Schovávačka¶
Představte si, že máte jeden černo-bílý obrázek (tedy takový, který obsahuje
jen pixely černé a bílé barvy) a chtěli byste jej schovat do jiného obrázku,
takovým způsobem, aby nebyla jeho přítomnost zřejmá. Naprogramujte tedy dvě
funkce, encode
, která dostane dva obrázky a jeden ukryje do druhého, a
funkci decode
, která z obrázku vytáhne ten ukrytý.
Jak na to? Poznáte okem rozdíl mezi pixely s barvami (88, 63, 149)
a (88,
62, 149)
? Spíš ne, takže co takhle ten jeden bit využít pro zakódování
jednoho pixelu z tajného obrázku…
Poznámka: úkolem schovávání informací tak, aby nebyly zjistitelné se zabývá vědní disciplína steganografie.