/*************************************************************************************************************************************/ /* */ /* T O O L S F O R A U T O S T E R E O G R A M G E N E R A T I O N */ /* W I T H F L O A T I N G P O I N T D E P T H F I E L D : */ /* */ /* */ /* Example of an alpha-numeric autostereogram : */ /* */ /* */ /* O-oo::o:-o%o:o:-O-oo::o:-o%o:o:-O-oo::o:-o%o:o:-O-oo::o:-o%o:o:- */ /* -oo::O:.-::oOoo:-oo::O:.-::oOoo:-oo::O:.-::oOoo:-oo::O:.-::oOoo: */ /* :o:-OoO.-:OOo:o::o:-OoO.-:OOo:o::o:-OoO.-:OOo:o::o:-OoO.-:OOo:o: */ /* :o::::-OOOO-:oOo:o::::-OOOO-:oOo-o::::-OOOO-:oOo-o::::-OOOO-:oOo */ /* ::-o-o.o:oO:-oo-::-o-o.ooOo-oo-::-:::-::oOo-oo-::-:::-::oOo-oo-: */ /* :o-::oo::.:oo:Oo:o-::oo:.oooOo:o-::oo:.-ooo-%o:o-::oo:.-ooo-%o:o */ /* ::o-:O:o.o:ooooo::::O::o:o-oOo:--:%o-Ooo-ooO::::-:%o-Ooo-ooO:::: */ /* O-o-oOOoOOo:o:--oo-OOOOoooo:o:-oo-OO%O:oo::o-O-o-:OO%O:oo::o-O-o */ /* -o:-:o::oOo-::O-o::o:::OOo:-::O-o::o::oOo-::::o:-:o:::oOo-::::o: */ /* o-:-oO-o:ooo:o:-::oO::o::ooo:o:-::oO::o::oo::-:OoOOo-:o::oo::-:O */ /* :o-:::%::O:O-O:oo::::O%::O:O-O:oo::::O%::O:o%:.:::::o%%::O:o%:.: */ /* :-:::-oo::%-:-:-:o:::-oo::%-:-:-:o:::-oo::%-:--o:::--ooo::%-:--o */ /* :-o::Ooooo-:-%O-:OO-:Ooooo-:-%O-:OO-:Ooooo-:-O::O-oooooooo-:-O:: */ /* :::ooooOoOoo::o::-oooooOoOoo::o::-oooooOoOoo::o::o:OOoo%oOoo::o: */ /* o:oooo:::Ooo:-oo::oooo:::Ooo:-oo::oooo:::Ooo:-o:::o::::::Ooo:-o: */ /* :o::o::oO-:-.:::o:::o::oO-:-.:::o:::o::oO-:-.::o::o:::o:O-:-.::o */ /* o-oo:O::-oOoO-o:-ooo:O::-oOoO-o:-ooo:O::-oOoO-o-oo-Oo::--oOoO-o- */ /* o-o::oo:oo-::::-:oO::oo:oo-::::-:oO::oo:oo-:::::oo:OOoo:oo-::::: */ /* -o::-o:O-O-:oo-o::-:-o:O-O-:oo-o::-:-o:O-O-:ooo:-:-oo:oO-O-:ooo: */ /* O:Ooo:o:ooo:OoO:OOooo:o:ooo:OoO:OOooo:o:ooo:oo:%ooo::O::ooo:oo:% */ /* o:oO-o:oo::%Ooo:oO:-o::oo::%Ooo:oO:-o::oo:::ooOO--oo:::oo:::ooOO */ /* ::O:o-o:o::oO:-:o:o:-Oo:o::oO:-:o:o:-Oo:o:oO%:%oo:--:Oo:o:oO%:%o */ /* O.-:ooOOoo:ooo%O.:ooOO:ooo-Ooo%O.:oo%Oooo:oooo.-:ooO%Oooo:oooo.- */ /* O.o::-O:oo:o::o--o:.O:oo:o:o:O--o:.Ooo:o:o:O-O.o:o.Ooo:o:o:O-O.o */ /* oOO:-oo::oo%oo-:ooo-oo-ooOO:-o:oo-Oo:OooO:--ooOoo-Oo:OooO:--ooOo */ /* ooo:oO:Ooo:oo%o:ooo:o:OooO:#o:ooO:ooOoo-O:%%o:ooO:ooOoo-O:%%o:oo */ /* oo:ooo-o%-:%o:o:oo:ooo-OO-%ooo-oo:Oo:::%:-%ooo-oo:Oo:::%:-%ooo-o */ /* O:O:o:o:%::Oo:oOO:O:o:o:%::Oo:oOO:O:o:o:%::Oo:oOO:O:o:o:%::Oo:oO */ /* Oo:o:o:-Oo::oo-oOo:o:o:-Oo::oo-oOo:o:o:-Oo::oo-oOo:o:o:-Oo::oo-o */ /* ::::o::::o:ooO-O::::o::::o:ooO-O::::o::::o:ooO-O::::o::::o:ooO-O */ /* :o:-o::o-::::%Oo:o:-o::o-::::%Oo:o:-o::o-::::%Oo:o:-o::o-::::%Oo */ /* :o::::OO%-o::::.:o::::OO%-o::::.:o::::OO%-o::::.:o::::OO%-o::::. */ /* */ /* */ /* Author of '$xtc/stereogra.02$c' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 20110604100914). */ /* */ /*************************************************************************************************************************************/ #include <stdio.h> extern void *malloc(); extern int atoi(); extern char *getenv(); #define Get(valeur_de_la_variable,nom_de_la_variable) \ { \ valeur_de_la_variable = atoi(getenv(nom_de_la_variable)); \ } \ /* Get an environment variable. */ static int dimX=0; #define Xmin 0 #define Xmax (Xmin + (dimX-1)) /* Definition of the 'OX' axis. */ static int dimY=0; #define Ymin 0 #define Ymax (Ymin + (dimY-1)) /* Definition of the 'OY' axis. */ #define Dpicture(type,nom) \ type *nom=malloc(dimX*dimY*sizeof(type)) \ /* Definition of a picture as a matrix. */ #define Rpicture(type,nom) \ type *nom \ /* Reference a picture. */ #define IMAGE(image,x,y) \ (*(image + (int)((((y)-Ymin)*dimX) + ((x)-Xmin)))) \ /* Point access. */ #define COXR(x) \ ((int)((x) - Xmin)) \ /* Relative value of an 'X' coordinate. */ #define COXA(x) \ ((int)((x) + Xmin)) \ /* "Absolute" value of an 'X' coordinate. */ #define X_SCREEN(x) \ COXA((int)((double)(x)*((double)dimX))) \ /* Put a [0,1] value into X-screen coordinate system. */ #define X_01(x) \ ((double)COXR(x)/(double)(dimX)) \ /* Put a [0,1] value into X-screen coordinate system. */ #define COYR(y) \ ((int)((y) - Ymin)) \ /* Relative value of an 'Y' coordinate. */ #define COYA(y) \ ((int)((y) + Ymin)) \ /* "Absolute" value of an 'Y' coordinate. */ #define Y_SCREEN(y) \ COYA((int)((double)(y)*((double)dimY))) \ /* Put a [0,1] value into Y-screen coordinate system. */ #define Y_01(y) \ ((double)COYR(y)/(double)(dimY)) \ /* Put a [0,1] value into Y-screen coordinate system. */ #define LENG(origine,extremite) \ ((int)((extremite)-(origine)+1)) \ /* Compute a length. */ #define MODS(x,origine,extremite) \ (((x) < (origine)) ? \ ((x)-(((((x)+1-(origine))/LENG(origine,extremite))-1)*LENG(origine,extremite))) : \ (((x) > (origine)) ? \ ((x)-((((x)-(origine))/LENG(origine,extremite))*LENG(origine,extremite))) : \ (x) \ ) \ ) \ /* Modulo. */ extern double atan2(); extern double sin(); extern double cos(); #define CERCLE_TRIGONOMETRIQUE \ 6.283185307179586 #define COND(condition,valeur_si_VRAI,valeur_si_FAUX) \ ((condition) ? (valeur_si_VRAI) : (valeur_si_FAUX)) #define IFNE(x,a) \ ((x) != (a)) #define IFGE(x,a) \ ((x) >= (a)) #define IZNE(x) \ IFNE(x,0) #define IZGE(x) \ IFGE(x,0) #define ADD2(a,b) \ ((a) + (b)) #define SOUS(a,b) \ ((a) - (b)) #define MUL2(a,b) \ ((a) * (b)) #define DIVI(a,b) \ ((a) / (b)) #define gSCAZ(x,ancien_intervalle,nouvel_intervalle,exception,conversion) \ COND(IZNE(ancien_intervalle) \ ,MUL2(DIVI(conversion(x) \ ,conversion(ancien_intervalle) \ ) \ ,conversion(nouvel_intervalle) \ ) \ ,exception \ ) #define SCAZ(x,ancien_intervalle,nouvel_intervalle,exception) \ gSCAZ(x,ancien_intervalle,nouvel_intervalle,exception,(double)) #define SCAL(x,ancien_intervalle,nouvel_intervalle) \ SCAZ(x,ancien_intervalle,nouvel_intervalle,x) #define HOMO(x,origine1,extremite1,origine2,extremite2) \ ADD2(SCAL(SOUS(x,origine1),SOUS(extremite1,origine1),SOUS(extremite2,origine2)),origine2) #define ATAN(y,x) \ COND(IZGE(atan2(y,x)),atan2(y,x),ADD2(CERCLE_TRIGONOMETRIQUE,atan2(y,x))) #define CERC(x) \ ATAN(sin(x),cos(x)) #define MODF(x,origine,extremite) \ HOMO(CERC(HOMO(x \ ,origine,extremite \ ,0,CERCLE_TRIGONOMETRIQUE \ ) \ ) \ ,0,CERCLE_TRIGONOMETRIQUE \ ,origine,extremite \ ) /* Procedures utiles a 'fXmodulo(...)'. */ #define fXmodulo(x,period) \ MODF(x,0,period*(double)(dimX)) #define Xmodulo(x,period) \ COXA(MODS(COXR(x),COXR(Xmin),X_SCREEN(period))) /* Put 'x' inside [Xmin,Xmin+period-1]. */ /*************************************************************************************************************************************/ /* */ /* A U T O S T E R E O G R A M G E N E R A T I O N : */ /* */ /*************************************************************************************************************************************/ Rpicture(unsigned char ,AutostereogramGeneration(Autostereogram,Depth,MultiplicativeFactor,Texture,IntrinsicPeriod,ActualPeriod,TextureSwap) ) Rpicture(unsigned char,Autostereogram); /* The autostereogram to be generated. */ Rpicture(double,Depth); double MultiplicativeFactor; /* The depth field of the scene to be displayed is defined itself as a picture ; high */ /* values correspond to points that are close to the viewer. */ Rpicture(unsigned char,Texture); double IntrinsicPeriod; double ActualPeriod; /* The 2D texture to be used. Two periods are characteristic : */ /* */ /* 1-IntrinsicPeriod gives the intrinsic period of Texture ; for example, if Autostereogram */ /* should be made of 5 vertical bands, it is equal to 0.2 (=1/5). */ /* */ /* 2-ActualPeriod generally equals IntrinsicPeriod but it could be different in the case */ /* where texture is pseudo-periodical. It gives the width of the used area of Texture. */ int TextureSwap; /* A logical indicator ; a null value allows the possible swap of texture points during */ /* the left shift process. This allows "dynamical" effects and for example "ghost" subsets */ /* of the 3D object that appear and disappear according to the point of view. */ { Dpicture(double,Xshifted); /* A temporary picture to simulate the process of circular shifting of Texture. */ int X,Y; for (Y=Ymin ; Y<=Ymax ; Y++) { for (X=Xmin ; X<=Xmax ; X++) { IMAGE(Xshifted,X,Y) = Xmodulo(X,ActualPeriod); } } for (Y=Ymin ; Y<=Ymax ; Y++) { int FormerLeftshift=0; for (X=Xmin ; X<=Xmax ; X++) { double Leftshift=MultiplicativeFactor*IMAGE(Depth,X,Y); double ActualLeftshift=((TextureSwap==0)||((FormerLeftshift-Leftshift)<=1)) ? Leftshift : FormerLeftshift-1; /* Texture will be left circular shifted proportionally to the */ /* current Depth ; however, the actual left shift depends on */ /* the swapping enabling of the texture. */ int n; for (n=1 ; n<=(ActualPeriod/IntrinsicPeriod) ; n++) /* For the sake of simplicity it is assumed that IntrinsicPeriod */ /* divides exactly ActualPeriod. */ { int Xperiodic=Xmodulo(X+(n-1)*X_SCREEN(IntrinsicPeriod),ActualPeriod); IMAGE(Xshifted,Xmodulo(Xperiodic,ActualPeriod),Y) = IMAGE(Xshifted,Xmodulo(Xperiodic+ActualLeftshift,ActualPeriod),Y); /* shift the current texture according to the current depth. */ } IMAGE(Autostereogram,X,Y) = IMAGE(Texture,IMAGE(Xshifted,Xmodulo(X,ActualPeriod),Y),Y); /* Generation of Autostereogram. */ FormerLeftshift = ActualLeftshift; } } return(Autostereogram); } /*************************************************************************************************************************************/ /* */ /* M A I N T E S T P R O G R A M : */ /* */ /*************************************************************************************************************************************/ extern double exp(); extern double sin(); extern double drand48(); #define BLACK 0 #define WHITE 255 #define GreyLevel(n) \ (BLACK + ((n)*(WHITE-BLACK))) \ /* Convert a [-1,+1] value into a grey level. */ int main() { Get(dimX,"dimX"); Get(dimY,"dimY"); /* Get the definition of the picture size : */ /* */ /* setenv dimX ... */ /* setenv dimY ... */ /* */ { Dpicture(unsigned char,Autostereogram); /* The autostereogram to be generated. */ Dpicture(unsigned char,RealisticView); Dpicture(double,DepthOfRealisticView); int DepthChoice; Dpicture(double,Depth); double MultiplicativeFactor; /* The depth field of the scene to be displayed is defined itself as a picture ; high */ /* values correspond to points that are close to the viewer. */ int TextureChoice; Dpicture(unsigned char,Texture); double IntrinsicPeriod; double ActualPeriod; /* The 2D texture to be used. Two periods are characteristic : */ /* */ /* 1-IntrinsicPeriod gives the intrinsic period of Texture ; for example, if Autostereogram */ /* should be made of 5 vertical bands, it is equal to 0.2 (=1/5). */ /* */ /* 2-ActualPeriod generally equals IntrinsicPeriod but it could be different in the case */ /* where texture is pseudo-periodical. It gives the width of the used area of Texture. */ int TextureSwap; /* A logical indicator ; a null value allows the possible swap of texture points during */ /* the left shift process. This allows "dynamical" effects and for example "ghost" subsets */ /* subsets of the 3D object that appear and disappear according to the point of view. */ DepthChoice=1; /* Definition : */ /* */ /* 0 : sinusoidal, */ /* 1 : gaussian. */ /* */ TextureChoice=1; /* Definition : */ /* */ /* 0 : random, */ /* 1 : vertical lines, */ /* 2 : color bars. */ /* */ int X,Y; for (Y=Ymin ; Y<=Ymax ; Y++) { for (X=Xmin ; X<=Xmax ; X++) { switch (TextureChoice) { case 0: { IMAGE(Texture,X,Y) = GreyLevel(drand48()); /* Computation of a random texture... */ break; } case 1: { IMAGE(Texture,X,Y) = GreyLevel(((X%(dimX/10))<=((dimX/100)-1)) ? 1 : 0); /* Computation of vertical lines (introduced on 20110603132430). */ break; } case 2: { IMAGE(Texture,X,Y) = MODS((X*((dimX/100)-1)),BLACK,WHITE); /* Computation of vertical color bars (introduced on 20110605093327). */ break; } default: { IMAGE(Texture,X,Y) = GreyLevel(0); break; } } switch (DepthChoice) { case 0: { IMAGE(Depth,X,Y) = GreyLevel((1+sin(4*3.1415*X_01(X)))/2); /* Computation of a sinusoidal depth field. */ break; } case 1: { IMAGE(Depth,X,Y) = GreyLevel(exp(-10*(((X_01(X)-0.5)*(X_01(X)-0.5))+ ((Y_01(Y)-0.5)*(Y_01(Y)-0.5)) ) ) ); /* Computation of a gaussian depth field (introduced on 20110603132430). */ break; } default: { IMAGE(Depth,X,Y) = GreyLevel(0); break; } } } } MultiplicativeFactor = 0.24; IntrinsicPeriod = 0.2; ActualPeriod = 0.2; TextureSwap = 1; AutostereogramGeneration(Autostereogram ,Depth,MultiplicativeFactor ,Texture,IntrinsicPeriod,ActualPeriod,TextureSwap ); /* Computation of the random autostereogram. */ write(1,Autostereogram,dimX*dimY); /* Acces to the generated autostereogram is given on 'Stdout'. */ } return(0); }