2022-06-26 11:06:35 +02:00
|
|
|
|
/*
|
|
|
|
|
filtrages sur les images
|
|
|
|
|
------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
2022-06-27 00:48:18 +02:00
|
|
|
|
#include "../tthimage.h"
|
2022-06-26 11:06:35 +02:00
|
|
|
|
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
void
|
|
|
|
|
Image_filtre_display(FILE *ou, int *mat)
|
|
|
|
|
{
|
|
|
|
|
int cumul, foo;
|
|
|
|
|
|
|
|
|
|
for (cumul=foo=0; foo<9; foo++) cumul+=mat[foo];
|
|
|
|
|
|
|
|
|
|
fprintf(ou, "\t+------ Filtre ------+----- Coefs ------+\n");
|
|
|
|
|
fprintf(ou, "\t| %4d %4d %4d | divisor: %4d |\n",
|
|
|
|
|
mat[0], mat[1], mat[2], mat[9]);
|
|
|
|
|
fprintf(ou, "\t| %4d %4d %4d | offset: %4d |\n",
|
|
|
|
|
mat[3], mat[4], mat[5], mat[10]);
|
|
|
|
|
fprintf(ou, "\t| %4d %4d %4d | cumul: %4d |\n",
|
|
|
|
|
mat[6], mat[7], mat[8], cumul);
|
|
|
|
|
fprintf(ou, "\t+--------------------+------------------+\n");
|
|
|
|
|
|
|
|
|
|
fflush(ou);
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
void
|
|
|
|
|
Image_rotate_filtre(int *m)
|
|
|
|
|
{
|
|
|
|
|
register int foo;
|
|
|
|
|
|
|
|
|
|
foo = m[0];
|
|
|
|
|
m[0] = m[3];
|
|
|
|
|
m[3] = m[6];
|
|
|
|
|
m[6] = m[7];
|
|
|
|
|
m[7] = m[8];
|
|
|
|
|
m[8] = m[5];
|
|
|
|
|
m[5] = m[2];
|
|
|
|
|
m[2] = m[1];
|
|
|
|
|
m[1] = foo;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
int
|
|
|
|
|
Image_convolueur3(Image_Desc *in, Image_Desc *out, int *mat)
|
|
|
|
|
{
|
|
|
|
|
int foo;
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
|
fprintf(stderr, "warning: %s is (maybe) obsolete\n", __func__);
|
|
|
|
|
#endif
|
|
|
|
|
foo = Image_convolueur_2(in, out, mat, "rgb");
|
|
|
|
|
|
|
|
|
|
return foo;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
int
|
|
|
|
|
Image_convolueur_2(Image_Desc *in, Image_Desc *out, int *mat, char *planes)
|
|
|
|
|
{
|
|
|
|
|
int foo, x, y;
|
|
|
|
|
long lval;
|
|
|
|
|
int masque = 0;
|
|
|
|
|
|
|
|
|
|
if (in == out)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "convolueur 2: out overwrite in.\n");
|
|
|
|
|
return IMG_OVERWRITE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (foo=Image_compare_desc(in, out)) )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Convolueur: images are differents %d\n", foo);
|
|
|
|
|
return foo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
|
|
|
Image_dump_descriptor(in, "image d'entree convolueur");
|
|
|
|
|
Image_dump_descriptor(out, "image de sortie convolueur");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL > 2
|
|
|
|
|
Image_filtre_display(stdout, mat);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (mat[9] == 0)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Convolueur: fuck, divisor is ZERO !\n");
|
|
|
|
|
/*
|
|
|
|
|
! c'est sur, avec un message comme c,a je vais pas
|
|
|
|
|
! pouvoir transmettre mon code aux australiens
|
|
|
|
|
! parfois, ils sont tres cons, les australiens :)
|
|
|
|
|
*/
|
|
|
|
|
return DIVISOR_IS_ZERO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* preparation of the binary mask from the parameter string
|
|
|
|
|
*/
|
|
|
|
|
for (foo=0; foo<(int)strlen(planes); foo++)
|
|
|
|
|
{
|
|
|
|
|
switch (planes[foo])
|
|
|
|
|
{
|
|
|
|
|
case 'r': case 'R':
|
|
|
|
|
masque |= 8;
|
|
|
|
|
break;
|
|
|
|
|
case 'g': case 'G':
|
|
|
|
|
masque |= 4;
|
|
|
|
|
break;
|
|
|
|
|
case 'b': case 'B':
|
|
|
|
|
masque |= 2;
|
|
|
|
|
break;
|
|
|
|
|
case 'a': case 'A':
|
|
|
|
|
masque |= 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
|
|
|
printf("masque convolueur = %02x\n", masque);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ( (masque & 1) && (in->Apix == NULL) )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Convolueur2: filtering NULL alpha plane is _bad_\n");
|
|
|
|
|
return WRONG_CHANNEL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (y=1; y<((in->height)-1); y++)
|
|
|
|
|
{
|
|
|
|
|
for (x=1; x<((in->width)-1); x++)
|
|
|
|
|
{
|
|
|
|
|
if (masque & 8)
|
|
|
|
|
{
|
|
|
|
|
lval = mat[0] * in->Rpix[y-1][x-1] +
|
|
|
|
|
mat[1] * in->Rpix[y-1][x] +
|
|
|
|
|
mat[2] * in->Rpix[y-1][x+1] +
|
|
|
|
|
mat[3] * in->Rpix[y] [x-1] +
|
|
|
|
|
mat[4] * in->Rpix[y] [x] +
|
|
|
|
|
mat[5] * in->Rpix[y] [x+1] +
|
|
|
|
|
mat[6] * in->Rpix[y+1][x-1] +
|
|
|
|
|
mat[7] * in->Rpix[y+1][x] +
|
|
|
|
|
mat[8] * in->Rpix[y+1][x+1] ;
|
|
|
|
|
|
|
|
|
|
lval = (lval / mat[9]) + mat[10];
|
|
|
|
|
if (lval > 255) lval = 255;
|
|
|
|
|
else if (lval < 0) lval = 0;
|
|
|
|
|
out->Rpix[y][x] = (uint8_t)lval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (masque & 4)
|
|
|
|
|
{
|
|
|
|
|
lval = mat[0] * in->Gpix[y-1][x-1] +
|
|
|
|
|
mat[1] * in->Gpix[y-1][x] +
|
|
|
|
|
mat[2] * in->Gpix[y-1][x+1] +
|
|
|
|
|
mat[3] * in->Gpix[y] [x-1] +
|
|
|
|
|
mat[4] * in->Gpix[y] [x] +
|
|
|
|
|
mat[5] * in->Gpix[y] [x+1] +
|
|
|
|
|
mat[6] * in->Gpix[y+1][x-1] +
|
|
|
|
|
mat[7] * in->Gpix[y+1][x] +
|
|
|
|
|
mat[8] * in->Gpix[y+1][x+1] ;
|
|
|
|
|
|
|
|
|
|
lval = (lval / mat[9]) + mat[10];
|
|
|
|
|
if (lval > 255) lval = 255;
|
|
|
|
|
else if (lval < 0) lval = 0;
|
|
|
|
|
out->Gpix[y][x] = (uint8_t)lval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (masque & 2)
|
|
|
|
|
{
|
|
|
|
|
lval = mat[0] * in->Bpix[y-1][x-1] +
|
|
|
|
|
mat[1] * in->Bpix[y-1][x] +
|
|
|
|
|
mat[2] * in->Bpix[y-1][x+1] +
|
|
|
|
|
mat[3] * in->Bpix[y] [x-1] +
|
|
|
|
|
mat[4] * in->Bpix[y] [x] +
|
|
|
|
|
mat[5] * in->Bpix[y] [x+1] +
|
|
|
|
|
mat[6] * in->Bpix[y+1][x-1] +
|
|
|
|
|
mat[7] * in->Bpix[y+1][x] +
|
|
|
|
|
mat[8] * in->Bpix[y+1][x+1] ;
|
|
|
|
|
|
|
|
|
|
lval = (lval / mat[9]) + mat[10];
|
|
|
|
|
if (lval > 255) lval = 255;
|
|
|
|
|
else if (lval < 0) lval = 0;
|
|
|
|
|
out->Bpix[y][x] = (uint8_t)lval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (masque & 1)
|
|
|
|
|
{
|
|
|
|
|
lval = mat[0] * in->Apix[y-1][x-1] +
|
|
|
|
|
mat[1] * in->Apix[y-1][x] +
|
|
|
|
|
mat[2] * in->Apix[y-1][x+1] +
|
|
|
|
|
mat[3] * in->Apix[y] [x-1] +
|
|
|
|
|
mat[4] * in->Apix[y] [x] +
|
|
|
|
|
mat[5] * in->Apix[y] [x+1] +
|
|
|
|
|
mat[6] * in->Apix[y+1][x-1] +
|
|
|
|
|
mat[7] * in->Apix[y+1][x] +
|
|
|
|
|
mat[8] * in->Apix[y+1][x+1] ;
|
|
|
|
|
|
|
|
|
|
lval = (lval / mat[9]) + mat[10];
|
|
|
|
|
if (lval > 255) lval = 255;
|
|
|
|
|
else if (lval < 0) lval = 0;
|
|
|
|
|
out->Apix[y][x] = (uint8_t)lval;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out->modified = 1;
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
int
|
|
|
|
|
Image_raz_sides(Image_Desc *im)
|
|
|
|
|
{
|
|
|
|
|
int foo;
|
|
|
|
|
|
|
|
|
|
for (foo=0; foo<im->width; foo++)
|
|
|
|
|
{
|
|
|
|
|
(im->Rpix[0])[foo] = 0;
|
|
|
|
|
(im->Gpix[0])[foo] = 0;
|
|
|
|
|
(im->Bpix[0])[foo] = 0;
|
|
|
|
|
(im->Rpix[im->height-1])[foo] = 0;
|
|
|
|
|
(im->Gpix[im->height-1])[foo] = 0;
|
|
|
|
|
(im->Bpix[im->height-1])[foo] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (foo=0; foo<im->height; foo++)
|
|
|
|
|
{
|
|
|
|
|
(im->Rpix[foo])[0] = 0;
|
|
|
|
|
(im->Gpix[foo])[0] = 0;
|
|
|
|
|
(im->Bpix[foo])[0] = 0;
|
|
|
|
|
(im->Rpix[foo])[im->width-1] = 0;
|
|
|
|
|
(im->Gpix[foo])[im->width-1] = 0;
|
|
|
|
|
(im->Bpix[foo])[im->width-1] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
im->modified = 1;
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
* Arf, le grand classique :)
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
Image_lissage_3x3(Image_Desc *in, Image_Desc *out)
|
|
|
|
|
{
|
|
|
|
|
int foo, x, y;
|
|
|
|
|
|
|
|
|
|
if (in == out)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Lissage 3x3: out overwrite in\n");
|
|
|
|
|
return IMG_OVERWRITE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (foo=Image_compare_desc(in, out)) )
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "Lissage 3x3: images have differents size, %d\n", foo);
|
|
|
|
|
return foo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (y=1; y<((in->height)-1); y++)
|
|
|
|
|
{
|
|
|
|
|
for (x=1; x<((in->width)-1); x++)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
foo = in->Rpix[y-1][x-1] + in->Rpix[y-1][x] + in->Rpix[y-1][x+1] +
|
|
|
|
|
in->Rpix[y] [x-1] + in->Rpix[y] [x] + in->Rpix[y] [x+1] +
|
|
|
|
|
in->Rpix[y+1][x-1] + in->Rpix[y+1][x] + in->Rpix[y+1][x+1] ;
|
|
|
|
|
out->Rpix[y][x] = (uint8_t)(foo / 9);
|
|
|
|
|
|
|
|
|
|
foo = in->Gpix[y-1][x-1] + in->Gpix[y-1][x] + in->Gpix[y-1][x+1] +
|
|
|
|
|
in->Gpix[y] [x-1] + in->Gpix[y] [x] + in->Gpix[y] [x+1] +
|
|
|
|
|
in->Gpix[y+1][x-1] + in->Gpix[y+1][x] + in->Gpix[y+1][x+1] ;
|
|
|
|
|
out->Gpix[y][x] = (uint8_t)(foo / 9);
|
|
|
|
|
|
|
|
|
|
foo = in->Bpix[y-1][x-1] + in->Bpix[y-1][x] + in->Bpix[y-1][x+1] +
|
|
|
|
|
in->Bpix[y] [x-1] + in->Bpix[y] [x] + in->Bpix[y] [x+1] +
|
|
|
|
|
in->Bpix[y+1][x-1] + in->Bpix[y+1][x] + in->Bpix[y+1][x+1] ;
|
|
|
|
|
out->Bpix[y][x] = (uint8_t)(foo / 9);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Image_raz_sides(out);
|
|
|
|
|
out->modified = 1;
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
* new 14 Jan 2000
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
Image_filtre_Prewitt(Image_Desc *src, Image_Desc *dst, int rotation)
|
|
|
|
|
{
|
|
|
|
|
static int Prewitt[] =
|
|
|
|
|
{
|
|
|
|
|
1, 1, 1,
|
|
|
|
|
0, 0, 0,
|
|
|
|
|
-1, -1, -1,
|
|
|
|
|
1, 128
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int filtre[11], foo;
|
|
|
|
|
|
|
|
|
|
memcpy(filtre, Prewitt, 11*sizeof(int));
|
|
|
|
|
|
|
|
|
|
for (foo=0; foo<rotation; foo++)
|
|
|
|
|
Image_rotate_filtre(filtre);
|
|
|
|
|
|
|
|
|
|
Image_convolueur_2(src, dst, filtre, "rgb");
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/*
|
|
|
|
|
* XXX cette fonction est incorrecte XXX
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
Image_filtre_Sobel(Image_Desc *src, Image_Desc *dst, int rotation)
|
|
|
|
|
{
|
|
|
|
|
static int Sobel[] =
|
|
|
|
|
{
|
|
|
|
|
1, 2, 1,
|
|
|
|
|
0, 0, 0,
|
|
|
|
|
-1, -2, -1,
|
|
|
|
|
1, 128
|
|
|
|
|
};
|
|
|
|
|
int filtre[11], foo;
|
|
|
|
|
|
|
|
|
|
memcpy(filtre, Sobel, 11*sizeof(int));
|
|
|
|
|
|
|
|
|
|
for (foo=0; foo<rotation; foo++)
|
|
|
|
|
Image_rotate_filtre(filtre);
|
|
|
|
|
|
|
|
|
|
Image_convolueur_2(src, dst, filtre, "rgb");
|
|
|
|
|
|
|
|
|
|
return OLL_KORRECT;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Voir aussi 'sobel4.c' */
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/* new 15 Jan 2000 */
|
|
|
|
|
int
|
|
|
|
|
Image_filtre_passe_bas(Image_Desc *src, Image_Desc *dst)
|
|
|
|
|
{
|
|
|
|
|
int foo;
|
|
|
|
|
|
|
|
|
|
static int PasseBas[] =
|
|
|
|
|
{
|
|
|
|
|
1, 2, 1,
|
|
|
|
|
2, 4, 2,
|
|
|
|
|
1, 2, 1,
|
|
|
|
|
16, 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
foo = Image_convolueur_2(src, dst, PasseBas, "rgb");
|
|
|
|
|
|
|
|
|
|
return foo;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/* nouveau: 18 Janvier 2001
|
|
|
|
|
moral <EFBFBD> z<EFBFBD>ro, il faut que je fasse p<EFBFBD>daler le 486 ! */
|
|
|
|
|
int
|
|
|
|
|
Image_filtre_random(Image_Desc *src, Image_Desc *dst, int p1, int p2)
|
|
|
|
|
{
|
|
|
|
|
int filtre[11];
|
|
|
|
|
int foo, somme, v, delta;
|
|
|
|
|
|
|
|
|
|
if (p1 == p2)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "%s: p1=%d must be different from p2=%d\n",
|
|
|
|
|
__func__, p1, p2);
|
|
|
|
|
return INVALID_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
somme = 0;
|
|
|
|
|
|
|
|
|
|
delta = abs(p2 - p1);
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
|
fprintf(stderr, "%s: delta is %d\n", __func__, delta);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
for (foo=0; foo<9; foo++)
|
|
|
|
|
{
|
|
|
|
|
v = (rand()%delta)+p1;
|
|
|
|
|
filtre[foo] = v;
|
|
|
|
|
somme += v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filtre[9] = somme;
|
|
|
|
|
filtre[10] = 0; /* XXX calcul automatique a faire ! */
|
|
|
|
|
|
|
|
|
|
Image_filtre_display(stdout, filtre);
|
|
|
|
|
|
|
|
|
|
foo = Image_convolueur_2(src, dst, filtre, "rgb");
|
|
|
|
|
fprintf(stderr, "retour convolueur = %d\n", foo);
|
|
|
|
|
|
|
|
|
|
return FUNC_IS_BETA;
|
|
|
|
|
/* et en plus, ce _truc_ n'a _aucune_ valeur scientifique... */
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
/* nouveau: 3 Fevrier 2001
|
|
|
|
|
on s'inspire de la precedente.
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
Image_filtre_random_2(Image_Desc *src, Image_Desc *dst,
|
|
|
|
|
int p1, int p2, int p3, int p4)
|
|
|
|
|
{
|
|
|
|
|
int filtre[11];
|
|
|
|
|
int foo, somme, v, delta, deltb;
|
|
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
|
fprintf(stderr, "Filtre Random 2: %d %d / %d %d\n", p1, p2, p3, p4);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
delta = abs(p2 - p1);
|
|
|
|
|
deltb = abs(p4 - p3);
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
|
fprintf(stderr, "Filtre Random 2: delta are %d %d\n", delta, deltb);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
somme = 0;
|
|
|
|
|
for (foo=0; foo<9; foo++)
|
|
|
|
|
{
|
|
|
|
|
if (foo != 4)
|
|
|
|
|
{
|
|
|
|
|
v = (rand()%delta)+p1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
v = (rand()%deltb)+p3;
|
|
|
|
|
}
|
|
|
|
|
filtre[foo] = v;
|
|
|
|
|
|
|
|
|
|
somme += v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filtre[9] = somme;
|
|
|
|
|
filtre[10] = 0; /* XXX calcul automatique a faire ! */
|
|
|
|
|
|
|
|
|
|
Image_filtre_display(stdout, filtre);
|
|
|
|
|
|
|
|
|
|
foo = Image_convolueur_2(src, dst, filtre, "rgb");
|
|
|
|
|
|
|
|
|
|
return FUNC_IS_BETA;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
int
|
|
|
|
|
Image_filtre_passe_haut(Image_Desc *src, Image_Desc *dst)
|
|
|
|
|
{
|
|
|
|
|
int foo;
|
|
|
|
|
static int PasseHaut[] =
|
|
|
|
|
{
|
|
|
|
|
-1, -1, -1,
|
|
|
|
|
-1, 8, -1,
|
|
|
|
|
-1, -1, -1,
|
|
|
|
|
1, 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
foo = Image_convolueur_2(src, dst, PasseHaut, "rgb");
|
|
|
|
|
|
|
|
|
|
return foo;
|
|
|
|
|
}
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|