Advertisement
madegoff

C_Kurs_6Blatt

Nov 8th, 2023
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.75 KB | None | 0 0
  1. /*
  2. Willkommen zum sechsten Aufgabenblatt vom Programmierkurs. Auf diesem Aufabenblatt geht es um enums und structs.
  3.  
  4. Um die Tests für dieses Blatt zu kompilieren und zu starten, führen Sie den folgenden Befehl aus:
  5. cc -std=c11 -g -Wall 06ex_test.c -o 06ex_test.o -lm && ./06ex_test.o
  6. */
  7.  
  8. #include "06_canvas.h"
  9. #include <stdio.h>
  10. #include <stdint.h>
  11. #include <math.h>
  12.  
  13. /*
  14. In diesem Aufgabenblatt erweitern wir unsere Canvas API um Farben.
  15. Menschen nehmen Farben als Mischung von drei "Basisfarben" wahr: rot, grün, und blau.
  16. Jedes Pixel eines Bildschirms gibt rotes, grünes, und blaues Licht ab, je nach Intensität dieser
  17. drei Farbkanäle sehen wir unterschiedliche Farben.
  18.  
  19. Unsere Canvas hat nun neue Funktionen `canvas_set_r`, `canvas_set_g`, and `canvas_set_b`, welche die einzelen Kanäle
  20. `red`, `green` und `blue` setzen. Das Canvas header-file dokumentiert die neuen Funktionen ausführlicher.
  21. */
  22.  
  23. /*
  24. Aufgabe 1a:
  25. Farben verhalten sich auf einem Bildschirm anders als zum Beispiel Wasserfarben auf Papier.
  26.  
  27. Färben Sie die gegebene Canvas so, dass die Rotkomponente jedes Pixels gleichmäßig von ganz links (also bei `x == 0` -> 0.0)
  28. nach ganz rechts (bei `x == maximum` -> 1.0) zunimmt, und die Grünkomponente jedes Pixels gleichmäßig von
  29. ganz unten (also bei `y == 0` -> 0.0) nach ganz oben (bei `y == maximum` -> 1.0) zunimmt.
  30. Die Blaukomponente soll überall unverändert bleiben (und ist nicht in allen Testfällen die selbe).
  31.  
  32. Tipp: der Rotanteil für ein Pixel an der X-Koordinate berechnet sich beispielsweise als `x / (Canvasbreite - 1)`.
  33. Aber Vorsicht: bei Division auf `int`s wird immer zur Null abgerundet, während hier z.B. in der Mitte 0.5 rauskommen soll.
  34. (Einen Wert durch den Maximalwert zu teilen um eine Zahl zwischen 0 und 1 zu erhalten, wird als
  35. "normalisieren" bezeichnet. Normalisieren kommt häufig vor, auch auf diesem Blatt. Wie wäre es also mit einer
  36. Hilfsfunktion `float normalize(int value, int max)` ? :-) )
  37. */
  38.  
  39.  
  40. float normalize(int value, int max){
  41.  
  42.     return (float)value/(float)max;
  43.  
  44. }
  45.  
  46. Canvas swatch_red_green(Canvas c) {
  47.  
  48.  
  49.     for (int i = 0; i < canvas_width(c); i++){ //laufen durch alle x-Koordinaten von links nach rechts // aufsteigender roter anteil
  50.  
  51.         for(int j = 0; j < canvas_height(c); j++){ //laufen durch alle y-Koordinaten von unten nach oben // aufsteigender gruener anteil
  52.  
  53.             int w = canvas_width(c)-1;
  54.             int h = canvas_height(c)-1;
  55.             float rotanteil = normalize(i,w);
  56.             float gruenanteil = normalize(j,h);
  57.             canvas_set_r(c,i,j,rotanteil);
  58.             canvas_set_g(c,i,j,gruenanteil);
  59.         }
  60.     }
  61.  
  62.     return c;
  63. }
  64.  
  65. /*
  66. Dieses enum repräsentiert die drei Farbkanäle.
  67. */
  68. typedef enum ColorChannel_ {
  69.     Red,
  70.     Green,
  71.     Blue
  72. } ColorChannel;
  73.  
  74. /*
  75. Aufgabe 1b:
  76. Das obrige Enum können wir nun nutzen um eine Funktion zu schreiben, welche unterschiedliche Farbkanäle setzen kann.
  77. Schreiben Sie die Funktion so, dass der jeweils richtige `channel` des Pixels mit der Koordinate `(x,y)` den Wert `v`
  78. erhält.
  79. */
  80. Canvas canvas_set_channel(Canvas c, int x, int y, ColorChannel channel, float v) {
  81.  
  82.     if(channel == 0){
  83.         canvas_set_r(c,x,y,v);
  84.     }
  85.     else if(channel == 1){
  86.         canvas_set_g(c,x,y,v);
  87.     }
  88.     else canvas_set_b(c,x,y,v);
  89.  
  90.     return c;
  91. }
  92.  
  93. /*
  94. Aufgabe 1c:
  95. Die folgende Funktion soll eine Canvas nach den selben Richtlinien wie in Aufgabe 1a einfärben, anstelle von Rot für
  96. die X-Achse und Grün für die Y-Achse allerdings die Farben aus den Parametern nutzen.
  97. Schreiben Sie die Funktion so, dass `channel_x` den Farbkanal für die X-Achse festlegt und `channel_y` den Farbkanal für
  98. die Y-Achse.
  99. Alle nicht in den Parametern angegeben Farbkanäle sollen unverändert bleiben.
  100. */
  101. Canvas swatch_rgb(Canvas c, ColorChannel channel_x, ColorChannel channel_y) {
  102.  
  103.     for (int i = 0; i < canvas_width(c); i++){ //laufen durch alle x-Koordinaten von links nach rechts // aufsteigender channel_x anteil
  104.  
  105.         for(int j = 0; j < canvas_height(c); j++){ //laufen durch alle y-Koordinaten von unten nach oben // aufsteigender channel_y anteil
  106.  
  107.             int w = canvas_width(c)-1;
  108.             int h = canvas_height(c)-1;
  109.  
  110.             float channel_x_anteil = normalize(i,w);
  111.             float channel_y_anteil = normalize(j,h);
  112.  
  113.             canvas_set_channel(c,i,j,channel_x, channel_x_anteil); //faerben pixel mit farbe channel_x mit intensivitaet channel_x_anteil
  114.             canvas_set_channel(c,i,j,channel_y, channel_y_anteil); //analog
  115.         }
  116.     }
  117.     return c;
  118. }
  119.  
  120. /*
  121. Häufig wollen wir nicht über einzelne Farbkanäle nachdenken, sondern über Farben als solche.
  122. Darum definieren wir einen neuen Typ für Farben. Eine Farbe wird eindeutig durch die Intensität ihrer drei Farbkanäle
  123. beschrieben, also fassen wir drei Intensitätswerte in einem struct zusammen:
  124. */
  125. typedef struct RGBByTheWayThisCanBeNamedArbitrarilygSinceWeAreUsingTheTypedefAnyways {
  126.     float r;
  127.     float g;
  128.     float b;
  129. } RGB;
  130.  
  131. /*
  132. Aufgabe 2a:
  133. Geben Sie den Wert zurück, der die Farbe Flieder (rot 0.86, grün 0.82, blau 1.0) repräsentiert.
  134.  
  135. Hinweis: Häufig werden RGB-Farben alternativ mit Ganzzahlen zwischen 0 und 255 angegeben, statt mit Kommazahlen zwischen 0.0 und 1.0.
  136. Flieder wäre dann z.B. (rot 219, grün 209, blau 255).
  137. */
  138. RGB lilac() {
  139.  
  140.     RGB color;
  141.  
  142.     color.r = 0.86;
  143.     color.g = 0.82;
  144.     color.b = 1.0;
  145.  
  146.     return color;
  147. }
  148.  
  149. /*
  150. Aufgabe 2b:
  151. Nutzen wir nun unser neues struct auf der Canvas. Die folgende Funktion soll mit einem Funktionsaufruf alle
  152. Kanäle gleichzeitig ansteuern!
  153. Setzen Sie die Farbe des Pixels mit Koordinate `(x, y)` auf die von `color` repräsentierte Farbe.
  154. */
  155. Canvas canvas_set_rgb_struct(Canvas c, int x, int y, RGB color) {
  156.  
  157.     float rot_anteil = color.r;
  158.     float gruen_anteil = color.g;
  159.     float blau_anteil = color.b;
  160.  
  161.     canvas_set_r(c,x,y,rot_anteil);
  162.     canvas_set_g(c,x,y,gruen_anteil);
  163.     canvas_set_b(c,x,y,blau_anteil);
  164.  
  165.     return c;
  166. }
  167.  
  168. /*
  169. Aufgabe 2c:
  170. Konvertieren Sie die gegebene Farbe in den Grauton der gleichen Helligkeit.
  171. Die Helligkeit vom Grauton berechnet sich, indem man den Rotwert mit 0.2989, den Grünwert mit 0.587,
  172. und den Blauwert mit 0.1140 multipliziert, und die Resultate addiert.
  173. Der Grauton mit dieser Helligkeit setzt alle drei Farbkanäle auf diesen Wert.
  174. */
  175. RGB rgb_to_gray(RGB color) {
  176.  
  177.     float all_channels_anteil = color.r*0.2989+color.g*0.587+color.b*0.1140;
  178.  
  179.     color.r = all_channels_anteil;
  180.     color.g = all_channels_anteil;
  181.     color.b = all_channels_anteil;
  182.  
  183.     return color;
  184. }
  185.  
  186. /*
  187. Aufgabe 2d:
  188. Konvertieren Sie mithilfe der `rgb_to_gray` Funktion das gegebene Bild in ein Graustufenbild.
  189. Die aktuelle Farbe eines Pixels kann mit den `canvas_get_r`, `canvas_get_g` und `canvas_get_b` Funktionen ausgelesen
  190. werden (siehe Headerfile für die Dokumentation).
  191.  
  192. Tipp: Genau so wie wir die drei Funktionen zum Färben zusammengefasst haben ließen sich auch die gerade genannten drei
  193. Funktionen in einer Hilfsfunktion zusammenfassen welche die Farbe an der gegebenen Koordinate als ein
  194. Wert vom Typ `RGB` zurück gibt.
  195. */
  196. Canvas canvas_to_gray(Canvas c) {
  197.  
  198.     int width = canvas_width(c)-1;
  199.     int height = canvas_height(c)-1;
  200.  
  201.     for (int i = 0; i<=width; i++){
  202.  
  203.         for(int j = 0; j<=height; j++){
  204.  
  205.             RGB current_color; //definieren die aktuelle farbe des einzelnen pixels
  206.             current_color.r = canvas_get_r(c,i,j);
  207.             current_color.g = canvas_get_g(c,i,j);
  208.             current_color.b = canvas_get_b(c,i,j);
  209.  
  210.             RGB new_color; //definieren die neue Farbe
  211.             new_color = rgb_to_gray(current_color);
  212.  
  213.             canvas_set_rgb_struct(c, i, j, new_color); //faerben unser pixel mit der neuen farbe
  214.         }
  215.     }
  216.  
  217.     return c;
  218. }
  219.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement