/* 
   Made by SirDude		mein@cs.umn.edu
   http://www.cs.umn.edu/~mein/blender
   Tue Mar  7 15:38:37 CST 2000
   This sequence plugin takes in one strip and allows you to alter
   the coloring of it let me know if you have any suggestions for 
   improving it and or questions about it.

   hsv formula's taken from Computer Graphics Principles and Practice
	Foley, vanDam, Feiner, Hughes  Second Edition Page 592
 */

#include "plugin.h"

/* ******************** GLOBAL VARIABLES ***************** */
char name[24]= "invert";	
/* structure for buttons, 
 *  butcode      name           default  min  max  0
 */

VarStruct varstr[]= {
   { LABEL,			"Input: 1 strip", 0.0, 0.0, 0.0, ""},
   { LABEL, 	"Invert", 0,0,0, ""},
   { TOG|INT,     "Red", 1.0,        0.0,    1.0, "Invert Red"},
   { TOG|INT,     "Green", 1.0,        0.0,    1.0, "Invert Green"},
   { TOG|INT,     "Blue", 1.0,        0.0,    1.0, "Invert Blue"},
   { TOG|INT,     "Alpha", 0.0,        0.0,    1.0, "Invert Alpha"},
   { LABEL, 	"RGB Modifiers", 0,0,0, ""},
   { NUMSLI|FLO,	"redSat", 0.0,	-255,	255, 
	"Modify Saturation"},
   { NUMSLI|FLO,	"BlueSat", 0.0,	-255,	255, 
	"Modify Saturation"},
   { NUMSLI|FLO,	"GreenSat", 0.0,	-255,	255, 
	"Modify Saturation"},
   { NUMSLI|FLO,	"AlphaSat", 0.0,	-255,	255, 
	"Modify Saturation"},
   { LABEL, 	"HSV Modifiers", 0,0,0, ""},
   { NUMSLI|FLO,	"Hue", 0.0,	-1,	1, "Modify Saturation"},
   { NUMSLI|FLO,	"Saturation", 0.0,	-1,	1, "Modify Saturation"},
   { NUMSLI|FLO,	"Value", 0.0,	-1,	1, "Modify Saturation"},
};

/* The cast struct is for input in the main doit function
   Varstr and Cast must have the same variables in the same order */ 

typedef struct Cast {
	int label;			/* because of the 'label' button */
        int label2;
        int rsat, bsat, gsat, asat;
        int label3;
	float redsat, bluesat, greensat, alphasat;
	int label4;
	float hn, sn, vn;
} Cast;


/* cfra: the current frame */

float cfra;

void plugin_seq_doit(Cast *, float, float, int, int, ImBuf *, ImBuf *, ImBuf *, ImBuf *);

/* ******************** Fixed functions ***************** */

int plugin_seq_getversion(void) 
{
	return B_PLUGIN_VERSION;
}

void plugin_but_changed(int but) 
{
}

void plugin_init()
{
}

void plugin_getinfo(PluginInfo *info)
{
	info->name= name;
	info->nvars= sizeof(varstr)/sizeof(VarStruct);
	info->cfra= &cfra;

	info->varstr= varstr;

	info->init= plugin_init;
	info->seq_doit= (SeqDoit) plugin_seq_doit;
	info->callback= plugin_but_changed;
}

void plugin_seq_doit(Cast *cast, float facf0, float facf1, int x, int y, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibufo, ImBuf *use) {
   float s, h, v, p, q;
   int xo, t, max, min, i, d, f;
   char *in1, *out;	
	
   xo= x;
   in1=  (char *)ibuf1->rect;
   out=  (char *)ibufo->rect;
	
   while(y--) {
      x= xo;
      while(x--) {
         out[0] = in1[0];
         out[1] = in1[1];
         out[2] = in1[2];
         out[3] = in1[3];

         if (cast->rsat) out[0]= 255.0 - out[0];
         if (cast->gsat) out[1]= 255.0 - out[1];
         if (cast->bsat) out[2]= 255.0 - out[2];
         if (cast->asat) out[3]= 255.0 - out[3];

         out[0] = out[0] + cast->redsat;
         out[1] = out[1] + cast->greensat;
         out[2] = out[2] + cast->bluesat;
         out[3] = out[3] + cast->alphasat;
         if ((cast->hn >= 0.01) || (cast->hn <=-0.01) ||
             (cast->sn >= 0.01) || (cast->sn <=-0.01) ||
             (cast->vn >= 0.01) || (cast->vn <=-0.01)) {
  	   /* Compute HSV */
            max= MAX2(MAX2(out[0],out[1]), out[2]);
            min= MIN2(MIN2(out[0],out[1]), out[2]);
            v=max;
            d=max-min;
            if (max==0)  {
               s=0;
            } else {
               s=d/max;
            }
            if (d > 0) {
	       if (out[0] ==max) h = (out[2] - out[1])/d;
               else if (out[2] == max) h = 2 + (out[1] - out[0])/d;
 	       else h= 4 + (out[0] - out[2])/d;
	       h = h * 60;
	       if (h < 0.0) h = h + 360.0;
            } else {
	       s=0;
	       h=-1;
	    }
   	    h+=cast->hn;
	    s+=cast->sn;
	    v+=cast->vn;
	    h =MAX2(MIN2(h,0),1);
	    s =MAX2(MIN2(s,0),1);
	    v =MAX2(MIN2(v,0),1);

	    /* compute RGB from new HSV; */
	    if (s==0) {
	       for(t=0;t<4;t++) out[t]=v;
 	    } else {
	       if (h==360) h=0;
	       else h=h/60;
	       i=floor(h);
	       f=h-i;
	       p=floor(v*(1-s) * 255);
	       q=floor(v*(1-(s*f)) * 255);
	       t=floor(v*(1-(s*(1-f))) * 255);
	       switch(i) {
	          case 0:
	  	     out[0]=v;
	  	     out[2]=t;
	     	     out[1]=p;
	             break;
	          case 1:
	  	     out[0]=q;
	  	     out[2]=v;
	  	     out[1]=p;
	             break;
	          case 2:
	  	     out[0]=p;
	  	     out[2]=v;
	  	     out[1]=t;
	             break;
	          case 3:
	  	     out[0]=p;
	  	     out[2]=q;
	  	     out[1]=v;
	             break;
	          case 4:
	  	     out[0]=t;
	  	     out[2]=p;
	  	     out[1]=v;
	             break;
	          case 5:
	  	     out[0]=v;
	  	     out[2]=p;
	  	     out[1]=q;
	             break;
 	       }
	    }
         }
/* printf("out[0] = %d out[1] = %d out[2] = %d\n",out[0],out[1],out[2]); */
         for(t=0;t<4;t++) {
            out[t] = MIN2(MAX2(out[t],0),255);
         } 
	 in1 +=4;
	 out +=4;
      }
   }
}
