Dr. Johannes Mayer Abteilung Angewandte Informationsverarbeitung 5. Dezember 2005
Axel Blumenstock Blatt 7
Christian Ehrhardt


Uni Logo



Allgemeine Informatik III / Systemnahe Software I (WS 2005/2006)


Abgabetermin: 13. Dezember 2005

Flotter Plotter (10 Punkte)

Dieses Mal wollen wir einen Funktionsplotter schreiben.

  1. Erstellen Sie eine Funktion plot, die wie folgt aufgerufen werden kann:

      plot(image, &f, a, xmin, xmax, ymin, ymax);
    Dabei sei
    image
    ein zweidimensionales int-Array. Die Größe können Sie beispielsweise durch ein #define festlegen. Jedes Element steht für ein Pixel, und sein Wert gibt die Farbe an - zunächst 0 für weiß und 1 für schwarz.
    f
    eine Funktion, die zwei Werte x und a vom Typ double akzeptiert und einen double-Wert zurückgibt. Über die Variable x wird geplottet, und a sei der Scharparameter, der für einen Plot konstant ist. Beispiel für eine Funktion, die auf dieses Schema passt, ist sin(ax) - ein Sinus mit variabler Frequenz.
    a
    der Scharparameter, der an f weitergereicht wird.
    xmin, xmax
    die Endpunkte des darzustellenden Ausschnitts der x-Achse.
    ymin, ymax
    die Endpunkte des darzustellenden Ausschnitts der y-Achse.
    Achsen können, müssen aber nicht dargestellt werden.
  2. Stellen Sie ferner eine Funktion

      writePBM(FILE *fp, int image[SIZE1][SIZE2])
    (oder ähnlich) bereit, die das Bild image im PBM-Raw-Format in die gegebene Datei schreibt. Dieses ist Ihnen bereits aus Blatt 2 bekannt; hier nochmal in Kürze: Nach der Kennung ,,P4`` folgen, jeweils durch Whitespace getrennt und als Dezimalzahl formatiert, die Breite und Höhe des Bildes in Pixeln. Nach genau einem Newline folgen die Bilddaten. Für jedes Pixel wird ein Bit abgelegt, wobei ein gesetztes Bit für ein schwarzes Pixel steht. Die Pixel werden zeilenweise von links nach rechts durchgegangen und je acht in ein Byte gepackt - vom höchst- zum niedrigstwertigen Bit. Ist die Breite des Bildes kein Vielfaches von acht, wird das jeweils letzte Bytes einer Pixelzeile mit ,,don't-care``-Bits (beliebigen Wertes) aufgefüllt. Die ins PBM hinauszuschreibende Zeichenfolge enthält aber keine Newlines an den Zeilenenden!
  3. Verwenden Sie nun beide Funktionen, um in einer weiteren Routine Plots mit variierendem Scharparameter in jeweils eine Datei zu schreiben. Wenn Sie die Dateien mit fortlaufenden Nummern benennen, so dass die lexikalische Reihenfolge der numerischen entspricht (also beispielsweise plot0000.pbm, plot0001.pbm, ...), können Sie mit dem Kommando

      convert -delay 10 -loop 0 *.pbm animate.gif
    in der Shell diese einzelnen Plots zu einem animierten GIF zusammenfügen, das Sie wiederum mit einem Browser oder xanim betrachten können.
  4. Wir wollen nun convert zusätzlich nutzen, um etwas Text, insbesondere den Scharparameter, zu den Grafiken hinzuzufügen. Zu diesem Zweck rufen wir es aus unserem Programm für jedes Einzelbild auf, und zwar mit der Funktion

      popen(command, "w");
    Es gibt wie fopen() (siehe unten) einen Dateizeiger zurück, der genauso verwendbar ist, aber mit pclose() geschlossen werden muss. Dieser Ausgabestrom wird als Standardeingabe an das gegebene command gerichtet, das wie in einer Shell interpretiert wird.

    Für uns kommt hier das Kommando

      convert [OPTIONEN] - Ausgabedatei
    in Frage. Das ,,-`` weist convert an, statt aus einer Datei von der Standardeingabe zu lesen. Die große Zahl der Optionen entnehmen Sie der Manualseite, die für uns nützlichsten sind (mit ,,-``!)
    -font helvetica
    wählt helvetica als Font;
    -pen color
    setzt die angegebene Farbe (z.B. ,,red``);
    -draw 'text x,y "..."'
    druckt den bei ,,...`` angegebenen Text an Position (x,y) ins Bild. Enthält der Text besondere Zeichen, muss er in doppelte Anführungsstriche gesetzt werden.

  5. (Zusatzaufgabe, 5 Punkte) Damit die Kurven nun auch noch richtig schön erscheinen, implementieren Sie schließlich noch Anti-Aliasing. Als Übergabeformat der dabei entstehenden Grauwertbilder können Sie das in Blatt 4 bereits verwendete PGM-Raw-Format nutzen. (Hier gilt: Jedes Pixel wird durch ein Byte abgelegt, wobei 0 für ein schwarzes Pixel steht.)

    Für das Anti-Aliasing sind verschiedene Vorgehensweisen denkbar. Dabei müssen Sie für den Zeichenstift jeweils eine gewisse Breite, beispielsweise ein Pixel, annehmen.

    \includegraphics{antialiasing}

Einige nützliche Bibliotheksfunktionen:

Viel Erfolg!



Axel Blumenstock 2005-12-05