You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
7.5 KiB
Markdown

2 months ago
# Autostereogram
2 months ago
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.
2 months ago
2 months ago
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).
2 months ago
TODO
2 months ago
## Random Dot Autostereograms
The "random dot" technique gives rise to an especially [interesting](interesting.md) type of autostereogram -- one whose creation can easily be automatized 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
2 months ago
```
.:,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#
```
2 months ago
*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.*
2 months ago
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;
}
```