/*
			SPECIALS EFFECTS
 */

#include  <stdio.h>
#include  <string.h>
#include  <stdlib.h>

#include  "tga_outils.h"

/*::------------------------------------------------------------------::*/
#define		EFF_4BITS	4
#define		EFF_CLASS0	5
#define		EFF_DECOMP	6
#define		EFF_FLATGRAY	7
#define		EFF_GRAY	9
#define		EFF_GRAYK	11
#define		EFF_MOSAIC 	13
#define		EFF_MOSAIC0	14
#define		EFF_PHMATON	15	/* new 30 avril 2007 */
#define		EFF_MIRROR	16
#define		EFF_EXTRBIT0	17	/* new 11 mars 2015 */
#define		EFF_EXTRBIT1	18	/* new 11 mars 2015 */
#define		EFF_NEGATE	20
#define		EFF_SEUIL	22
#define		EFF_DEGOULE	23	/* new octobre 2015 */
#define		EFF_NOISE	27
#define		EFF_PIXELX	33
#define		EFF_PIXELY	34	/* new 30 mars 2007 */
#define		EFF_FIVE	35	/* new 16 dec 2007 */
#define		EFF_WARP_0	36	/* new 17 janv 2015 */
#define		EFF_ROTULACION	37	/* new  6 juillet 2022 */
#define		EFF_RECURSE	40
#define		EFF_RGBMSKH	41
#define		EFF_RGBMSKV	42
#define		EFF_RGBMSK2	43
#define		EFF_RGBMSKR	44
#define		EFF_BICOLOR0	46	/* new 17 janv 2010 */
#define		EFF_BICOLOR1	47	/* new 18 janv 2010 */
#define		EFF_BICOLOR2	48	/* new 22 janv 2010 */
#define		EFF_ROT4PIX	51
#define		EFF_CONT2X2	52	/* new 1 sept 2008 */
#define		EFF_CONT2X2G	53	/* new 8 sept 2008 */
#define 	EFF_SCRATCH	54
#define		EFF_SINW0	55
#define		EFF_SINW1	56
#define		EFF_SWAPCOL	58
#define		EFF_SWAPNIBBLE	59
#define		EFF_UPDOWN	65
#define		EFF_SHIFT_XY	66	/* new 8 mai 2009 */
#define		EFF_WATER	72
#define		EFF_FUKUNG	75
#define		EFF_CLASS1	83	/* new 20 nov 2013 */
#define		EFF_GLITCH	87	/* new 13 oct 2014 */
#define		EFF_X0		100
#define		EFF_X1		101
#define		EFF_X2		102
#define		EFF_X3		103
#define		EFF_X4		104
#define		EFF_X5		105

mot_clef mots_clef[] =
{
{ "4bits",	EFF_4BITS,	"",	"and 0xf0"			},
{ "class0",	EFF_CLASS0,	"",	"experimental"			},
{ "decomp",	EFF_DECOMP,	"f",	"flag: print colors"		},
{ "flatgray",	EFF_FLATGRAY,	"i",	"detect flatgray zones"		},
{ "gray",	EFF_GRAY,	"", 	""				},
{ "grayk",	EFF_GRAYK,	"iii", 	"3 coefs"			},
{ "mirror",	EFF_MIRROR,	"", 	""				},
{ "updown",	EFF_UPDOWN,	"",	"upside down"			},
{ "rotulacion",	EFF_ROTULACION,	"d",	"angle in degree"		},
{ "extrbits0",	EFF_EXTRBIT0,	"iii",	"shifts for r, g & b"		},
{ "mosaic",	EFF_MOSAIC,	"",	"?"				},
{ "mosaic0",	EFF_MOSAIC0,	"iif",	"?"				},
{ "photomaton", EFF_PHMATON,	"",	""				},
{ "negate",	EFF_NEGATE,	"", 	""				},
{ "seuil",	EFF_SEUIL,	"iii",	"rgb thresholds"		},
{ "degoule",	EFF_DEGOULE,	"ii",	"k1 & k2 ? wtf ?"		},
{ "noise",	EFF_NOISE,	"i", 	"0..255"			},
{ "pixelX",	EFF_PIXELX,	"",	"prototype"			},
{ "pixelY",	EFF_PIXELY,	"",	"prototype"			},
{ "efive",	EFF_FIVE,	"",	"got it, code it"		},
{ "warp0",	EFF_WARP_0,	"dii",	"angle xc yc"			},
{ "recurse",	EFF_RECURSE,	"i",	"classic and recursif"		},
{ "rgbmskh",	EFF_RGBMSKH,	"i",	"'par' is a gray level"		},
{ "rgbmskv",	EFF_RGBMSKV,	"i",	"'par' is a gray level"		},
{ "rgbmsk2",	EFF_RGBMSK2,	"i",	"'par' is a gray level"		},
{ "rgbmskr",	EFF_RGBMSKR,	"i",	"'par' is a gray level"		},
{ "bicolor0",	EFF_BICOLOR0,	"i",	"?"				},
{ "bicolor1",	EFF_BICOLOR1,	"ii",	"..."				},
{ "rot4pix",	EFF_ROT4PIX,	"i",	"???"				},
{ "cont2x2",	EFF_CONT2X2,	"",	"contours 2x2 en auto"		},
{ "cont2x2g",	EFF_CONT2X2G,	"",	"contours 2x2 sur le gris"	},
{ "scratch",	EFF_SCRATCH,	"i",	"coredumper :)"			},
{ "sinwave1",	EFF_SINW1,	"dddddd", "strange effect"		},
{ "swapcol",	EFF_SWAPCOL,	"s",	"rg rb bg"			},
{ "swapnibble",	EFF_SWAPNIBBLE,	"",	"swap all pix nibbles"		},
{ "shift_xy",	EFF_SHIFT_XY,	"ii",	"les deux offsets"		}, 
{ "water",	EFF_WATER,	"i", 	"'par' is water distance"	},
/* { "fukung",	EFF_FUKUNG,	"i",	"OMG ! WTF ?"			}, */
{ "class1",	EFF_CLASS1,	"iiii",	"R G B diameter"		},
{ "glitch",	EFF_GLITCH,	"si",	"type nbre"			},
{ "x0",		EFF_X0,		"iii", 	"3 thresholds for r, g, b"	},
{ "x1",		EFF_X1,		"", 	"xor other componant"		},
{ "x2",		EFF_X2,		"iii", 	"trigonometry"			},
{ "x3",		EFF_X3,		"iis", 	""				},
{ "x4",		EFF_X4,		"i", 	"essai Aug 2008"		},
{ "x5",		EFF_X5,		"iii", 	"essai Sept 2008"		},
{ NULL,		0,		NULL,	NULL				}
};
/*::------------------------------------------------------------------::*/
void usage(int flag)
{
fprintf(stderr, "*** tga_effects v 0.1.58 [%s] %s\n",
				TGA_OUTILS_VERSION, TGA_OUTILS_COPYLEFT);

fprintf(stderr, "\nUsage:\n");
fprintf(stderr, "\ttga_effects <src.tga> EFF <dst.tga> [p1] ... [p8]\n");
if (flag) {
	Image_print_version(0);
	liste_mots_clefs(mots_clef, 42);
	}
else	{
	fprintf(stderr, "\ttry 'tga_effects list' for a list.\n");
	}
exit(5);
}
/*::------------------------------------------------------------------::*/
/* fonction codee a la rache le 8 septembre 2008.
 * a passer un jour ou l'autre dans la libimage */
int contours_du_gris(Image_Desc *src, Image_Desc *dst)
{
Image_Desc	*tmp;
int		foo;

tmp = Image_clone(src, 1);

foo = Image_to_gray(src, tmp, 0);
#if DEBUG_LEVEL
fprintf(stderr, "to_gray %d\n", foo);
#endif

foo = Image_seuil_RGB(tmp, tmp, 64, 128, 192);
#if DEBUG_LEVEL
fprintf(stderr, "seuil rgb %d\n", foo);
#endif

Image_2x2_contours_0(tmp);
Image_copy(tmp, dst);

return 42;
}
/*::------------------------------------------------------------------::*/
static int do_classif_1(Image_Desc *img, int kr, int kg, int kb, int diam)
{
int		foo;
Une_Classe_Sph	classes[2];
int		r, g, b;
Image_Rect	zone;	

#if DEBUG_LEVEL
fprintf(stderr, "%s ( %p  %d %d %d  %d )\n", __func__, img, kr, kg, kb, diam);
#endif

zone.x = zone.y = 0;
zone.w = img->width;
zone.h = img->height;

foo = Image_stats_zone_0(img, &zone, &r, &g, &b, NULL, NULL, NULL);
 
#if DEBUG_LEVEL
fprintf(stderr, "%s,   stats  -> %d %d %d\n", __func__, r, g, b);
#endif

classes[0].rc = r; classes[0].gc = g; classes[0].bc = b;
classes[0].rad = 30;
classes[0].r = classes[0].g = 50; classes[0].b = 200;

classes[1].rc = kr; classes[1].gc = kg; classes[1].bc = kb;
classes[1].rad = diam;
classes[1].r = classes[1].g = 250; classes[1].b = 20;

if (must_be_verbose()) {
	Image_display_classes(classes, 2, "umpf", 0);
	}

foo = Image_classif_1(img, img, classes, 2, 0);
fprintf(stderr, "classif 1 -> %d\n", foo);

return FUNC_IS_BETA;
}
/*::------------------------------------------------------------------::*/
/* new 13 OCT 2014 - comburant: Kellegen 8.0 50cl */
static int do_glitch(Image_Desc *src, Image_Desc *dst, char *type, int nbre)
{
int		foo;

#if DEBUG_LEVEL
fprintf(stderr, "%s :\n\t%p %p  %s  %d\n", __func__,
			src, dst, type, nbre);
#endif

foo = Image_Glitch_simple(src, dst, nbre);
fprintf(stderr, "glitch simple -> %d\n", foo);

return 0;
}
/*::------------------------------------------------------------------::*/
/*
 *	argv[1]		source.tga
 *	argv[2]		type de l'effet
 *	argv[3]		destination.tga
 */
#define FIRST_PARAM	4
int main(int argc, char *argv[])
{
Image_Desc	*src, *dst;
int		foo;
int		commande, nbargs, idx;
double		angle;
int		xc, yc;

/*
 *		USE GETOPT HERE
 */

dump_command_line(argc, argv, 0);
if (argc==2 && !strcmp(argv[1], "-?"))		usage(0);
if (argc==2 && !strcmp(argv[1], "list"))	usage(1);
if (argc < 4) usage(0);

srand(getpid());

/* recherche du type d'effet demande */
idx = cherche_mot_clef(argv[2], mots_clef, &commande, &nbargs);
if (idx < 0)
	{
	fprintf(stderr, "tga_effects: mot-clef '%s' inconnu...\n", argv[2]);
	exit (5);
	}

if ( (argc-nbargs) != FIRST_PARAM )
	{
	fprintf(stderr, "%s: bad number of parameters\n", argv[0]);
	exit(5);
	}

/* analyse des parametres */
foo = parse_parametres(argc, argv, mots_clef[idx].ptypes, FIRST_PARAM);

if ((src = Image_TGA_alloc_load(argv[1]))==NULL)
	{
	fprintf(stderr, "tga_effect: can't load image %s\n", argv[1]);
	exit(5);
	}
if ( (dst=Image_clone(src, 1)) == NULL )
	{
	fprintf(stderr, "tga_effect: can't clone %p\n", src);
	exit(1);
	}
/* XXX ne serait-il pas de bon ton d'effacer l'image de destination ? */

switch (commande)
	{
	case EFF_4BITS:
		foo = Image_col4bits_and(src, dst);
		break;
	case EFF_CLASS0:
		foo = Image_classif_0(src, dst);
		break;
	case EFF_DECOMP:
		foo = Image_decompose(src, dst, GFP(0));
		break;
	case EFF_FLATGRAY:
		foo = Image_detect_flat_gray(src, dst, GIP(0), 0);
		break;
	case EFF_GRAY:
		foo = Image_to_gray(src, dst, 0);
		break;
	case EFF_GRAYK:
		foo = Image_to_gray_k(src, dst, GIP(0), GIP(1), GIP(2), 0);
		break;
	case EFF_MIRROR:
		foo = Image_mirror(src, dst, 0);
		break;
	case EFF_ROTULACION:			 /* new 6 juillet 2022 */
		angle = GDP(0);
		fprintf(stderr, "%s: angle rotulacion = %f\n", __FILE__, angle);
		foo = Image_center_rotate(src, dst, angle);
		break;
	case EFF_EXTRBIT0:
		foo = Image_extrbits_0(src, dst, GIP(0), GIP(1), GIP(2));
		break;
	case EFF_MOSAIC:
		foo = Image_mosaic_simple(src, dst);
		break;
	case EFF_MOSAIC0:
		/* explanation of the parameters, please */
		foo = Image_mosaic_0(src, dst, GIP(0), GIP(1), GFP(2));
		break;
	case EFF_PHMATON:
		foo = Image_photomaton_0(src, dst);
		break;
	case EFF_NEGATE:
		foo = Image_negate(src, dst);
		break;
	case EFF_SEUIL:
		foo = Image_seuil_RGB(src, dst, GIP(0), GIP(1), GIP(2));
		break;
	case EFF_DEGOULE:
		foo = Image_degouline_0(src, dst, GIP(0), GIP(1));
#if DEBUG_LEVEL
		fprintf(stderr, "Degouline ---> %d\n", foo);
#endif
		break;
	case EFF_NOISE:
		foo = Image_noise(src, dst, GIP(0));
		break;
	case EFF_PIXELX:
		/* fprintf(stderr, "Experimental : pixel X !\n"); */
		foo = Image_pixeliz_X(src, dst);
		break;
	case EFF_PIXELY:
		/* fprintf(stderr, "Experimental : pixel Y!\n"); */
		foo = Image_pixeliz_Y(src, dst);
		break;
	case EFF_FIVE:		/* XXX */
		foo = Image_effect_x_5(src, dst, 0, 0, 0);
		break;
	case EFF_WARP_0:
		angle = 33.5;
		xc = GIP(1); yc = GIP(2);
		foo = Image_warp_essai_0(src, dst, angle, xc, yc);
#if DEBUG_LEVEL
		fprintf(stderr, "warp0 %f %d %d > %d\n", angle, xc, yc, foo);
#endif
		break;
	case EFF_RECURSE:
#if DEBUG_LEVEL
		fprintf(stderr, "RECURSE EXPERIMENTAL !\n");
#endif
		foo = Image_call_recursion_0(src, dst, GIP(0));
		break;
	case EFF_RGBMSKH:
		foo = Image_rgbmask_H(src, dst, GIP(0));
		break;
	case EFF_RGBMSKV:
		foo = Image_rgbmask_V(src, dst, GIP(0));
		break;
	case EFF_RGBMSK2:
		foo = Image_rgbmask_2(src, dst, GIP(0));
		break;
	case EFF_RGBMSKR:
		foo = Image_rgbmask_R(src, dst, GIP(0));
		break;
	case EFF_BICOLOR0:
		foo = Image_BiColor_0(src, dst, GIP(0));
		break;
	case EFF_BICOLOR1:
		foo = Image_BiColor_1(src, dst, GIP(0), GIP(1));
		break;
	case EFF_ROT4PIX:
		foo = Image_2x2_rot4pix(src, dst, GIP(0));
		break;
	case EFF_CONT2X2:
		Image_AutoSeuilRGB(src, dst);
		foo = Image_2x2_contours_0(dst);
		break;
	case EFF_CONT2X2G:
		foo = contours_du_gris(src, dst);
		break;
	case EFF_SCRATCH:
		foo = Image_scratch(src, dst, GIP(0));
		break;
	case EFF_SWAPCOL:
		Image_copy(src, dst);
		foo = Image_swap_colors(dst, GSP(0));
		break;
	case EFF_SWAPNIBBLE:
		foo = Image_swap_nibbles(src, dst);
		break;
	case EFF_UPDOWN:
		foo = Image_upside_down(src, dst, 0);
		break;
	case EFF_SHIFT_XY:
		foo = Image_shift_xy(src, dst, GIP(0), GIP(1));
		break;

	case EFF_WATER:
		foo = Image_water(src, dst, GIP(0));
		break;

	case EFF_CLASS1:
		/* XXX not very trustable */
		foo = do_classif_1(dst, GIP(0), GIP(1), GIP(2), GIP(3));
		break;

	/*  new 13 october 2014 */
	case EFF_GLITCH:
		foo = do_glitch(src, dst, GSP(0), GIP(1));
		fprintf(stderr, "do glitch -> %d\n", 0);
		break;

	case EFF_X0:
		foo = Image_effect_x_0(src, dst, GIP(0), GIP(1), GIP(2));
		break;
	case EFF_X1:
		foo = Image_effect_x_1(src, dst);
		break;
	case EFF_X2:
#if DEBUG_LEVEL
		fprintf(stderr, "\teff X2 badly implemented :)\n");
#endif
		foo = Image_effect_x_2(src, dst, 12, 12, 0);
		break;
	case EFF_X3:
#if DEBUG_LEVEL
		fprintf(stderr, "\teff X3 badly implemented :)\n");
#endif
		foo = Image_effect_x_3(src, dst, GIP(0), GIP(1), GSP(2));
		break;
	case EFF_X4:
		foo = Image_effect_x_4(src, dst, GIP(0));
		break;
	case EFF_X5:
#if DEBUG_LEVEL
		fprintf(stderr, "\teff X5 badly implemented :)\n");
#endif
		foo = Image_effect_x_5(src, dst, GIP(0), GIP(1), GIP(2));
		break;

	default:
		fprintf(stderr, "%s invalid command %d, plopped out\n",
				argv[0], commande);
		foo = 666;
		break;
	}

if (foo) {
	fprintf(stderr, "%s: return code is %d\n", __FILE__, foo);
	Image_print_error(argv[0], foo);
	}

foo = Image_TGA_save(argv[3], dst, 0);
if (foo) {
	fprintf(stderr, "%s: error %d saving '%s'\n", __FILE__, foo, argv[3]);
	Image_print_error(argv[0], foo);
	}

return 0;
}
/*::------------------------------------------------------------------::*/