Een bitmap-afbeelding is precies wat zijn naam reeds doet vermoeden: een reeks bits (0 of 1) die samen een digitale foto voorstellen. De afbeelding bestaat uit een matrix (rechthoekig rooster) van individuele beeldpunten (of pixels) die elk hun eigen kleur hebben. Laat ons een kijken naar een typische bitmap-afbeelding om het principe uit te leggen:
Links zie je een foto, en rechts zie je een 250% uitvergroting van de top van één van de bergen. Zoals je in deze uitvergroting kunt zien bestaat een bitmap-afbeeling uit honderden rijen en kolommen van kleine elementen die elk een eigen kleur hebben. Eén zo'n element wordt een pixel genoemd (afkorting voor picture element). Het menselijk oog is niet in staat om elke individuele pixel te zien, waardoor we een afbeelding met vloeiende gradaties waarnemen. Het aantal pixels dat nodig is om een realistisch uitziende afbeelding te krijgen, hangt in sterke mate af van de manier waarop de afbeelding zal gebruikt worden.
De kleur van een pixel uit een bitmap-afbeelding kan op verschillende manieren voorgesteld worden. Voor deze opgave onderscheiden we de volgende twee categoriën:
zwart-wit afbeeldingen: de kleur van een pixel is een grijswaarde die wordt voorgesteld als een integer tussen 0 (zwart) en 255 (wit) of als een floating point getal tussen 0.0 (zwart) en 1.0 (wit).
kleurafbeeldingen: de kleur van een pixel wordt voorgesteld door een lijst van drie getallen die een rood-, groen- en blauwcomponent voorstellen. Dit wordt de RGB-voorstelling van de kleur genoemd. Door verschillende hoeveelheden van deze componenten te vermengen bekomt men een kleur (denk aan het vermengen van gekleurde verf). Hierbij wordt elke component ofwel voorgesteld door een integer tussen 0 en 255, of door een floating point getal tussen 0.0 en 1.0. De extra waarden stellen in beide gevallen 0% kleur voor deze component en 100% kleur voor deze component voor.
We stellen een bitmap voor als een lijst van lijsten, waarbij de binnenste lijsten telkens de kleuren van een reeks pixels uit een rij van de foto voorstellen. Elke kleur wordt voorgesteld door een integer of floating point (zwart-wit afbeeldingen) of een lijst van drie integers of floats (kleurafbeeldingen). In deze opgave wordt gevraagd om beeldmanipulaties uit te voeren, door elke kleur van een bitmap om te zetten in een nieuwe kleur. Hiervoor ga je als volgt te werk:
Schrijf een functie kleur2grijs die de RGB-voorstelling ($$r$$, $$g$$, $$b$$) van een kleur (met $$r$$, $$g$$ en $$b$$ integers of floats) omzet naar een getal $$x \in [0, 1]$$ die een grijswaarde voorstelt, op basis van de volgende formule \[ x = 0.299r + 0.587g + 0.114b \] Indien de kleurcomponenten voorgesteld worden door integers, dan moeten deze eerst gedeeld worden door 255 vooraleer de formule toe te passen. Aan de functie moet dus een lijst van drie integers of floats doorgegeven worden. De functie moet de waarde van $$x$$ als resultaat teruggeven. Met deze functie kan een kleurafbeelding dus omgezet worden naar een zwart-wit afbeelding.
Schrijf een functie inverteer, die een kleur op de volgende manier omzet naar zijn omgekeerde kleur:
$$x \rightarrow 255 - x$$ als de kleur wordt voorgesteld door $$x \in \mathbb{N}$$
$$x \rightarrow 1 - x$$ als de kleur wordt voorgesteld door $$x \in \mathbb{R}$$
$$[r, g, b] \rightarrow [255 -r, 255 - g, 255 -b]$$ als $$r, g, b \in \mathbb{N}$$
$$[r, g, b] \rightarrow [1 -r, 1 - g, 1 -b]$$ als $$r, g, b \in \mathbb{R}$$
Schrijf een functie converteerBitmap waarin alle kleuren van een bitmap kunnen omgezet worden in een andere kleur. Aan de verplichte parameter bitmap moet een lijst van lijsten doorgegeven worden die een bitmap voorstelt zoals hierboven beschreven. De functie moet een nieuwe lijst van lijsten als resultaat teruggeven, die de bitmap voorstelt die men bekomt door de waarden van de gegeven bitmap te converteren. De standaard convertie bestaat erin om alle kleuren van de gegeven bitmap te kwadrateren:
$$x \rightarrow (x / 255)^2$$ als de kleur wordt voorgesteld door $$x \in \mathbb{N}$$
$$x \rightarrow x^2$$ als de kleur wordt voorgesteld door $$x \in \mathbb{R}$$
$$[r, g, b] \rightarrow [(r / 255)^2, g / 255)^2, b / 255)^2]$$ als $$r, g, b \in \mathbb{N}$$
$$[r, g, b] \rightarrow [r^2, g^2, b^2]$$ als $$r, g, b \in \mathbb{R}$$
Om na te gaan of een gegeven object een bepaald gegevenstype heeft, kan je natuurlijk gebruikmaken van de ingebouwde functie type(o) die het gegevenstype van het object o teruggeeft. Het is echter beter om hiervoor de ingebouwde functie isinstance(o, t) te gebruiken. Deze functie geeft een Booleaanse waarde terug die aangeeft of het object o al dan niet behoort tot het type t.
>>> type(3) == int
True
>>> isinstance(3.14, int)
False
>>> isinstance(3.14, float)
True
>>> isinstance([1, 2, 3], list)
True
>>> kleur2grijs([238, 172, 98])
0.7188156862745098
>>> kleur2grijs([0.7, 0.2, 0.6])
0.3951
>>> inverteer(168)
87
>>> inverteer(0.4)
0.6
>>> inverteer([238, 172, 98])
[17, 83, 157]
>>> inverteer([0.7, 0.2, 0.6])
[0.3, 0.8, 0.4]
>>> matrix = [[234, 124, 28], [36, 45, 179]]
>>> converteerBitmap(bitmap=matrix, converter=inverteer)
[[21, 131, 227], [219, 210, 76]]
>>> matrix = [[[0.2, 0.4, 0.6], [0.5, 0.9, 0.0]], [[0.5, 0.7, 0.1], [0.4, 0.3, 1.0]]]
>>> converteerBitmap(matrix)
[[[0.04, 0.16, 0.36], [0.25, 0.81, 0.0]], [[0.25, 0.49, 0.01], [0.16, 0.09, 1.0]]]
>>> converteerBitmap(bitmap=matrix, converter=kleur2grijs)
[[0.363, 0.6778], [0.5718, 0.4097]]
>>> converteerBitmap(bitmap=matrix, converter=inverteer)
[[[0.8, 0.6, 0.4], [0.5, 0.1, 1.0]], [[0.5, 0.3, 0.9], [0.6, 0.7, 0.0]]]