[ zurück ]

Generierung dynamischer Grafiken


Der ISAPI-Experte hot erlaubt es Ihnen nicht nur, dynamische HTML-Ausgabeseiten zu programmieren, sondern auch Grafiken "on the fly" zu erzeugen und an den Browser zurückzuschicken.

Auch bei ISAPI-DLLs mit grafischer Ausgabe besteht Ihr Programmieranteil bei Verwendung des Experten darin, die Ausgabedaten innerhalb der Prozedur namens IsapiAction zusammenzustellen. Um die Weiterleitung der fertigen Grafik an den Webserver kümmert sich dann der durch den ISAPI-Experten generierte Rahmen der DLL von selbst. Der Abruf einer in eine HTML-Seite eingebetteten und via ISAPI bereitgestellten Grafik erfolgt durch einen üblichen Grafikverweis in der Webseite. Als Quelle der Grafik wird allerdings nicht ein statisches Bild, sondern die Serverextension angegeben.

 <IMG SRC="http://myhost/scripts/myisapi.dll?Parameter" BORDER=1>
Nun muß die ISAPI-DLL nur noch einen erlaubten Grafiktyp liefern, und die Webseite ist mit dem entsprechenden Bild verziert. Als Content-Typ der Serverausgabe kommen derzeit das monochrome XBitmap oder die farbigen Formate GIF oder JPEG in Frage. Das ebenfalls mögliche Grafikformat PNG wird noch nicht von allen Browser unterstützt.

Für die Typen GIF und JPEG gibt es eine Reihe von teils freien Delphi-Bibliotheken, die das Programmieren erleichtern bzw. überhaupt mit vertretbarem Aufwand ermöglichen. So gehört seit Delphi2 eine Unit namens "JPEG.PAS" zum Lieferumfang der Borland-Sprache. Diese ermöglicht es auf recht bequeme Weise, ein Windows-Bitmap in das JPEG-Format zu konvertieren und auszugeben. Gleiches gilt für die Freeware-Unit "Gifimage.PAS" von Anders Melander, die auf diversen Delphi-Seiten im Internet zu finden ist. Der Projektquelltext "GifCount" am Seitenende zeigt deren Gebrauch und liefern auch eine Kopie der Bibliothek.

Das Format XBitmap hingegen ist ein Bildformat, das Sie auch ohne zusätzliche Anstrengungen verwenden können. Das folgende Bild zeigt einen Blick in eine Grafikdatei dieses Typs. Es handelt sich um ein sehr simples Klartextformat. Nach dem Header mit den Angaben zur Bildbreite und Bildhöhe folgen die Pixeldaten Byte für Byte und Linie für Linie von oben links nach unten rechts als Hex-Werte. Die beiden einzigen Besonderheit dieses Bildformates sind, daß ein gesetztes Bit den Farbwert schwarz und nicht weiß ergibt und daß die jeweils durch ein Hexzahl-Byte abgebildeten 8 Pixel spiegelverkehrt angeordnet sind (linkes der 8 Pixel im niederwertigsten Bit der Hexzahl).

X-Bitmap

Bild: XBitmap-Grafiken sind in einem einfachen Klartextformat kodiert und lassen sich mit Delphi bequem erzeugen.

Somit ist es nicht schwierig, Grafiken dieses Typs in eigenen Programmen zu kodieren. Der ISAPI-Experte enthält zudem Funktionen, die Ihnen diese Arbeit auch noch abnehmen. Die beiden Grafikfunktionen zum Erzeugen von XBitmap-Daten heißen dort BmpToXBmp und PixToStr.

Webcounter nach Ihrem Geschmack

Für das einführende Grafikprojekt soll das einfache XBitmap-Format genutzt werden. Stellvertretend für andere dynamische Grafiken können Sie hier Ihren individuellen Webcounter programmieren. Das ist zwar nicht gerade revolutionär neu, eignet sich aber gut für den Einstieg.

Auf einer beliebigen HTML-Seite soll der Seitenzähler mit dem folgenden Aufruf eingebettet werden:

 <IMG SRC="/scripts/counter.dll?Owner+Style" BORDER=1>
Der Parameter Owner stellt dabei ein Kürzel zur eindeutigen Referenzierung der Zählerseite und des Zählerstandes dar. Der Parameter Style verweist auf eine Mustervorlage für die verwendeten Zählerziffern. Beginnen Sie Ihr Projekt, indem Sie den ISAPI-Experten mit "Datei"-"Neu"-"Projekte"-"ISAPI-Extension" aufrufen. Dem Projekt mit dem Datentyp XBitmap geben Sie zweckmäßigerweise den Projektnamen Counter.

In der Projektunit finden Sie danach bereits die Hilfsroutinen für die XBitmap-Grafiken. Wie immer bei Arbeit mit dem vorgefertigten Programm ist die Prozedur IsapiAction Ihr eigentliche Schaffensort. Selbst hier hat der Experte bereits einige Codezeilen für Sie generiert.

 procedure IsapiAction(var s: String);
 var MyBmp: TBitmap;
 begin

  MyBmp:=TBitmap.Create;              // Bitmap anlegen
  MyBmp.Monochrome:=true;

  {Zeichnen Sie hier Ihr Ausgabebild}

  s:=BmpToXBmp(MyBmp);                // Konvertierung
  MyBmp.Free;                         // Bitmap beseitigen
 end;

Vor der Grafikerzeugung muß Ihr Zähler zunächst einmal den Zählerwert bestimmen. Dazu ist der Parameterstring mit der Seitenreferenz auszuwerten. Auch der Fall, daß von irgendeiner Seite ein Aufruf ohne Angabe eines Zählerbesitzers erfolgt, darf das Script nicht aus dem Takt bringen. Deshalb wird in einem solchen Fall die Zählerreferenz auf beispielsweise "Anonymous" gesetzt. Außerdem wird versucht, den zweiten Parameter mit der Style-Angabe zu erkennen. Fehlt dieser, wird ein "Default"-Muster angenommen. Nachdem die beiden möglichen Parameter getrennt und zugeordnet sind, wird im Beispiel über den Aufruf einer separaten Funktion namens GetCountValue der anzuzeigende Zählerstand ermittelt.

 sQuery:=StrPas(ECBQueryString);
 j:=Pos('+',sQuery);                        // Trennzeichen
 if j>0 then begin
  sStyle:=UpperCase(Copy(sQuery,j+1,99));
  Delete(sQuery,j,99);
 end else sStyle:='DEFAULT';                //wenn fehlt
 if Length(sQuery)=0 then sQuery:='Anonymous';
 ZhlValue:=GetCountValue(sQuery);
Die Beschreibung der Zählerstandsermittlung über GetCountValue ist hier unbedeutend. Sie finden den Quelltext in der Endfassung des Projektes "Counter". Dort können Sie auch mittels des privaten Compilersymbols REG darüber entscheiden, ob als Speicherort für die Zählerstände die Registry oder eine Ini-Datei benutzt werden soll.

Nach diesen Vorbereitungen erzeugen Sie in Ihrem Programm jetzt die Grafikausgabe mit den Zählerziffern. Es gibt hierfür vielfältigste Varianten. Denkbar wäre ein direktes Zeichnen mit einer besonderen Schriftart. Im vorgestellten Beispiel werden aber die Ziffern Stelle für Stelle aus einer Mustervorlage in das Zielbild kopiert.

Dazu legen Sie zusätzlich zu dem von ISAPI-Experten vorgesehenen Ziel-Bitmap MyBmp ein zweites Bild BmpSrc mit der Quelle für die Ziffernmuster an. Die unterschiedlichen Mustervorlagen sollen im vorgestellten Fall als Ressourcen in die zukünftige Zähler-DLL eingebunden sein. Die Erzeugung einer solchen Ressourcendatei mit den Mustervorlagen ist auf der Seite Ziffernentwurf beschrieben.

Sie laden das Musterbild aus den Programmressourcen über den Aufruf von BmpSrc.LoadFromResourceName mit dem Namen der gewünschten Style-Vorlage als Parameter. Auch hier sind Vorkehrungen notwendig, falls ein ungültiger Stil-Name als Eingabewert an den Zähler übergeben wurde. Der try-except-Block fängt solche Aufruffehler ab.

 MyBmp:=TBitmap.Create;
 MyBmp.Monochrome:=true;
 MyBmp.Canvas.CopyMode:=cmSrcInvert;
 BmpSrc:=TBitmap.Create;            // Quell-Bitmap
 try
  BmpSrc.LoadFromResourceName(HInstance,sStyle)
 except
  BmpSrc.LoadFromResourceName(HInstance,'DEFAULT')
 end;
Aus dieser Vorlage ermitteln Sie nun die Höhe und Breite des zu generierenden Zählerbildes und weisen die Werte dem Zielbild zu. Die Höhe wird 1:1 übertragen. Die Breite einer Stelle ermittelt sich als ein Zehntel der Breite der Vorlage aus den Musterziffern 0..9. Die Breite des künftigen Zählerbildes richtet sich dann nach der geplanten Stellenanzahl nDigits des Zählers.

Dann wird ziffernweise aus der Mustervorlage in das Zielbild umkopiert. Der linke Rand der jeweiligen Stelle im Quell- und Ziel-Bitmap ist die Bezugsmarke für die Kopierfunktion Canvas.CopyRect. Nach der Kopieraktion geben Sie die nicht länger benötigte Mustervorlage gleich wieder frei.

 nZl:=BmpSrc.Height
 MyBmp.Height:=nZl
 nSp:=BmpSrc.Width div 10
 MyBmp.Width:=nSp*nDigits
 for j:=0 to nDigits-1 do begin
  nDestLeft:=nSp*(nDigits-(j+1));
  nSrcLeft:= nSp*(ZhlValue mod 10);
  ZhlValue:=ZhlValue div 10;
  MyBmp.Canvas.CopyRect(Rect(nDestLeft,0,nDestLeft+nSp,nZl),
               BmpSrc.Canvas,Rect(nSrcLeft,0,nSrcLeft+nSp,nZl));
 end;
 BmpSrc.Free;
Diesen gesamten Teil zum Zeichnen des Grafikabbildes können Sie nach Ihren Wünschen auch vollkommen anders gestalten. Wesentlich ist nur, daß zum Schluß ein monochromes Bitmap mit dem Abbild des Zählerstandes in der beabsichtigten Größe vorliegt.

Den Rest der Grafikausgabe erledigt der vorbereitete standardisierte Programmtext. Mit der automatisch vorhandenen abschließenden Zeile

 s:=BmpToXBmp(MyBmp);
wird das Bitmap in einen Textstring s gemäß den Vorschriften zum XBitmap-Format konvertiert. Die rückkehrende Funktion IsapiAction übergibt diesen String an das Hauptprogramm in der Projektroutine HttpExtensionProc. Und diese sendet den Datenstrom an den Client.

Damit ist Ihre ISAPI-Extension zur dynamischen Darstellung eines Zählerbildes bereits fertig programmiert. Zum schnellen Test der fertigen DLL müssen Sie nicht erst eine HTML-Seite schreiben, sondern können den Aufruf des Scripts auch ausnahmsweise direkt wie abgebildet in die Adreßzeile Ihres Browsers schreiben.

Counter

Das komplette Musterprojekt "Counter" finden Sie gleich unten am Ende dieser Seite. Eine zweite Grafikanwendung wird innerhalb der folgenden Datenbankprojekte realisiert.


Download der Projektquelltexte:
Disk Counter.zip - der beschreibene WebCounter im X-Bitmap-Format (7 kByte)
Disk GifCount.zip - ein farbiger Webcounter im GIF-Format (58 kByte)

[ Seitenanfang ] [ ISAPI ]

J. Hummel,   2000