# Autostereogram

Autostereogram is a cool sort of image that when viewed in a special way (with eyes crossed or "walled") enables the viewer to see a [3D](3d.md) structure within it by [cheating](cheating.md) human stereoscopic vision (it is therefore in a sense also an optical illusion). As the name suggests it is a special case of [stereogram](stereogram.md) but unlike many traditional stereograms consisting of two side by side images, autostereogram is only a single image that forms the perceivable 3D pattern by being overlaid with itself (hence the prefix *auto*). These images are quite awesome for they implement stereoscopic 3D images without the need for special glasses or complex techniques like [autostereoscopy](autostereoscopy.md) or [holography](holograph.md) -- autostereograms can be made as long as we can draw plain 2D images, but of course they also suffer from some limitations. There are several types of autostereograms.

Viewing autostereograms is easy for some and difficult for others but don't worry, it can be trained. One trick that's used (for the "cross eyed" types of images) is putting a finger in front of the image, focusing your sight on it and then lowering the finger while keeping your eyes looking at the point where the finger was (for "walled" images you have to be looking beyond the image, i.e. try looking at a wall behind it). Also be careful about the possibility of crossing your eyes "too much" and seeing the image in incorrect way. Once you see the pattern, keep looking at it for a longer time, it becomes clearer and clear as the brain makes out more of the structure (it may also help to slightly move your head from side to side).

TODO

## Random Dot Autostereograms

The "random dot" technique gives rise to an especially [interesting](interesting.md) type of autostereogram -- one whose creation can easily be automated with a program and which lets us embed any depth image (or *[heightmap](heightmap.md)*) into an image that consists of some repeating base pattern. And yes, it can even be animated! The pattern image may in theory be anything, even a photo, but it should have great variety, high frequencies and big contrast to work properly, so the typical pattern is just randomly generated color dots. This pattern is then horizontally deformed according to the embedded depth image. A disadvantage is, of course, that we can only embed the depth image, we cannot give it any texture.

TODO: more detail

```
 .:,oX#r-'/=*miQ .:,oX#r-'/=*miQ .:,oX#r-'/=*miQ .:,oX#r-'/=*miQ .:,oX#r-'/=*miQ .:,oX#r-'/=*miQ
miQ)35;_0p]w@x4EmiQ)35;_0p]w@x4EmiQ)35;_0p]w@x4EmiQ)35;_0p]w@x4EmiQ)35;_0p]w@x4EmiQ)35;_0p]w@x4E
x4EY!{ .:,oX#r-'x4EY!{ .:,oX#r-'x4EY!{ .:,oX#r-'x4EY!{ .:,oX#r-'x4EY!{ .:,oX#r-'x4EY!{ .:,oX#r-'
r-'/=*miQ)35;_0pr'/=*miQ)35;_00pr'/=*miQ)35;_00pr'/=*miQ)35;_00pr'/=*miQ)35;_00pr'/=*miQ)35;_00p
_0p]w@x4EY!{ .:,_0]w@x4EY!{ ..:,_0]w@x4EY!..:,_0]w@x4EY!..:.:,_0]w@x4EY!..:.:,_0]w@x4EY!..:.:,_0
.:,oX#r-'/=*miQ).:,o#r-'/=**miQ).:,o#r-'/=*iQ).:,o#r-'/=*iQ).).:,o#r-'/=*iQ.).:,o#r-''/=*iQ).).:
iQ)35;_0p]w@x4EYiQ)3;_0p]w@@x4EYiQ)3;_0p]w@@EYiQ)3;3;_0w@@EYiQiQ)3;3;_0w@EYiQiQ)3;3;_0w@@EYYiQiQ
4EY!{ .:,oX#r-'/4EY! .:,oX##r-'/4EY! .:,oX##'/4EY! ! .:,##'/4E4EY! ! .,##'/4E44EY!  .,##''//4E4E
-'/=*miQ)35;_0p]-'/=miQ)35;;_0p]-'/=miQ)35;;p]-'/=m=miQ);;p]-'-'/=m=mi);;p]-''-'/=m=i);;p]]]-'-'
0p]w@x4EY!{ .:,o0p]wx4EY!{  .:,o0p]wx4EY!{  ,o0p]wxwx4!{  ,o0o0p]wxwx4{  ,o0o00p]wxwx4{  ,oo0o0p
:,oX#r-'/=*miQ)3:,oXr-'/=*mmiQ)3:,oXr-'/=*mm)3:,oXr-'/=*mm)3)3:,oXr-'/=*m)3)3:,oXr-''/=*m)33)3:,
Q)35;_0p]w@x4EY!Q)35_0p]w@xx4EY!Q)350pp]w@xxY!Q)350pp]w@xxY!Y!Q)350pp]w@xxY!!Q)350pp]w@xxxY!Y!Q)
EY!{ .:,oX#r-'/=EY!{.:,oX#rr-'/=EY!{:,,oX#rr/=EY!{:{:,,#rr/=E=EY!{:{:,,#rr/=E=EY{:{:,,#rrr/=E=EY
'/=*miQ)35;_0p]w'/=*iQ)35;__0p]w'/*iQ))35;__]w'/*iQiQ))3__]w'/'/*iQi))3__]ww'/'/*ii))3__]www'/'/
p]w@x4EY!{ .:,oXp]wx4EY!{ .:,oXp]wx4EYY!{ .:Xpp]x4E4EYY!{:Xpp]]]x4E4YY!{:Xppp]]]x4EYY!{:Xpppp]]]
,oX#r-'/=*miQ)35,o#r-'/=*miQ)35,o#r-'//=*miQ5,,or-'/'//=*Q5,,oo#r-'/'/=*Q5,,ooo#r-/'/=*Q5,,,,oo#
)35;_0p]w@x4EY!{)35;_0p]w@x4EY!{)35;_0p]w@xY!{)35;_0p0p]wY!{)3)3_;_0p0]wY!{)3)35;_0p0]wY!!{{)3)3
Y!{ .:,oX#r-'/=*Y!{ .:,oX#r-'/=*Y!{ .:,oX#r-'/=*Y!{ .:,oX#r-'/=*Y!{ .:,oXr-'/=*Y!{ .:,,oXr--'/=*
/=*miQ)35;_0p]w@/=*miQ)35;_0p]w@/=*miQ)35;_0p]w@/=*miQ)35;_0p]w@/=*miQ)35;_0p]w@/=*miQ)35;_0p]w@
]w@x4EY!{ .:,oX#]w@x4EY!{ .:,oX#]w@x4EY!{ .:,oX#]w@x4EY!{ .:,oX#]w@x4EY!{ .:,oX#]w@x4EY!{ .:,oX#
```

*If you look at this image the correct way, you'll see a 3D image of big letters spelling out LRS. Please forgive an increased viewing difficulty of [ASCII art](ascii_art.md) as compared to a true bitmap image.*

The following is a [C](c.md) program that generates the above image.

```
#include <stdio.h>

#define PATTERN_SIZE 16
#define RES_X 75
#define RES_Y 20
#define PATTERN_SEED_SIZE 32

char patternSeed[PATTERN_SEED_SIZE] = " .:,oX#r-'/=*miQ)35;_0p]w@x4EY!{";

char depth[RES_X * RES_Y + 1] = // must be big and simple to be easily seen
  "                                                                           "
  "                                                                           "
  "                                                                           "
  " 1111111111111                                                             "
  "  11111111111             22222222222222222                                "
  "    1111111                222222222222222222              1111111111      "
  "    1111111                 2222222    2222222          1111111111111111   "
  "    1111111                 2222222     222222        11111111     111111  "
  "    1111111                 2222222     222222        1111111       111111 "
  "    1111111                 2222222   2222222         11111111             "
  "    1111111                 2222222222222222            111111111111       "
  "    1111111         11      2222222222222222                111111111111   "
  "    1111111         11      2222222    222222                   111111111  "
  "    1111111       1111      2222222     222222      1111111       11111111 "
  "   1111111111111111111      2222222      222222     1111111        1111111 "
  "  11111111111111111111      22222222     2222222     11111111     11111111 "
  "                           2222222222    22222222     1111111111111111111  "
  "                                                         1111111111111     "
  "                                                                           "
  "                                                                           ";

char buffer1[PATTERN_SIZE + 1];
char buffer2[PATTERN_SIZE + 1];

int charToDepth(char c)
{
  return c == ' ' ? 0 : (c - '0');
}

int main(void)
{
  const char *c = depth;
  char *lineCurrent, *linePrev;

  buffer1[PATTERN_SIZE] = 0;
  buffer2[PATTERN_SIZE] = 0;
 
  for (int j = 0; j < RES_Y; ++j)
  {
    for (int i = 0; i < PATTERN_SIZE; ++i) // initiate first pattern from seed
      buffer1[i] =  patternSeed[(i + (j * 13)) % PATTERN_SEED_SIZE];

    lineCurrent = buffer1;
    linePrev = buffer2;

    for (int i = 0; i < RES_X; ++i)
    {
      if (i % PATTERN_SIZE == 0)
      {
        printf("%s",lineCurrent); // print the rendered line

        char *tmp = lineCurrent;  // swap previous and current buffer
        lineCurrent = linePrev;
        linePrev = tmp; 
      }

     lineCurrent[i % PATTERN_SIZE] = // draw the offset pixel
       linePrev[(PATTERN_SIZE + i + charToDepth(*c)) % PATTERN_SIZE];

      c++;
    }

    printf("%s\n",lineCurrent); // print also the last buffer
  }

  return 0;
}
```
