Scanimation!!



Scanimation Christmas Card

A scanimation is an animation created by moving a striped sheet over a specially designed image, creating an illusion of motion. Below is code to make them, I used them for my 2023 Christmas Cards. I printed the striped sheet from old transparencies (things used for old projectors that people can write on instead of whiteboards) - you can likely be kindly donated them at any old University stores (or purchase on Amazon!).

How the code works

I haven't tested this extensively, you just need to be careful how you factor the dimensions of the image. There are effectively \(n\) frames which the the size of the set of the frames of the gif. Then the size of the bar is the \((n-1)*t \), where \(t \times x \) is equal to the width dimension of the gif and \(x\) is the number of bars of the overlay. This leaves only one frame visible, as you just have a \(t\) sized transparent section over the image. Hence, select the frame appropraite to the stripe being passed over it. All the magic happens on this line


    Table[eventualimage[[;;,1+(i-1)*visiblespace+((j-1)*frames*visiblespace);;i*visiblespace+((j-1)*frames*visiblespace)]]=imagedata[[i,;;,1+(i-1)*visiblespace+((j-1)*frames*visiblespace);;i*visiblespace+((j-1)*frames*visiblespace)]],{i,1,frames,1},{j,1,bars,1}];

The code tries to make sure everything is an appropraite factor, but I haven't tested extensively - but it works for a few gifs I've dried. I found ones with fewer frames and little movement between frames worked well, particularly cyclical animations. This is the final effect (in comic sans brilliance), where you now have to imagine an overlay being applied....



I do wonder if you can expand the scanimation by using coloured transparencies (i.e. absorb different colors) and have a fuller image. But, anyway, thats a problem for another day (maybe next year!).

Code for Gif to Image

Use code below to generate the above gif animation. You might be better using the Git , where it will import a gif for you.


      (* import your own gif, or use example from github)
imagedata=ImageData[#,"Real32"]&/@gif;
imagedata=imagedata[[;;,;;,;;,1;;3]]; (*take b&w only *) 
spacing = Round[N[dimensions[[1]]/bars]];
visiblespace = Round[spacing/frames];
blackspace = spacing-visiblespace;

image=Table[imagedata[[i,;;,i;;i+visiblespace]],{i,1,frames,1}];

eventualimage=ConstantArray[{0,0,1},{dimensions[[2]],spacing*bars}];
Table[eventualimage[[;;,1+(i-1)*visiblespace+((j-1)*frames*visiblespace);;i*visiblespace+((j-1)*frames*visiblespace)]]=imagedata[[i,;;,1+(i-1)*visiblespace+((j-1)*frames*visiblespace);;i*visiblespace+((j-1)*frames*visiblespace)]],{i,1,frames,1},{j,1,bars,1}];

Image[eventualimage,ImageSize->Large]
Export["eventualimage.png",Image[eventualimage,ImageSize->Large]]



Code for Striped Overlay

Use code below to generate the stripes - you then need to print this on the aforementioned transparencies.


(* overlay *)

overlayimage=ConstantArray[{1,1,1},{frames,dimensions[[2]],spacing*bars}];
overlayimageblack=ConstantArray[{0,0,0},{dimensions[[2]],spacing*bars}];

Table[overlayimage[[i,;;,visiblespace+((j-1)*(visiblespace+blackspace));;visiblespace+blackspace+((j-1)*(visiblespace+blackspace))]]=overlayimageblack[[;;,visiblespace+((j-1)*(visiblespace+blackspace));;visiblespace+blackspace+((j-1)*(visiblespace+blackspace))]],{j,1,bars,1},{i,1,frames,1}];

Image[overlayimage[[1]],ImageSize->Large]

Export["overlayimage.png",Image[overlayimage[[1]],ImageSize->Large]]

Code for Testing

Use this code to test it.




overlays=Transpose[RotateRight[Transpose[overlayimage[[#]]],(#-1)*visiblespace]]&/@Range[frames];
overlayimages=ColorConvert[Image[#],"RGB"]&/@overlays;
eventualimage2=ColorConvert[Image[eventualimage],"RGB"];


animations=ImageCompose[Image[eventualimage2],ColorReplace[#,White->Transparent]]&/@overlayimages;

ListAnimate[animations,ImageSize->Large]