458 lines
12 KiB
C
458 lines
12 KiB
C
/*
|
|
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;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, ">>> %s ( %p %p )\n", src, dst);
|
|
#endif
|
|
|
|
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);
|
|
fprintf(stderr, "%s: seuil rgb -> %d\n", __func__, foo);
|
|
|
|
Image_2x2_contours_0(tmp);
|
|
Image_copy(tmp, dst);
|
|
|
|
Image_DeAllocate(tmp); free(tmp);
|
|
|
|
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 (%s) simple -> %d\n", type, 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;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|