//---------------------------------------------//

   MRCM  java Source
 
   Ishihama Yoshiaki       1998/6/29
   
   E-mail : ishmnn@cap.bekkoame.ne.jp
   
//---------------------------------------------//

import java.awt.*;
import java.applet.*;
import java.lang.String;
import java.util.Random;
import java.util.Date;


public class MRCM extends Applet implements Runnable {	
   Thread    runner;	
   int       WIDTH,HEIGHT,J;  
   Graphics  g2,off_g; 
   Random    nrand;   
   Image     offscreen;    
   int       Rot[][],InvertX[][],InvertY[][];  
   double    ValR[][],ValG[][],ValB[][];	
   
   	public void init() 	{	
   	        Date d=new Date();	
   	 	    nrand=new Random(d.getTime());	 
   	        WIDTH=this.size().width;
   	        HEIGHT=this.size().height;	
   	        
   	        offscreen = this.createImage(WIDTH, HEIGHT);
            off_g = offscreen.getGraphics();
            off_g.setColor(Color.black);
            off_g.fillRect(0,0,WIDTH,HEIGHT);
	   
		    g2=this.getGraphics();
		    g2.setColor(Color.black);
            g2.fillRect(0,0,WIDTH,HEIGHT);
   	         
   	        //-------------------------------------//	
   	         Rot=new int[2][2]; 	 
   	         InvertX=new int[2][2];	
   	         InvertY=new int[2][2]; 
   	         ValR=new double[2][2]; 
   	         ValG=new double[2][2]; 	
   	         ValB=new double[2][2]; 
   	         
   	         Initialize();	 
   	         J=0;	    
   	  }	
   	   	
   	public void start()	
   	{		
   	   if (runner == null)	
   	   	{		
   	   	runner= new Thread(this);
   	   	runner.start();		
   	  }	
       }		
       
       public void stop()
       	{		
       	   if (runner!=null)	
       	    {	
       	   	runner.stop();	
       	   	runner=null;	
       	     }	
       	}	   	
       	
       	public void run() //----------------------------------------//
       	 {	
       	 
       	     while (true) {	
       	     	try { Thread.sleep(10); }
       	     	catch (InterruptedException e){};
       	     	if ( isVisible()  ) {	
       	     	    DomyRun();	  	
       	     	  
       	    	}		
       	     }		  
       	 }	
       	 
       	public void paint(Graphics G)
	   {
		 G.drawImage(offscreen, 0, 0,this);
	    }	
       	 
       	 public void  DomyRun()//----------------------------------//
       	  {	
       	   int i,j,k,  xx[],yy[],Loc[],val[];
	  
	         xx=new int[8];yy=new int[8];Loc=new int[4];val=new int[2];
       	             
       	    for(i=0;i<256;i++){	  
       	  	  float     rr,gg,bb;    
       	  	  double     d0;      
       	  	               
       	  	    Loc[0]=0; Loc[1]=1; Loc[2]=2; Loc[3]=3;          
       	  	    xx[0]=i/128;         
       	  	    yy[0]=J/128;               
       	  	         
       	  	   for(k=1;k<8;k++){     
       	  	   
       	  	       switch(k){     
       	  	            case 1:   xx[1]=(i % 128)/64;   yy[1]=(J % 128)/64; break; 
       	  	            case 2:   xx[2]=(i % 64)/32;    yy[2]=(J % 64)/32;  break; 
       	  	            case 3:   xx[3]=(i % 32)/16;    yy[3]=(J % 32)/16;  break;  
       	  	            case 4:   xx[4]=(i % 16)/8;     yy[4]=(J % 16)/8;   break; 
       	  	            case 5:   xx[5]=(i % 8)/4;      yy[5]=(J % 8)/4;    break; 
       	  	            case 6:   xx[6]=(i % 4)/2;      yy[6]=(J % 4)/2;    break; 
       	  	            case 7:   xx[7]=(i % 2);        yy[7]=(J % 2);      break; 
       	  	        }  
       	  	                  
       	  	        DoConvert(Loc,Rot[xx[k-1]][yy[k-1]],
       	  	                  InvertX[xx[k-1]][yy[k-1]],InvertY[xx[k-1]][yy[k-1]]);                       
       	  	          val[0]=xx[k];        
       	  	          val[1]=yy[k];     
       	  	          doTransform(val,Loc);      
       	  	          xx[k]=val[0];      
       	  	          yy[k]=val[1];       
       	  	     }                  
       	  	     
       	  	      d0=1.0;   for(k=0;k<8;k++) d0 *=ValR[xx[k]][yy[k]];   
       	  	      d0 *=3.0;   if(d0>1.0) d0=1.0;    rr=(float)d0;  
       	  	            
       	  	      d0=1.0;   for(k=0;k<8;k++) d0 *=ValG[xx[k]][yy[k]];   
       	  	      d0 *=3.0;   if(d0>1.0) d0=1.0;    gg=(float)d0; 
       	  	        
       	  	      d0=1.0;   for(k=0;k<8;k++) d0 *=ValB[xx[k]][yy[k]]; 
       	  	      d0 *=3.0;   if(d0>1.0) d0=1.0;    bb=(float)d0;  
       	  	      
       	  	      g2.setColor(Color.getHSBColor(rr,gg,bb));        
       	  	      g2.drawLine(i,J,i,J); 
       	  	      
       	  	      off_g.setColor(Color.getHSBColor(rr,gg,bb));
                  off_g.drawLine(i,J,i,J);
       	  	       
       	     }                 
       	       J ++;        
       	      if(J>=256){   J=0;  Initialize();    } 
       	      
    }//-----------------------------------------------------//	 
    	 
       public int randomise(Random nrand,int range)
       {	  
       	    if(range==0) return 0;	
       	    return( java.lang.Math.abs(nrand.nextInt()) % range);
        }	 
          
        private void Initialize()  
         {   
          int i,j;        
            
             for(i=0;i<2;i++){     
                for(j=0;j<2;j++)  {    
                
                   ValR[i][j]=(double)(randomise(nrand,70)+30)*0.01;  //  3 - 16 
                   ValG[i][j]=(double)(randomise(nrand,40)+60)*0.01;   
                   ValB[i][j]=(double)(randomise(nrand,50)+50)*0.01;        
                }    
             }      
             
             for(j=0;j<2;j++){   
                 for(i=0;i<2;i++){   
                      Rot[j][i]=randomise(nrand,4);  
                      InvertX[j][i]=randomise(nrand,2);     
                      InvertY[j][i]=randomise(nrand,2);    
                  }   
              }  
         }      
         
       private void  DoConvert(int Loc[],int Rot,int  InvertX,int  InvertY)
       { 
       int i,loc[]=new int[4],loc2[]=new int[4];   
       
           for(i=0;i<4;i++) loc[i]=loc2[i]=Loc[i];    
         
           switch(Rot){    
               case 0: break;  
               case 1: loc[0]=loc2[3]; loc[1]=loc2[0]; loc[2]=loc2[1]; loc[3]=loc2[2]; break;
               case 2: loc[0]=loc2[2]; loc[1]=loc2[3]; loc[2]=loc2[0]; loc[3]=loc2[1]; break; 
               case 3: loc[0]=loc2[1]; loc[1]=loc2[2]; loc[2]=loc2[3]; loc[3]=loc2[0]; break; 
           }    
           
           for(i=0;i<4;i++) loc2[i]=loc[i];    
          
           if(InvertX==1){   
                  loc[0]=loc2[1];  loc[1]=loc2[0]; loc[2]=loc2[3]; loc[3]=loc2[2];     
                  for(i=0;i<4;i++) loc2[i]=loc[i];   
           }   
           
           if(InvertY==1){   
                loc[0]=loc2[3]; loc[1]=loc2[2]; loc[2]=loc2[1]; loc[3]=loc2[0];   
            }      
            
           for(i=0;i<4;i++) Loc[i]=loc[i];
       }       
       
       private void doTransform(int XX[],int Loc[])
       { 
          int xx=XX[0],yy=XX[1],loc;   
          
            if(xx==0){     
                if(yy==0) loc=0;     
                else      loc=3;   
             }else{    
                   if(yy==0) loc=1;   
                   else      loc=2;  
             }       
             
             loc=Loc[loc];   
             
             switch(loc){   
                   case 0: xx=0; yy=0; break;  
                   case 1: xx=1; yy=0; break;   
                   case 2: xx=1; yy=1; break;   
                   case 3: xx=0; yy=1; break;  
            }     
               XX[0]=xx; XX[1]=yy; 
        }
        
 }