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



Copyright © Jean-François Colonna, 2021-2023.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / École polytechnique, Institut Polytechnique de Paris, 2021-2023.