/* 
 * flipflop.c
 *
 * 2003 by Albrecht 'LayBack' Jacobs <Albrecht.Jacobs@gmx.de>
 * Take one strip as input and flip and/or flop the image.
 * $Id: flipflop.c,v 1.7 2003/03/02 14:36:34 aj Exp aj $
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
 * GNU General Public License for more details. 
 *
 */

/* 
 * Most of this code is copied from other plugins.
 * Beware: I don't really understand what I am doing here!
 * Colors and Alpha are not modified.
 * There is no IPO support.
 * Fields seem to work, Z buffer doesn't yet.
 */

#include "plugin.h"

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

char name[] = "FlipFlop 0.3"; 

/* structure for buttons, 
 *	 butcode name		default	min	max	tip
 */

VarStruct varstr[] = {
	{LABEL,	"Input: 1 Strip", 0.0,	0.0,	0.0,	""},
	{TOG|INT,	"Flip",		1.0,	0.0,	1.0,	"Flip the image"},
	{TOG|INT,	"Flop",		1.0,	0.0,	1.0,	"Flop the image"},
};

/* 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 flip;
	int flop;
} 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 *out, ImBuf *use)
{
	char *rectOrg, *rectDest;
	int sizeX, sizeY, res, i, j, x_rev, y_rev;

	/* The resolution of the image buffer is determined by the settings
	 * of the Display Buttons: 'SizeX', 'SizeY', '100%', '75%', ... */
	sizeX = ibuf1->x;
	sizeY = ibuf1->y;
	res = sizeX * sizeY;

	rectOrg	= (char *) ibuf1->rect;
	rectDest = (char *) out->rect;

	/* y: rows, x: columns */

	if ((cast->flip == 1) & (cast->flop == 1)) {
		/* turn image upside down (flipflop) */
		for (y=0; y<sizeY; y++) {
			for (x=0; x<sizeX; x++) {
				i = (y * sizeX + x) * 4;
				j = ((res - 1) * 4) - i;
				rectDest[i]		 = rectOrg[j];		  /* R */
				rectDest[i + 1] = rectOrg[j + 1];  /* G */
				rectDest[i + 2] = rectOrg[j + 2];  /* B */
				rectDest[i + 3] = rectOrg[j + 3];  /* A */
			}
		}
	} else if ((cast->flip == 0) & (cast->flop == 1)) {
		/* mirror image vertically */
		for (y=0; y<sizeY; y++) {
			y_rev = sizeY - 1 - y;
			for (x=0; x<sizeX; x++) {
				i = (y * sizeX + x) * 4;
				j = ((res - 1) * 4) - (y_rev * sizeX + x) * 4;
				rectDest[i]		 = rectOrg[j];		  /* R */
				rectDest[i + 1] = rectOrg[j + 1];  /* G */
				rectDest[i + 2] = rectOrg[j + 2];  /* B */
				rectDest[i + 3] = rectOrg[j + 3];  /* A */
			}
		}
	} else if ((cast->flip == 1) & (cast->flop == 0)) {
		/* mirror image horizontally */
		for (y=0; y<sizeY; y++) {
			for (x=0; x<sizeX; x++) {
				x_rev = sizeX - 1 - x;
				i = (y * sizeX + x) * 4;
				j = ((res - 1) * 4) - (y * sizeX + x_rev) * 4;
				rectDest[i]		 = rectOrg[j];		  /* R */
				rectDest[i + 1] = rectOrg[j + 1];  /* G */
				rectDest[i + 2] = rectOrg[j + 2];  /* B */
				rectDest[i + 3] = rectOrg[j + 3];  /* A */
			}
		}
	} else {
		/* do nothing (copy input to output) */
		memcpy(out->rect, ibuf1->rect, res * sizeof(out->rect[0]));
	}
} /* plugin_seq_doit() */

/* EOF */
