Die Japilib bietet verschiedene Funktionen zum Laden und Manipulieren von Bildern. Die beiden Bildformate, die Zur Zeit unterstützt werden sind GIF und JPEG. Ein Bild wird unter JAPI ähnlich behandelt wie die anderen Graphischen Objekte, d.h. für jedes Bild wird ein Eventcounter zurückgeliefert. Im gegensatz zu den interactiven Elementen, kann jedoch ein Bild niemals einen Event liefern. Der Eventcounter eines Bildes ist vielmehr als eine Art Index zu verstehen, über den man auf ein Bild zugreifen kann.
Ein Bild wird mit der Funktion:
image = j_loadimage(char* filename);
in den JAPI Kernel geladen. Die Abmessungen eines geladenen Bildes können mit den bereits bekannten Funktionen:
breite = j_getwidth(image); hoehe = j_getheight(image);
erfragt werden. Über die Funktion:
j_drawimage(component, image, x, y);
kann ein Bild in einer Component angezeigt werden. Die beiden Parameter x und y legen den linken oberen Punkt des Bildes innerhalb der Component fest.
Bei der Darstellung eines Bildes in einer Component, gelten die gleichen Einschränkungen wie bei den Graphic Primitiven. Prinzipiell kann ein Bild in jeder Component angezeigt werde, aber nur der Canvas verfügt über die Double Buffer Technik, die sicherstellt, das die Komponente nach einer Verdeckung wieder restauriert wird.
Mit diesen Funktionen wird im folgenden Beispiel ein einfacher Videoplayer erstellt:
/* Example video.c */ : int image[18]; : for(i=0;i<18;i++) { sprintf(filename,"../../managerspiel/ms%d.gif",i+1); printf("Loading %s\n",filename); image[i] = j_loadimage(filename); } breite = j_getwidth(image[0]); hoehe = j_getheight(image[0]); canvas = j_canvas(frame,breite,hoehe); : while((obj != quit)&& (obj != frame)) { : if(do_work) { j_drawimage(canvas,image[i],0,0); j_sync(); j_sleep(50000); i = (i+1)%18; } } :
Znächst werden in einer Schleife alle Bilder geladen. Da alle Bilder gleich groß sind wird nur vom ersten Bild die Abmessungen ermittelt, und der Canvas entsprechend dimensioniert. In der Eventloop werden die Bilder nun hintereinander dargestellt, was zu einer flüssigen Animation führt (siehe Abbildung 5.7).
Auch von dem Inhalt eines Canvas läßt sich ein Bild erstellen, das eine Momentaufname des aktuellen Inhalts des Canvas enthält. Die Funktion dazu ist:
image = j_getimage(canvas);
Soll das Bild jedoch nur einen Teil des Canvas beinhalten, oder eine andere Größe als der Canvas besitzen, so kann mit der Funktion
image = japi_getscaledimage(canvas, x, y, sw, sh, tw, th);
ein Bild erstellt werden, das aus dem Canvas von der Position (x,y) einen Auschnitt der Breite sw und der Höhe sh in ein Bild speichert mit den Ausmaßen: Breite = tw und Höhe = th
In ähnlicher Weise kann ein bereit bestehendes Bild scaliert werden, wenn es mit der Funktion
j_drawscaledimage(component,image,sx,sy,sw,sh,tx,ty,tw,th);
dargestellt wird. Diese Funktion bewirkt, das ein Ausschnitt vom Punkt (sx,sy) mit der Breite sw und der Hoehe sy in der Component dargestellt wird. Dabei wird das Bild an der Position (tx,ty) der Component dargestellt und auf eine Breite von tw und eine Höhe vom th transformiert.
Das folgende Beispiel zeigt diese Funktionen im Einsatz:
/* aus Example scaledimage.c */ : j_fillcircle(canvas,150,150,100); image = j_getscaledimage(canvas, 50, 50, 250, 250, 50, 50 ); j_drawscaledimage(canvas,image,0,0,25,25,0,0,100,100);
Zunächst wird in einem Canvas mittig ein gefüllter Kreis erzeugt, der einen Radius von 100 Pixeln hat. Mittels j_getscaledimage() wird nun ein Bild erzeugt, das nur den Ausschnitt des Keises enthält. Dabei wird das Bild gleichzeitig auf eine Kantenlänge von 50:50 reduziert. Mit der Funktion j_drawscaledimage() wird nun aus diesem Bild das linke obere Viertel entnommen und im Canvas ebenfalls links oben angezeigt. Dabei wird der Ausschnitt nun auf ein Größe von 100x100 Pixeln vergrößert. Die Abbildung 5.8 verdeutlicht diesen Vorgang, und zeigt das resultierte Bild.
Die beiden letzten Funktionen erlauben eine direkte Manipulation von Bildinhalten. Dabei wird das Bild in Form von RGB Werten an die Applikation geliefert, bzw. an den JAPI Kernel überliefert. Durch Änderung der RGB Werte kann nun das Bild verändert werden. Diese beiden Funktionen sind nur auf den Canvas anwendbar.
j_getimagesource(int canvas, int x, int y, int w, int h, int* r, int* g, int* b); j_drawimagesource(int canvas, int x, int y, int w, int h, int* r, int* g, int* b);
|
Die Funktion j_getimagesource() liefert einen Ausschnitt vom Punkt (x,y) der Breite w und der Höhe h zurück. Der Bildinhalt wird in den Arrays r,g,b abgelegt. Diese müssen daher mindestens die Länge w*h besitzen. Analog wird mit der Funktion j_drawimagesource() der Inhalt der Arrays r,g,b in der übergebenen Komponente dargestellt. Die Bilddaten werden ab der Position (x,y) mit einer Breite von w und einer Höhe von h dargestellt. Der folgende Auszug aus einer Eventloop realisiert mit diesen beiden Funktionen einen Inverter des Bildinhaltes eines Canvas (siehe Abbildung 5.9):
/* Example image.c */ : if(obj == invert) { j_getimagesource(image,0,0,breite,hoehe,r,g,b); for(i=0;i<breite*hoehe;i++) { r[i]=255-r[i]; g[i]=255-g[i]; b[i]=255-b[i]; } j_drawimagesource(canvas,0,0,breite,hoehe,r,g,b); } :
Abschließend soll auch an dieser Stelle nochmal das einleitende Beispiel der Mandelbrot Applikation aufgegriffen werden. Mit Hilfe der j_drawimagesource() Funktion läßt sich die Applikation deutlich beschleunigen, sodaß sich gegenüber einer plattformnahen Implementierung kaum noch Geschwindigkeitseinbußen festzustellen sind. Anstatt jeden berechneten Punkt nun einzeln zu setzen, wird im nachfolgenden Beispiel immer eine komplette Zeiel des Bildes berechnet und mit der j_drawimagesource() Funktion dargestellt. Das zeilenweise Darstellen ermöglich es, auch während der Berechnung auf weitere Events (wie Abbruch) zu reagieren.
/* Example mandel2.c */ : for(x=0;x<breite;x++) { zre = xstart + x*(xend-xstart)/breite; zim = ystart + y*(yend-ystart)/hoehe; it = mandel(zre,zim,512); r[x]=it*11; g[x]=it*13; b[x]=it*17; } j_drawimagesource(canvas,0,y,breite,1,r,g,b); :
|