//
// pingiz title applet
// Created by Korhan Kaya , 27.03.2005
//
// blur() by SEB
// blendmodes() from blend_modes.pde
//
//
//

int WIDTH = 680;
int HEIGHT = 140;

BFont metaBold;

int tick = 0;

BImage img;BImage img2;
int maxDots=120001;
int nrOfDots;
Dot[] dot=new Dot[maxDots+1];
float lmx=0.0, lmy=0.0, mxmov=0.0, mymov=0.0;

blendmodes mode=new blendmodes();

void setup() {

background(255);
 size(680,140);
 colorMode(RGB, 255);
 img = loadImage("PINGIZl.jpg");
 img2 = loadImage("PINGIZ.jpg");


 int i=0;
 for (int y=1;y<=height;y++) {
   for (int x=1;x<=width;x++) {
     color c=img.pixels[int(y-1)*width+int(x-1)];
     if (red(c)<230) {
//      if ((x % 4)==1) {
     if (random(1)<0.07) {
       dot[i]=new Dot(x,y,c);
       i++;
     }
   }
 }
 nrOfDots=i-1;
}}

float aa = 10.0;
float bb = 8/3;
float rr = 28.0;
float delt=0.01;
float Yangle;
float Xangle;
float dx = 0;
float dy = 0;

int loopmode = 0;

void loop()
{
   blur();
   if ((tick % 10)==1) {mxmov=50;mymov=50;lmx=width /2;lmy=width /2;}
   for (int i=1;i<=nrOfDots;i++) {dot[i].update();}
   if (loopmode==0) tick+=2;if (tick>255) loopmode=1;
   if (loopmode==1) tick-=2;if (tick<-255) loopmode=0;
}

void mousePressed() {
 lmx=mouseX; lmy=mouseY;
}
void mouseDragged() {
 mxmov=mouseX-lmx;
 mymov=mouseY-lmy;
 lmx=mouseX; lmy=mouseY;
}

float llx=0;
float lly=0;

class Dot {
 float x,y,sx,sy;
 float d,dm=20000.0;
 float xmov=0,ymov=0;
 float movability;
 int nrOfNeighbours;
 color col=color(255,255,255);

 Dot(int x, int y, color c) {
   col=c;
   sx=x;sy=y;
   this.x=x; this.y=y;
   xmov=random(-3,3);
   ymov=random(-3,3);
   movability=1-dist(x,y,width/2.0,height/2.0)/sqrt(pow(width/2.0,2)+pow(height/2.0,2));    //  0..
 }

 void update() {
   if (mousePressed) {
     dm=dist(x,y,mouseX,mouseY);
   } else {
     dm=(3*dm+20000000)/3;
   }
   d=pow(1/(5+dm),0.7);
   xmov+=movability*0.7*mxmov*d;
   ymov+=movability*0.7*mymov*d;

   xmov+=movability*0.0045*(sx-x);
   ymov+=movability*0.0045*(sy-y);

   float damp=0.99;
   xmov*=damp;
   ymov*=damp;

   if (x+xmov<1||x+xmov>width) {xmov*=-0.4;}
   if (y+ymov<1||y+ymov>height) {ymov*=-0.8;}

   x+=xmov;y+=ymov;


  color aa,bb,newcolor,newcolor2;
  aa=color(0,0,0);

  aa=img2.pixels[int(y)*width+int(x)];
  bb=pixels[int(y)*width+int(x)];
  col=color(x,y*2,tick*-1);

  newcolor=mode.multiply(aa,bb);
  newcolor=mode.lighten(newcolor,aa );
  newcolor=mode.overlay(newcolor,col);

  fill(newcolor);
  stroke(newcolor);

 ellipse(int(x),int(y),2,2);//,5,5);

 if (random(1)<.1) point(int(x)+random(1),int(y)+1);//,5,5);


 if (random(1)<.5)
         {
         newcolor2=mode.difference(newcolor,color(150+sin(tick),50+(sin(tick) / 1.8),(tick)));
         fill(newcolor2);//noStroke();
         point(int(x)+1,int(y)-1);//,5,5);
         }

 if (random(1)<.5) {
         newcolor=mode.lighten(newcolor,color(150+(tick /2),150+(tick / 2),0));
         stroke(newcolor);
         point(int(x)-1,int(y)-1);//,5,5);
     }
 }

 float getNrOfNeighbours(float xp,float yp) {
   int x=int(xp), y=int(yp);
   return 8;
 }
}



// FULL RGB DIFFUSION FILTER
// by SEB // www.seb.cc

void blur() {
 int index,R,G,B,left,right,top,bottom;

 for(int j=0;j<WIDTH;j++) {
   for(int i=0;i<HEIGHT;i++) {
     index=i*WIDTH+j;

     // Wraparound offsets
     if(j>0) left=-1; else left=WIDTH-1;
     if(j==(WIDTH-1)) right=-WIDTH+1; else right=1;
     if(i>0) top=-WIDTH; else top=(HEIGHT-1)*WIDTH;
     if(i==(HEIGHT-1)) bottom=-(HEIGHT-1)*WIDTH; else bottom=WIDTH;

     // Calculate the sum of n neighbors
     R=(pixels[left+index]>>16) & 255; // left middle
     R+=(pixels[right+index]>>16) & 255; // right middle
     R+=(pixels[index]>>16) & 255; // middle middle
     R+=(pixels[index+top]>>16) & 255; // middle top
     R+=(pixels[index+bottom]>>16) & 255; // middle bottom
     R=(R/5);

     G=(pixels[left+index]>>8) & 255; // left middle
     G+=(pixels[right+index]>>8) & 255; // right middle
     G+=(pixels[index]>>8) & 255; // middle middle
     G+=(pixels[index+top]>>8) & 255; // middle top
     G+=(pixels[index+bottom]>>8) & 255; // middle bottom
     G=(G/5);

     B=pixels[left+index] & 255; // left middle
     B+=pixels[right+index] & 255; // right middle
     B+=(pixels[index] & 255); // middle middle
     B+=pixels[index+top] & 255; // middle top
     B+=pixels[index+bottom] & 255; // middle bottom
     B=(B/5);
     pixels[index]=(R<<16)+(G<<8)+B;
   }
 }

}

class blendmodes{
 int[] theList=new int[6];
 color theColor;
 blendmodes(){
 }
 void makeList(color cl1, color cl2){
   theList[0]=int(red(cl1));
   theList[1]=int(green(cl1));
   theList[2]=int(blue(cl1));
   theList[3]=int(red(cl2));
   theList[4]=int(green(cl2));
   theList[5]=int(blue(cl2));
 }
 void makeColor(){
   theColor=color(theList[0],theList[1],theList[2]);
 }

 color average(color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     theList[i]=(theList[i]+theList[i+3])>>1;
   }
   makeColor();
   return(theColor);
 }

 color multiply(color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     theList[i]=(theList[i]*theList[i+3])>>8;
   }
   makeColor();
   return(theColor);
 }

 color screen(color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     theList[i]=255 - ((255-theList[i]) * (255-theList[i+3]) >>8);
   }
   makeColor();
   return(theColor);
 }

 color darken(color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     if(theList[i]<theList[i+3]){
       theList[i]=theList[i];
     }else{
       theList[i]=theList[i+3];
     }
   }
   makeColor();
   return(theColor);
 }
 color lighten(color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     if(theList[i]>theList[i+3]){
       theList[i]=theList[i];
     }else{
       theList[i]=theList[i+3];
     }
   }
   makeColor();
   return(theColor);
 }

 color difference (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     theList[i]=abs(theList[i]-theList[i+3]);
   }
   makeColor();
   return(theColor);
 }

 color negation (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     theList[i]=255-abs(255-theList[i]-theList[i+3]);
   }
   makeColor();
   return(theColor);
 }

 color exclusion (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     theList[i]=theList[i]+theList[i+3]-(theList[i]*theList[i+3]>>7);
   }
   makeColor();
   return(theColor);
 }

 color overlay (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     if (theList[i] < 128){
       theList[i]=(theList[i]*theList[i+3])>>7;
     }else{
       theList[i]= 255 -((255-theList[i])*(255-theList[i+3])>>7);
     }
   }
   makeColor();
   return(theColor);
 }

 color hardLight  (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     if (theList[i+3] < 128){
       theList[i]=(theList[i]*theList[i+3])>>7;
     }else{
       theList[i]= 255 -((255-theList[i])*(255-theList[i+3])>>7);
     }
   }
   makeColor();
   return(theColor);
 }

 color dodge  (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     if(theList[i+3]==255){
       theList[i]= 255;
     }else{
       int res = (theList[i] << 8) / (255-theList[i+3]);
       if (res>255) {
         theList[i]= 255;
       } else{
         theList[i]=res;
       }
     }
   }
   makeColor();
   return(theColor);
 }

 color burn  (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     if(theList[i+3]==0){
       theList[i]= 0;
     }else{
       int res =  255 - (((255-theList[i]) << 8) / theList[i+3]);
       if (res<0) {
         theList[i]= 0;
       } else{
         theList[i]=res;
       }
     }
   }
   makeColor();
   return(theColor);
 }

 color reflect  (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     if (theList[i+3]== 255){
       theList[i]= 255;
     }else{
       int res = theList[i]*theList[i] / (255-theList[i+3]);
       if (res > 255){
         theList[i]= 255;
       }else{
         theList[i]=res;
       }
     }
   }
   makeColor();
   return(theColor);
 }

 color glow  (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     if (theList[i]== 255){
       theList[i]= 255;
     }else{
       int res = theList[i+3]*theList[i+3] / (255-theList[i]);
       if (res > 255){
         theList[i]= 255;
       }else{
         theList[i]=res;
       }
     }
   }
   makeColor();
   return(theColor);
 }

 color freeze  (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     if (theList[i+3]==0){
       theList[i+3]= 0;
     }else{
       int res =int(255-sq(255-theList[i])/theList[i+3]);
       if (res < 0){
         theList[i]= 0;
       }else{
         theList[i]=res;
       }
     }
   }
   makeColor();
   return(theColor);
 }

 color heat  (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     if (theList[i]==0){
       theList[i]= 0;
     }else{
       int res =int(255-sq(255-theList[i+3])/(theList[i]));
       if (res < 0){
         theList[i]= 0;
       }else{
         theList[i]=res;
       }
     }
   }
   makeColor();
   return(theColor);
 }

 color stamp  (color cl1, color cl2 ){
   makeList(cl1,cl2);
   for (int i=0;i<3;i++){
     int res = theList[i] + 2*theList[i+3] - 256;
     if (res < 0){
       theList[i]= 0;
     }else if (res > 255){
       theList[i]= 255;
     }else{
       theList[i]= res;
     }
   }
   makeColor();
   return(theColor);
 }
}