/* The RotateImage.java class.
   This provides rotation of the image in the applet
   */
   
import java.applet.Applet;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.image.IndexColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;

class RotateImage {
   // applet to draw into
   private static Applet applet;
   // image to be rotated
   Image rotimg;
   // the 3D matrix associated with this image
   Matrix3D mat;
   // whether already transformed
   boolean transformed;
   // width and height of rotatable image
   int W, H;
   // pixels of the rotimg and the transformed pixels
   int[] pixels, tpixels;
   // grabber to get pixels[]
   PixelGrabber pg;
   // positions of the pixels as cosecutive x,y,z coordinates 
   float[] pos; 
   int[] tpos; // transformed positions of the pixels
   // bounding dimensions of the transformed image to be created 
   int xmin, xmax, ymin, ymax, xw, yw;
   
   RotateImage( Image img, Applet app, int w, int h) {
      rotimg = img;
      applet = app;
      W = w;
      H = h;
      mat = new Matrix3D();
      pixels = new int[W * H];
      // generate pixels for this image
      int imgw = img.getWidth(applet);
      int imgh = img.getHeight(applet);
      int[] pix = new int[imgw*imgh];
      pg = new PixelGrabber(img, 0, 0, imgw, imgh, pix, 0, imgw);
      try {
         pg.grabPixels();
         }
      catch (InterruptedException e) {
         System.err.println("interrupted waiting for pixels!");
         return;
         }
      if ((pg.status() & ImageObserver.ABORT) != 0) {
         System.err.println("image fetch aborted or errored");
         return;
         }
      int i, nx, ny;
   /* for (int y = 0; y < H; ++y)
         for (int x = 0; x < W; ++x) {
            nx = (imgw / 2) + x - (W / 2);
            ny = (imgh / 2) + y - (H / 2);
            if (nx<0 || ny<0 || nx>=imgw || ny>=imgh) {
               pixels[x + y*W] = 0xffafafaf;
               }
            else {
               //System.out.println(x+","+y+" : "+nx+","+ny);
               pixels[x + y*W] = pix[nx + ny*imgw];
               }
            } */
      for (int y = 0; y < H; ++y)
         for (int x = 0; x < W; ++x) {
            nx = (x * imgw) / W;
            ny = (y * imgh) / H;
            pixels[x + y*W] = pix[nx + ny*imgw];
            }            
      pos = new float[W * H * 3];
      tpos = new int[W * H * 3];
      for (int y = 0; y < H; ++y)
         for (int x = 0; x < W; ++x) {
            i = (x + y*W) * 3;
            pos[i] = tpos[i] = x;
            pos[i+1] = tpos[i+1] = y;
            pos[i+2] = tpos[i+2] = 0;
            }     
      }
         
   public void paint(Graphics g) {
      // transforming the points to their new positions
      if (!transformed) {
         mat.transform(pos, tpos, W*H);
         transformed = true;
         }
      // if the image's back is showing, do not draw the image
      if (tpos[(W/2 + (H/2)*W)*3 + 2] < 0)
         return;
      // sorting on basis of depth may be required at this stage
      // find the bounding area of the pixels
      xmin = xmax = tpos[0];
      ymin = ymax = tpos[1];
      for (int indx = 0; indx < W*H; ++indx) {
         int i = indx*3;
         if (xmin > tpos[i]) xmin = tpos[i];
         if (ymin > tpos[i+1]) ymin = tpos[i+1];
         if (xmax < tpos[i]) xmax = tpos[i];
         if (ymax < tpos[i+1]) ymax = tpos[i+1];
         }
      // the dimensions of the image to be created are :
      xw = xmax - xmin + 1;
      yw = ymax - ymin + 1;
      //System.out.println("NewDim : "+xw+" , "+yw);
      // generate the pixel array to be made into an image
      tpixels = new int[xw * yw];
      for (int i = 0; i<xw*yw; ++i) tpixels[i] = 0;
      for (int y = 0; y < H; ++y)
         for (int x = 0; x < W; ++x) {
            int a = x + y*W;
            int timgx = tpos[a*3] - xmin ;
            int timgy = tpos[a*3 + 1] - ymin ;
            //System.out.println("error x,y : "+timgx+" , "+timgy);
            tpixels[timgx + timgy*xw] = pixels[a];
            }
      // make the image from the pixel array using MemoryImageSource
      Image img = applet.createImage(new MemoryImageSource(xw, yw, tpixels, 0, xw));
      // draw this image in the backbuffer recieved as g
      g.drawImage(img, xmin, ymin, xw, yw, applet);
      img.flush();
      } // end of paint method
   } // end of RotateImage class

