/* 
 * Image pixelizer plugin by Calle Laakkonen
 * Changes:
 * 21.12.2004 - Fixed IPO support
 * 11.12.2004 - Created plugin
 */

#include "plugin.h"

/* ******************** GLOBAL VARIABLES ***************** */

#define MAX_PIXEL 32

char name[24]= "Pixelize";

/* structure for buttons, 
 *  butcode         name         default  min  max  0
 */
VarStruct varstr[]= {
    {LABEL,         "Input: 1 strip", 0.0, 0.0, 0.0, ""},
    {NUMSLI|INT,    "Width: ",      2,	1,	MAX_PIXEL, "Pixel width"},
    {NUMSLI|INT,    "Height: ",	    2,	1,	MAX_PIXEL, "Pixel height"},
    {TOG|INT,       "Animated",     0.0,    0.0,    1.0, "Use IPO to control pixel size"}
};

/* 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 dummy;			/* because of the 'label' button */
	int w;
	int h;
	int use_ipo;
} 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()
{
}

/*** Return average color of rectange ***/
static unsigned int get_rect(int x,int y,int w,int h,ImBuf *buf) {
    unsigned int *ptr;
    unsigned int red=0,green=0,blue=0,alpha=0;
    int X,Y,size;

    if(x+w>=buf->x) w=buf->x-x;
    if(y+h>=buf->y) h=buf->y-y;

    ptr=buf->rect + y*buf->x + x;
    for(Y=0;Y<h;Y++) {
        for(X=0;X<w;X++,ptr++) {
            alpha+=*((char*)ptr);
            blue+=*((char*)ptr+1);
            green+=*((char*)ptr+2);
            red+=*((char*)ptr+3);
        }
        ptr+=buf->x-w;
    }
    size=w*h;
    alpha/=size; blue/=size; green/=size; red/=size;
    return alpha | blue<<8 | green<<16 | red<<24;
}

/*** Fill Rectangle ***/
static void fill_rect(int x,int y,int w,int h,unsigned int color,ImBuf *buf) {
    unsigned int *ptr;
    int X,Y;

    if(x+w>=buf->x) w=buf->x-x;
    if(y+h>=buf->y) h=buf->y-y;

    ptr=buf->rect + y*buf->x + x;
    for(Y=0;Y<h;Y++) {
        for(X=0;X<w;X++,ptr++) {
            *ptr=color;
        }
        ptr+=buf->x-w;
    }
}

void plugin_seq_doit(Cast *cast, float facf0, float facf1, int x, int y, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *out, ImBuf *use)
{
    unsigned int pixelw,pixelh,X,Y;

    if(cast->use_ipo==0) {
        pixelw=cast->w;
        pixelh=cast->h;
    } else {
        if(facf0>1.0) facf0=1.0;
        pixelw = MAX_PIXEL*facf0+0.5;
        if(pixelw<1) pixelw=1;
        pixelh = pixelw;
    }

    for(Y=0;Y<y;Y+=pixelh) {
        for(X=0;X<x;X+=pixelw) {
            unsigned int pix;
            pix=get_rect(X,Y,pixelw,pixelh,ibuf1);
            fill_rect(X,Y,pixelw,pixelh,pix,out);
        }
    }
}

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;
}

