// ********************************************************* // * Turn.class * // ********************************************************* // ********************************************************* // * Beschreibung: * // * Ein beliebiges Bild (JPG oder GIF (auch transparent)) * // * wird vor einem Hintergrund um die Y-Achse rotiert * // * wird. Der Hintergrund wird entweder mit Farbe * // * oder einem Texturbild (das nicht genau den Massen des * // * Applets entsprechen muss) ausgefuellt. * // * Alle Animationsphasen werden im Voraus berechnet, * // * das Applet hinreichend schnell ablaeuft. * // * Bevor man das Applet in eine Seite einbindet, kann * // * man das Offset der Textur (nur auf Wunsch) mit den * // * Cursortasten steuern, damit sich die Textur genau mit * // * einer eventuellen Textur der eigentlichen HTML-Seite * // * deckt. * // ********************************************************* // ********************************************************* // * Autor: Sascha Schneider * // * email: st000991@hrz1.hrz.th-darmstadt.de * // * Homepage: http://www.th-darmstadt.de/~st000991 * // ********************************************************* // ************************************************************ // * Parameter: * // * offsetcheck (optional) - wenn dieser Parameter auf * // * "true" gesetzt wird kann * // * man die optimale Position * // * seiner Applet-Hintergrund- * // * Textur ermittlen * // * speed (optional) - Die Pause zwischen den ein- * // * zelnen Animationsphasen in * // * ms. * // * bgimage (optional) - Das Bild, mit dem der * // * Hintergrund des Applets * // * ausgefuellt wird (Textur) * // * bgcolor (optional) - Die Farbe, mit der der * // * Hintergrund ausgefuellt * // * werden soll (anstatt Textur) * // * turnimage - Das Bild, das gedreht werden * // * soll. * // * xoffset (optional) - das Xoffset des Hintergrund- * // * Bildes (negativ!). * // * yoffset (optional) - das Yoffset des Hintergrund- * // * Bildes (negativ!). * // * einzelschritte (optional) - Die Anzahl der einzelnen * // * Animationsphasen (wird aus * // * Java-Speicherverwaltungs- * // * gruenden) automatisch auf 75 * // * beschraenkt. * // ************************************************************ // ************************************************************ // * Fragen und Anregungen bitte per email an mich schicken * // * st000991@hrz1.hrz.th-darmstadt.de (Sascha Schneider) * // ************************************************************ // ************************************************************ // * Description: * // * A picture (JPG or GIF (even transparent)) is rotatet * // * along its y-axis. The background of the applet is * // * either filled up with a specified image (which doesn´t * // * need to fit exactly into the applet window) or with * // * a selected Color. All phases of the animation are * // * calculated before the Applet starts to maximize * // * animation speed. Before putting the applet on a * // * special place on the html-page, you case choose the * // * x- and y-offset of the backgroundimage (if specified) * // * to get the backgroundimage fit with an texture * // * putted on the applet-including html-page. * // ********************************************************** // ********************************************************** // * Author: Sascha Schneider * // * email: st000991@hrz1.hrz.th-darmstadt.de * // * Homepage: http://www.th-darmstadt.de/~st000991 * // ********************************************************** // ************************************************************* // * Parameters: * // * offsetcheck (optional) - if this parameter is set * // * to "true", you can change * // * the position of the back- * // * groundimage to get the * // * optimal x- and yoffset * // * speed (optional) - the pause between the * // * particual phases of animation * // * in ms * // * bgimage (optional) - the picture for the * // * backgroundtexture * // * bgcolor (optional) - the desired color for the * // * background * // * turnimage - the picture which will be * // * rotated * // * xoffset (optional) - the xoffset of the background * // * picture * // * yoffset (optional) - the yoffset of the background * // * picture * // * einzelschritte (optional) - the numbers of steps for the * // * animation to form a half turn * // * this parameter will be * // * limited to 75 (for java * // * memory-management reasons) * // ************************************************************* // ************************************************************* // * Pleas give questions and comments via email to * // * st000991@hrz1.hrz.th-darmstadt.de (Sascha Schneider) * // ************************************************************* // ************************************************************* import java.awt.*; import java.awt.image.*; import java.applet.*; import java.lang.*; public class Turn extends Applet implements Runnable { boolean offsetcheck; Image bufferbild=null; Image bgimage=null; int bgw, bgh; int turnw, turnh; int w,h; int xoffset; int yoffset; int xmiddle, ymiddle; int speed; Thread t=null; int[] tpixelarray = null; Image bg=null; int einzelschritte; boolean bgimageangegeben = false; boolean bgimagepasst = false; Color bgcolor=null; int bgcolorint; int[][] rpixelarray = null; int counter=0; public void init () { Dimension d=size(); w=d.width; h=d.height; Image turnimage=null; try {this.offsetcheck = (new Boolean(getParameter("offsetcheck"))).booleanValue();} catch (NumberFormatException e) { this.offsetcheck = false; } // falls Typumwandlung scheitert setze offsetcheck auf false try {this.xoffset = (new Integer(getParameter("xoffset"))).intValue();} catch (NumberFormatException e) { this.xoffset = 0; } // falls Typumwandlung scheitert setze xoffset auf 0 try {this.yoffset = (new Integer(getParameter("yoffset"))).intValue();} catch (NumberFormatException e) { this.yoffset = 0; } // falls Typumwandlung scheitert setze yoffset auf 0 try {this.einzelschritte = (new Integer(getParameter("einzelschritte"))).intValue();} catch (NumberFormatException e) { this.einzelschritte = 10; } // falls Typumwandlung scheitert setze einzelschritte auf 10 if (einzelschritte > 75) einzelschritte = 75; try {this.speed = (new Integer(getParameter("speed"))).intValue();} catch (NumberFormatException e) { this.speed = 250; } // falls Typumwandlung scheitert setze speed auf 250 try {this.bgcolor = new Color(Integer.valueOf(getParameter("bgcolor"),16).intValue());} catch (NumberFormatException e) { bgcolor = Color.green; } // falls Typumwandlung scheitert setze speed auf gruen this.bgcolorint = (255 << 24) | (bgcolor.getRed() << 16) | (bgcolor.getGreen() << 8) | bgcolor.getBlue(); if (getParameter("bgimage") != null) bgimageangegeben = true; int[] bgpixelarray; try { if (bgimageangegeben) { bgimage=getImage(getDocumentBase(),getParameter("bgimage"));} else { bgimage=createImage(w,h); }; turnimage=getImage(getDocumentBase(),getParameter("turnimage")); MediaTracker m = new MediaTracker(this); m.addImage(bgimage,0); m.addImage(turnimage,1); m.waitForID(0); m.waitForID(1); bgw=bgimage.getWidth(this); bgh=bgimage.getHeight(this); turnw=turnimage.getWidth(this); turnh=turnimage.getHeight(this); xoffset%=bgw; // xoffsets in erlaubten Bereich holen yoffset%=bgh; if (xoffset > 0) xoffset-=bgw; if (yoffset > 0) yoffset-=bgh; tpixelarray = new int[turnw*turnh]; PixelGrabber pg = new PixelGrabber(turnimage,0,0,turnw,turnh,tpixelarray,0,turnw); pg.grabPixels(); bgpixelarray = new int[bgw*bgh]; pg = new PixelGrabber(bgimage,0,0,bgw,bgh,bgpixelarray,0,bgw); pg.grabPixels(); if (!offsetcheck) { int[] completebgpixelarray = new int [w*h]; int i,j,k,l; if (bgimageangegeben == false) { // falls kein Hintergrundbild angegeben, fuelle mit Hintergrundfarbe for (i=0; (i < w*h); i += 1) { completebgpixelarray[i]=bgcolorint; } bg=createImage(new MemoryImageSource(w,h,completebgpixelarray,0,w)); } else { // mache mir das hintergrundbild if (h >= bgh) { //0000 wenns mehr als eine gibt! //xxxx 1. Zeile if (w >= bgw) { bgimagepasst = true; //xxxx wenns mehr als eine Spalte gibt // mache das erste bild in der ersten zeile (2fach abgeschnitten 1x,1y) for (i=-yoffset; (i < bgh); i += 1) { for (j=-xoffset; (j < bgw); j += 1) { completebgpixelarray[(i+yoffset)*w+(j+xoffset)]=bgpixelarray[i*bgw+j]; } } // mache alle anderen ganzen bilder in der zeile (1fach abgeschnitten - y) int xa, ya; xa = w - (bgw+xoffset); ya = h - (bgh+yoffset); xa /= bgw; // restliche anzahl ganze bilder in der Zeile ya /= bgh; // restliche anzahl ganze bilder in der Spalte for (k = 1; k <= xa; k +=1) { for (i = -yoffset; (i < bgh); i +=1) { for (j = 0; (j < bgw); j +=1) { completebgpixelarray[(bgw+xoffset)+(k-1)*bgw+w*(i+yoffset)+j]=bgpixelarray[i*bgw+j]; } } } // for k // mache das letzte bild in der ersten zeile (2fach abgeschnitten 1x,1y) for (i=-yoffset; (i < bgh); i += 1) { for (j=0; (j < (w-(bgw+xoffset+xa*bgw))); j += 1) { completebgpixelarray[(bgw+xoffset+xa*bgw)+w*(i+yoffset)+j]=bgpixelarray[i*bgw+j]; } } //xxxx mache mir alle dazwischenliegenden zeilen (gibts die?) for (l = 1; l <= ya; l +=1) { // 1. bild (1fach abgeschnitten - x) for (i=0; (i < bgh); i += 1) { for (j=-xoffset; (j < bgw); j += 1) { completebgpixelarray[((l-1)*w*bgh)+(bgh+yoffset)*w+(j+xoffset)+i*w]=bgpixelarray[i*bgw+j]; } } // alle anderen (nicht abgeschnitten) for (k = 1; k <= xa; k +=1) { for (i = 0; (i < bgh); i +=1) { for (j = 0; (j < bgw); j +=1) { completebgpixelarray[((l-1)*w*bgh)+(bgh+yoffset)*w+(bgw+xoffset)+(k-1)*bgw+w*i+j]=bgpixelarray[i*bgw+j]; } } } // for k // letztes bild (1fach abgeschnitten - x) for (i=0; (i < bgh); i += 1) { for (j=0; (j < (w-(bgw+xoffset+xa*bgw))); j += 1) { completebgpixelarray[((l-1)*w*bgh)+(bgh+yoffset)*w+(bgw+xoffset+xa*bgw)+w*i+j]=bgpixelarray[i*bgw+j]; } } } // for l //xxxx mache die letzte zeile // 1. bild (2fach 1x,1y) for (i = 0; (i < (h-(bgh+yoffset+ya*bgh))); i +=1) { for (j = -xoffset; (j < bgw); j +=1) { completebgpixelarray[(bgh+yoffset)*w+(ya*bgh)*w+i*w+(j+xoffset)]=bgpixelarray[i*bgw+j]; } } // alle anderen (1fach y) for (k = 1; k <= xa; k +=1) { for (i = 0; (i < (h-(bgh+yoffset+ya*bgh))); i +=1) { for (j = 0; (j < bgw); j +=1) { completebgpixelarray[(bgh+yoffset)*w+(ya*bgh)*w+(bgw+xoffset)+(k-1)*bgw+w*i+j]=bgpixelarray[i*bgw+j]; } } } // for k // letztes bild (2fach 1x,1y) for (i = 0; (i < (h-(bgh+yoffset+ya*bgh))); i +=1) { for (j = 0; (j < (w-(bgw+xoffset+xa*bgw))); j +=1) { completebgpixelarray[(bgh+yoffset)*w+(ya*bgh)*w+(xa*bgw)+(bgw+xoffset)+i*w+j]=bgpixelarray[i*bgw+j]; } } } } bg=createImage(new MemoryImageSource(w,h,completebgpixelarray,0,w)); } } } catch (InterruptedException e) {}; xmiddle=w/2; ymiddle=h/2; bufferbild=createImage(w,h); if (!offsetcheck) { double phi, phistep; phi=0; phistep=Math.PI/einzelschritte; // ******************************************************* // * Jetzt werden erst mal alle einzelnen Bilder erzeugt * // ******************************************************* rpixelarray= new int[einzelschritte][turnw*turnh]; int a, b, c; double m; for (c = 0; c < einzelschritte; c +=1) { m = Math.sin(phi); showStatus("Turn Applet: Berechne Frame "+c+"/"+einzelschritte); for (a=0; (a < turnw*turnh); a += 1) { rpixelarray[c][a]=(0 << 24) | (0 << 16) | (0 << 8) | 0; }; // erst mal alles transparent ausfuellen for (a = 0;(a < turnh); a += 1) { for (b = turnw/2;(b >= 0); b -=1) { rpixelarray[c][(int)(Math.abs(a*turnw+turnw/2-(m*b)))]=tpixelarray[a*turnw+turnw/2-b]; } } for (a = 0;(a < turnh); a += 1) { for (b = 0;(b < turnw/2); b +=1) { rpixelarray[c][(int)(Math.abs(a*turnw+turnw/2+(m*b)))]=tpixelarray[a*turnw+turnw/2+b]; } } phi+=phistep; if (phi > (Math.PI)) phi %= Math.PI; } showStatus(""); counter=0; t = new Thread(this); t.start(); t.suspend(); } } public void start() { if (offsetcheck == false) { t.resume(); } } public void run() { if (offsetcheck == false) { for ( ; ; ) { try { repaint(); Thread.sleep(speed); counter+=1; if (counter >= 2*einzelschritte-1) counter=0; } catch (InterruptedException e) {} } } } public void stop () { if (offsetcheck == false) { t.suspend(); } } public void destroy () { if (offsetcheck == false) { t.stop(); t = null; } } public void paint (Graphics g) { //if (offsetcheck == false) t.suspend(); Graphics screenretter = null; screenretter = g; // Zeiger auf ScreenContext retten g=bufferbild.getGraphics(); // male ab jetzt im bufferbild if (offsetcheck) { g.setColor(Color.white); g.fillRect(0,0,w,h); g.drawImage(bgimage,xoffset,yoffset,this); g.setColor(Color.black); g.drawString("xoffset:"+xoffset,10,h/2); g.drawString("yoffset:"+yoffset,10,h/2+10); g.drawString("offsetcheck:"+offsetcheck,10,h/2+20); g.drawString("bgw,bgh:"+bgw+","+bgh,10,h/2+30); showStatus("Turn Applet: Offsetcheck aktiviert. Steuere Textur mit Cursortasten."); } else { if ((bgimageangegeben) & (bgimagepasst == false)) { // falls Hintergrundbild zu gross war, muss es eben von Hand gemacht werden int a, b; for (a=0; a <= 1; a+=1) { for (b=0; b <= 1; b+=1) { g.drawImage(bgimage,xoffset+a*bgw,yoffset+b*bgh,this); } } } else { g.drawImage(bg,0,0,this); // male das fertige hintergrundbild in den ScreenContext } int helpimagearray[] = new int[turnw*turnh]; if (counter < einzelschritte) for (int s=0; s < (turnw*turnh); s += 1) helpimagearray[s] = rpixelarray[counter][s]; else for (int s=0; s < turnh; s += 1) for (int u=0; u < turnw; u += 1) helpimagearray[s*turnw+u] = rpixelarray[counter-einzelschritte][s*turnw+turnw-u-1]; Image rimage = createImage(new MemoryImageSource(turnw,turnh,helpimagearray,0,turnw)); g.drawImage(rimage,xmiddle-turnw/2,ymiddle-turnh/2,this); } screenretter.drawImage(bufferbild,0,0,this); // male das fertige bufferbild in den ScreenContext //if (offsetcheck == false) t.resume(); } public void update(Graphics g) { paint(g); } public boolean keyDown(Event evtObj, int key){ if (offsetcheck) { switch(key) { case Event.LEFT : xoffset-=1; break; case Event.RIGHT: xoffset+=1; break; case Event.DOWN : yoffset+=1; break; case Event.UP : yoffset-=1; break; case ' ' : xoffset=0; yoffset=0; break; } xoffset%=bgw; yoffset%=bgh; if (xoffset > 0) xoffset-=bgw; if (yoffset > 0) yoffset-=bgh; repaint(); } return true; } public boolean keyUp(Event evtObj, int key) { return true; } }