/*************************************************************************************************************************************/ /* */ /* 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 : */ /* */ /* */ /* 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.01$c' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 1994MMJJhhmmss). */ /* */ /*************************************************************************************************************************************/ #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(nom) \ unsigned char *nom=malloc(dimX*dimY*sizeof(unsigned char)) \ /* Definition of a picture as a matrix. */ #define Rpicture(nom) \ unsigned char *nom \ /* Reference a picture. */ #define IMAGE(image,x,y) \ (*(image + ((((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. */ #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(AutostereogramGeneration(Autostereogram,Depth,MultiplicativeFactor,Texture,IntrinsicPeriod,ActualPeriod,TextureSwap)) Rpicture(Autostereogram); /* The autostereogram to be generated. */ Rpicture(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(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(TemporaryTexture); /* A temporary picture containing the texture during the */ /* process of circular shifting of Texture. */ int X,Y; for (Y=Ymin ; Y<=Ymax ; Y++) { for (X=Xmin ; X<=Xmax ; X++) { IMAGE(TemporaryTexture,X,Y) = IMAGE(Texture,X,Y); /* Copy the whole input texture (could be optimized according */ /* to IntrinsicPeriod and ActualPeriod). */ } } for (Y=Ymin ; Y<=Ymax ; Y++) { int FormerLeftshift=0; for (X=Xmin ; X<=Xmax ; X++) { int Leftshift=MultiplicativeFactor*IMAGE(Depth,X,Y); int 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(TemporaryTexture,Xmodulo(Xperiodic,ActualPeriod),Y) = IMAGE(TemporaryTexture,Xmodulo(Xperiodic+ActualLeftshift,ActualPeriod),Y); /* shift the current texture according to the current depth. */ } IMAGE(Autostereogram,X,Y) = IMAGE(TemporaryTexture,Xmodulo(X,ActualPeriod),Y); /* Generation of Autostereogram. */ FormerLeftshift = ActualLeftshift; } } return(Autostereogram); } /*************************************************************************************************************************************/ /* */ /* T E X T U R E G E N E R A T I O N F R O M A N O B J E C T V I E W : */ /* */ /*************************************************************************************************************************************/ void TextureGenerationFromView(Depth,Texture,DepthOfRealisticView,RealisticView) Rpicture(Depth); Rpicture(Texture); /* Depth field and 2D texture to be used to produce the */ /* autostereogram. */ Rpicture(DepthOfRealisticView); Rpicture(RealisticView); /* The "realistic" view of the object(s) to be displayed. */ { int X,Y; for (Y=Ymin ; Y<=Ymax ; Y++) { for (X=Xmin ; X<=Xmax ; X++) { IMAGE(Depth,X,Y) = ((X>=(Xmin+((Xmax-Xmin)/3))) && (X<(Xmin+((2*(Xmax-Xmin))/3)))) ? IMAGE(DepthOfRealisticView,X,Y) : 0; /* The depth field is extracted from the center of the realistic */ /* view and remains center aligned. The left and right bands */ /* are initialized to zero thus giving birth to a background */ /* plane. */ IMAGE(Texture,X,Y) = (X<(Xmin+((Xmax-Xmin)/3))) ? IMAGE(RealisticView,X+((Xmax-Xmin)/3),Y) : 0; /* The 2D texture is extracted from the center of the realistic */ /* view and is left aligned. */ } } } /*************************************************************************************************************************************/ /* */ /* 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) \ ((unsigned char)(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(Autostereogram); /* The autostereogram to be generated. */ Dpicture(RealisticView); Dpicture(DepthOfRealisticView); int DepthChoice; Dpicture(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(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=0; /* 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 20110605092911). */ 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; } } if (0) /* Test sequence for the function 'TextureGenerationFromView(...)', not needed here... */ { IMAGE(RealisticView,X,Y) = IMAGE(Depth,X,Y); IMAGE(DepthOfRealisticView,X,Y) = IMAGE(Depth,X,Y); } else { } } } MultiplicativeFactor = 0.24; IntrinsicPeriod = 0.2; ActualPeriod = 0.2; TextureSwap = 1; AutostereogramGeneration(Autostereogram ,Depth,MultiplicativeFactor ,Texture,IntrinsicPeriod,ActualPeriod,TextureSwap ); /* Computation of the random autostereogram. */ if (0) /* Test sequence for the function 'TextureGenerationFromView(...)', not needed here... */ { TextureGenerationFromView(Depth,Texture,DepthOfRealisticView,RealisticView); AutostereogramGeneration(Autostereogram ,Depth,MultiplicativeFactor ,Texture,IntrinsicPeriod,ActualPeriod,TextureSwap ); } else { } write(1,Autostereogram,dimX*dimY); /* Acces to the generated autostereogram is given on 'Stdout'. */ } return(0); }