Exkurs: Postscriptgrafiken erstellen (für den kleinen Gebrauch)


Diesen kleinen Exkurs können Sie nur mal überfliegen. Er ist ein kleiner Appetitanreger. Vielleicht gewinnen Sie Interesse an dem Thema und steigen tiefer ein...

Wir wollen mit QBASIC Vektorgrafiken erstellen. Vektorgrafiken sind Grafiken, die mittels "Steuerdateien" gespeichert werden. Eine solche Steuerdatei besteht aus einer Sequenz von Zeichenanweisungen, z.B. dem Zeichen von Linien, Kreisen, Vierecken usw. Der Vorteil solcher Vektorgrafiken ist u.a., das sie auf dem Drucker in maximaler Auflösung dargestellt werden und nicht in lauter "Klötzchen" zerfallen, wie das gerne mit Pixel-Grafiken (bmp, gif, jpg) der Fall ist.

Können wir mit QBASIC auch solche schönen vektorgrafiken herstellen? Prinzipiell ja: Einfach nur eine entsprechend formatierte vektorgrafikdatei schreiben, z.B. eine Corel Draw-Datei oder Powerpoint-Datei. Nichts einfacher als das...

Das scheitert gegenwärtig schon daran, dass die aufgezählten Dateiformate BINÄR-Formate sind - und die lernen wir erst später. Zweitens sind diese Formate aber extrem komplex und es würde Hunderte von Seiten Einarbeitung brauchen, um auch nur das erste Viereck auf den Bildschirm zu bekommen. Drittens kennen wir aber die Formate gar nicht, wir müssten also ersteinmal irgendwo uns eine Dokumentation beschaffen. Nein, das alles erscheint keine gute Idee.

Nun, es gibt ein Format für die grafische Darstellung, das in Form von Textdateien abgespeichert wird - Postscript. Noch dazu kann jeder Linux- oder Windows-Anwender selbst ohne spezielles Programm dieses Format erzeugen. Dazu geht er in ein Vektorzeichenprogramm (z.B. Power Point oder Zoner Draw oder Corel Draw), zeichnet ein paar Vierecke und druckt das Ganze auf einem Postscript-Drucker aus - allerdings in eine Datei und nicht wirklich auf dem Drucker, den wahrscheinlich nur die wenigstens haben. Man muss sich also als erstes einen Postscript-Drucker installieren. Es macht nichts, dass man den gar nicht angeschlossen hat. Ich empfehle den "Apple Color LW 12/660", das ist ein ziemlicher Standarddrucker mit kompatiblem Postscript.

Nächster Schritt ist also: Ausdruck in eine Datei, die wir mit der Endung ".ps" versehen. So, nun kommt der einzige Haken: Wir wollen die Datei ansehen, OHNE sie auszudrucken. Wie geht das? Nun, dazu brauchen wir ein Programm namens "Ghostview", das es im Internet kostenlos zum Herunterladen gibt. Wenn Sie das installiert haben, können Sie sich die Datei ansehen - und sogar in ein pdf umwandeln. Und Sie können die Datei auf Ihrem Standarddrucker ausdrucken.

Der Plan

Soweit, so schön. Aber dadurch wissen wir immer noch nicht, wie wir ps-Dateien mit QBASIC erzeugen. Wir kennen das postscript-Format ja nicht und es wird schon hinreichend kompliziert sein.

Das kann schon sein. Aber es geht auch gar nicht darum, nun alles zu verstehen. Es geht darum, ersteinmal ein Muster zur Hand zu haben und die Teile darin zu identifizieren, die die Vierecke darstellen könnten. Dann schauen wir uns die Viereck-Angaben (oder das, was wir dafür halten) an und ändern den ein oder anderen Wert. Mit Ghostview schauen wir, was das Ergebnis davon ist. Und am Ende wissen wir, wie die grundlegende Syntax für "Viereck zeichnen" in Postscript lautet. Dann lassen wir QBASIC das ganze "Drumherum" wortgetreu schreiben und dazwischen beliebige Viereck- Anweisungen. Mit Viereck-Anweisungen kann man auch Linien und Punkte malen. Wir haben also alles zur Verfügung, um einfache Vektorgrafiken zu erstellen.

1. Schritt: Wir malen mit einem Vektorzeichenprogramm Vierecke.

Das geht schon meist mit einer Textverarbeitung wie MS Word oder Open Office Write. Ich benutze hier mal Powerpoint:

Es ist ganz gut, gleich viele Vierecke zu malen, da dann die charakteristische Struktur im ps-File besser auffällt.

2. Schritt: Wir drucken die Zeichnung auf dem ps-Drucker als File aus.

3. Schritt: Wir schauen uns die Datei in einem ps-Viewer an:

Das sieht soweit gut aus.

4. Schritt: Wir schauen uns die Datei in einem Editor an:

Sie beginnt mit:

%!PS-Adobe-3.0
%%Title: (Microsoft PowerPoint - Pr\344sentation1)
%%Creator: PScript5.dll Version 5.2
%%CreationDate: 2/1/2005 16:15:15
%%For: schatz
%%BoundingBox: (atend)
...

Darunter sehen wir schnell, dass Schlüsselworte der Postscript-Sprache mit "%%" eingeleitet werden. Die Datei besteht aus mehreren Abschnitten, die z.B. mit "%%BeginProlog" beginnen und mit "%%EndProlog" enden. Prologe interessieren uns nicht. Viele weitere haben was mit "Resource" zu tun. Ressourcen interessieren uns auch nicht.

Ziemlich weit unten, kurz vor "%%Trailer" sehen wir viele Zahlen. Das sieht ungefähr so aus:

: N 350 112 6000 4500 rp C 
1 1 1 1 scol  L ; 0 0 0 1 scol 0 Lj 1 Lc 6 Lw solid N 1900 462 M 800 462 I 800 1312 I 1900 1312 I C 
: [ 1 0 0 1 350 112 ] concat K 
; N 2000 562 M 900 562 I 900 1412 I 2000 1412 I C 
: [ 1 0 0 1 350 112 ] concat K 
; N 2100 662 M 1000 662 I 1000 1512 I 2100 1512 I C 
: [ 1 0 0 1 350 112 ] concat K 
; N 2200 762 M 1100 762 I 1100 1612 I 2200 1612 I C 
: [ 1 0 0 1 350 112 ] concat K 
; N 2300 862 M 1200 862 I 1200 1712 I 2300 1712 I C 
: [ 1 0 0 1 350 112 ] concat K 
; N 2400 962 M 1300 962 I 1300 1812 I 2400 1812 I C 
: [ 1 0 0 1 350 112 ] concat K 
; LH

Betrachten wir einmal jeweils die Zeile mit dem führenden "N". Wir erkennen, dass die hinter den Buchstaben angegeben Zahlen, wenn wir sie als x/y-Koordinaten interpretieren, jeweils ein Viereck ergeben! Bingo! Machen wir ein Experiment. Verändern wir im letzten Viereck einfach mal eine Zahl. Machen wir z.B. die letzte Zahl des letzten Vierecks, 1812, zu etwas anderem, z.B. "3000":

: N 350 112 6000 4500 rp C 
1 1 1 1 scol  L ; 0 0 0 1 scol 0 Lj 1 Lc 6 Lw solid N 1900 462 M 800 462 I 800 1312 I 1900 1312 I C 
: [ 1 0 0 1 350 112 ] concat K 
; N 2000 562 M 900 562 I 900 1412 I 2000 1412 I C 
: [ 1 0 0 1 350 112 ] concat K 
; N 2100 662 M 1000 662 I 1000 1512 I 2100 1512 I C 
: [ 1 0 0 1 350 112 ] concat K 
; N 2200 762 M 1100 762 I 1100 1612 I 2200 1612 I C 
: [ 1 0 0 1 350 112 ] concat K 
; N 2300 862 M 1200 862 I 1200 1712 I 2300 1712 I C 
: [ 1 0 0 1 350 112 ] concat K 
; N 2400 962 M 1300 962 I 1300 1812 I 2400 3000 I C 
: [ 1 0 0 1 350 112 ] concat K 
; LH

Dann speichern wir die Datei ab und schauen sie uns im ps-viewer an:

Siehe da, wir haben unsere erste ps-Datei erfolgreich manipuliert!

Weiteres Forschen

Mit systematischem weiterem Austesten lässt sich des weiteren folgendes vermuten:

Probieren Sie mal, was passiert, wenn Sie die vorletzte Zeile von oben durch
"; 0 0 1 0 scol N 2400 962 M 300 962 I 1300 1812 I 2400 1812 I 3000 3000 I C"
ersetzen. Hier wurde die Farbe Blau gewählt ("0 0 1 0" vor scol), der zweite Punkt (hinter "M") wurde nach links verschoben und hinten wurde ein fünfter Punkt angefügt.

5. Schritt: Eine ps-Datei in QBASIC

Was brauchen wir dazu? Zunächst die erstellte Datei als Vorlage. Sie wird durch unser QBASIC-Programm bis zum kritischen Punkt ohne Modifikation in die Zieldatei geschrieben. Wir beschränken uns hier einmal auf Schwarzweiß-Grafiken und nehmen daher als Einstieg unserer eigenen Postscript-Zugabe den Punkt hinter "solid", wenn Linienfarbe und -stil festgelegt sind. Hier fügen wir in die Vorlage ein "$start" ein, um uns das Auffinden dieses Punkts zu erleichtern. Das Ganze sieht also am Ende so aus:

end reinitialize
: N 350 112 6000 4500 rp C 
1 1 1 1 scol  L ; 0 0 0 1 scol 0 Lj 1 Lc 6 Lw solid 
$start
; LH
(%%[Page: 1]%%) = 

Anstatt von "$start" schreiben wir dann unsere eigenen Linien im ps-Format. Das heisst, wir legen Start- und Zielkoordinaten hinter "N" und "M" in einem String ab und schliessen das Ganze mit einem "I C" ab. Das könnte in BASIC so aussehen:

' Statt line (x1,y1)-(x2,y2):
BUF$="N "+STR$(INT(x1))+" "+STR$(INT(y1))
BUF$=BUF$+"M "+STR$(INT(x2))+" "+STR$(INT(y2))+" I C"

Bei der zweiten und allen folgenden Linien müssen wir allerdings noch ein Semikolon voranstellen.

Dann geben wir BUF$ aus: PRINT #2,BUF$

Anschliessend müssen wir noch jeweils eine zweite Zeile der Form ": [ 1 0 0 1 350 112 ] concat K" ausgeben. Das ist wirklich kein Problem. Also:

' Statt line (x1,y1)-(x2,y2):
BUF$="N "+STR$(INT(x1))+" "+STR$(INT(y1))
BUF$=BUF$+"M "+STR$(INT(x2))+" "+STR$(INT(y2))+" I C"
IF (iline>0) BUF$="; "+BUF$
PRINT #2,BUF$
PRINT #2,": [ 1 0 0 1 350 112 ] concat K"

Damit ist das Herzstück unserer QBASIC-Routine, die "psline"-Routine fertig. Am Ende müssen wir den Rest der Vorlage ausgeben und die Datei schliessen.

Übung 1: Schreiben Sie zum folgenden QBASIC-Programm eine Postscript-Version!

...das dürfte ja jetzt nicht mehr schwer fallen.

rad0 = 100
radf = 60
in = 20
pi = 22 / 7
xoff = 320
yoff = 240

screen1:

SCREEN 12
FOR ic = 0 TO 4
  rad = rad0 + radf * ic
  FOR ir = 0 TO in - 1
    ang = 2 * pi / in * ir
    ang1 = ang + pi + pi / in
    ang2 = 2 * pi / in * (ir + 1)
    'PRINT ang, ang1
    'INPUT a$
    y1 = yoff - rad * COS(ang): x1 = xoff + rad * SIN(ang)
    y2 = yoff - rad * COS(ang1): x2 = xoff + rad * SIN(ang1)
    y3 = yoff - rad * COS(ang2): x3 = xoff + rad * SIN(ang2)
    LINE (x1, y1)-(x2, y2)
    LINE (x2, y2)-(x3, y3)
  NEXT ir
NEXT ic
END

Natürlich gibt's hier auch ne Lösung...

...und das Resultat sind da so aus...

Was haben wir gelernt?

  1. Mit langweiligen Textdateien lässt sich wesentlich mehr Spannendes erreichen, als man vermuten würde.
  2. Man muss nicht immer alles von Grund auf verstehen, um es benutzen zu können.
  3. Systematisches Probieren und die richtigen kleinen Werkzeuge helfen, sich fremder Techniken zu bedienen, auch wenn man die technischen Einzelheiten nicht kennt.