Magic Eyes (Autostereogram)

Here’s a program I wrote probably 25 years ago. I thought I’d dig it up and see if anyone remembers magic eyes. Probably the youngsters don’t know what I’m talking about. It takes a few seconds for the image to show. If you don’t know how to view what’s in the image, do a search on autostereograms and look at Wikipedia.


supportedOrientations(LANDSCAPE_ANY)

function setup()
    img=image(WIDTH,HEIGHT)    
    tab={
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000011111111111111111000000000000000000000000000000000",
    "00000000000000000000000000000000000012222222222222221000000000000000000000000000000000",
    "00000000000000000000000000000000000012333333333333321000000000000000000000000000000000",
    "00000000000000000000000000000000000012344444444444321000000000000000000000000000000000",
    "00000000000000000000000000000000000012345555555554321000000000000000000000000000000000",
    "00000000000000000000000000000000000012345666666654321000000000000000000000000000000000",
    "00000000000000000000000000000000000012345677777654321000000000000000000000000000000000",
    "00000000000000000000000000000000000012345678887654321000000000000011111000000000000000",
    "00000000000033333333300000000000000012345678987654321000000000000011111000000000000000",
    "00000000000033333333300000000000000012345678887654321000000000000022222000000000000000",
    "00000000000033333333300000000000000012345677777654321000000000000022222000000000000000",
    "00000000000000000000000000000000000012345666666654321000000000000033333000000000000000",
    "00000000000000000000000000000000000012345555555554321000000000000033333000000000000000",
    "00000000000000000000000000000000000012344444444444321000000000000044444000000000000000",
    "00000000000055555555500000000000000012333333333333321000000000000044444000000000000000",
    "00000000000055555555500000000000000012222222222222221000000000005555555550000000000000",
    "00000000000055555555500000000000000011111111111111111000000000005555555550000000000000",
    "00000000000000000000000000000000000000000000000000000000000000005555555550000000000000",
    "00000000000000000000000000000000000000000000000000000000000000005555555550000000000000",
    "00000000000000000000000000000000000000000000000000000000000000005555555550000000000000",
    "00000000000077777777700000000000000000000000000000000000000000005555555550000000000000",
    "00000000000077777777700000000000000011111111111111111000000000005555555550000000000000",
    "00000000000077777777700000000000000012222222222222221000000000005555555550000000000000",
    "00000000000000000000000000000000000012333333333333321000000000005555555550000000000000",
    "00000000000000000000000000000000000012344444444444321000000000000000000000000000000000",
    "00000000000000000000000000000000000012345555555554321000000000000000000000000000000000",
    "00000000000099999999900000000000000012345666666654321000000000000000000000000000000000",
    "00000000000099999999900000000000000012345677777654321000000000000000000000000000000000",
    "00000000000099999999900000000000000012345678887654321000000000000000000000000000000000",
    "00000000000099999999900000000000000012345678987654321000000000000000000000000000000000",
    "00000000000099999999900000000000000012345678887654321000000000000000000000000000000000",
    "00000000000000000000000000000000000012345677777654321000000000000000000000000000000000",
    "00000000000000000000000000000000000012345666666654321000000000000000000000000000000000",
    "00000000000000000000000000000000000012345555555554321000000000000000000000000000000000",
    "00000000000000000000000000000000000012344444444444321000000000000000000000000000000000",
    "00000000000000000000000000000000000012333333333333321000000000000000000000000000000000",
    "00000000000000000000000000000000000012222222222222221000000000000000000000000000000000",
    "00000000000000000000000000000000000011111111111111111000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    }
    
    setContext(img)
    for x=1,600 do
        for y=1,400 do
            p=math.floor(x/100)
            b1=level(x,y)*2
            if p==0 then
                r=math.random(240)
                g=r
                b=r
            else
                r,g,b=img:get(x-100+b1+1,y)
            end
            img:set(x,y,r,g,b,255)
        end
    end
    setContext()
end

function draw()
    background(40, 40, 50)
    sprite(img,WIDTH/2+100,HEIGHT/2+100)
end

function level(x,y)
    if x>150 and y>50 then
        xo=math.ceil((x-150)/5)
        yo=math.ceil((y-50)/5)
        if xo>85 or yo>59 then 
            return(0) 
        end
        return(string.sub(tab[yo],xo,xo))
    end
    return(0)
end

:open_mouth: how many zeros . but is great

I can see it in 3D, not quite sure what I’m looking at, though.

@SkyTheCoder If you view it correctly, you should be looking at 2 pyramids from above. On the left of the pyramids should be some rectangles at different levels like steps. On the right is a square with some steps going down. Not everyone can see the 3D images in these.

@dave1707 now that is really cool! You should make a generator for these :stuck_out_tongue:

@Briarfox This was an old program I had, thought I would share it. The hard part was creating the table with the Codea editor. The editor I used 25 years ago allowed me to copy/paste chunks of data and to do search/replace. So changing the table to create images was easy. I’ll have to think if there’s an easy way to create the table or to create the images without using a table. Maybe I can use an image and read that.

@dave1707 - I found a good page on this, where someone has done a sophisticated job of it and posted all the (C) code.

http://www.techmind.org/stereo/stech.html

I have converted the code and created a test project here

https://gist.github.com/dermotbalson/7192218

My problem is it seems to create a 3D image all right, but it’s empty, ie I can’t seem to insert objects.

I’ve marked two places in the code.

[1] I create a test image with a couple of rectangles at different distances, which becomes the “depth” image that tells the program how far away to place pixels . It’s these rectangles that are not showing up in the final image.

[2] when I read pixels in from this image, I scale them so they are a proportion of the observable distance (calculated by the program).

The webpage discusses how to place objects, but isn’t very clear.

Anyway, this might give you a good start.

It’s one of the things I was keen to play with and never got around to. Rather than a hard coded table for the objects, I like the idea of a shader that can render the hieght field of meshes to an off screen image, then generate the autostereogram from that.

Then if that’s all done in shaders and can be made to calculate fast enough, could try and make it animate, this probably will cause a big headache when viewing :wink:

There was a bit of discussion on stereograms back in this discussion.

@Andrew_Stacey I looked at the discussion. I see the word Codea in your stereogram. I also made a few comments in that discussion, but I don’t remember it at all. At least I didn’t post the code back then and repost it here. @Ignatz I’ll have to read thru the doc you posted. I’m kind of interested in the details on how this actually happens.

I got it working, will post code soon!

Here is an example (shark)

https://www.dropbox.com/s/fa9lo9p97t9057k/magic.JPG

based on this code

https://gist.github.com/dermotbalson/7192218

You need to choose your own images - I couldn’t find any suitable built in images, so I had to use some I had already downloaded. If you want mine, you can get them here:
https://www.dropbox.com/s/kxlz65ofy7ynq0j/3D-water1.png
https://www.dropbox.com/s/2o33v91rd0hmz58/shark.png

Stereograms rely on providing a depth value for each layer of the picture. I wrote a function to make an outline out of an image and set the colour value to the depth you want. But if you don’t want that, all you need is the CreateStereogram function, which I got from here (this guy seems to know what he’s doing).

http://www.techmind.org/stereo/stech.html

@Ignatz After I posted my code, I was looking around for some info and I ran across a stereogram that showed a shark swimming. I’m not sure how they did it, probably just several stereograms that they just kept showing in a loop.

@dave1707 - yes, easy enough to do

@Ignatz I finally read the link you shared about the stereograms. It does a good job of explaining how these work, and also explains some of the flaws that appear in the stereograms that I was making. But then I originally wrote this code 20-25 years ago, with nothing more to go on then seeing the pictures.