/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        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);
          }



Copyright (c) Jean-François Colonna, 1995-2014.
Copyright (c) France Telecom R&D and CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / Ecole Polytechnique, 1995-2014.