Last active
December 16, 2015 20:19
-
-
Save rm-hull/5491968 to your computer and use it in GitHub Desktop.
Arnold's cat map is named after the mathematician Vladimir Arnold, who in the 1960s demonstrated the effect of repeatedly applying a linear transformation to an image of a cat (hence the name). Each animation frame transforms the pixels according to the pisano period of the largest dimension (width or height). Eventually the image will restore b…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns arnolds-cat-map.demo | |
(:use [monet.canvas :only [draw-image get-pixel composition-operation]] | |
[monet.core :only [animation-frame]] | |
[enchilada :only [ctx canvas proxy-request]] | |
[jayq.core :only [show]] | |
[jayq.util :only [wait]]) | |
(:use-macros [dommy.macros :only [sel1 node]])) | |
(def cat-resources | |
[ | |
"https://gist.github.com/rm-hull/8859515c9dce89935ac2/raw/cat_01.jpg" | |
"https://gist.github.com/rm-hull/8859515c9dce89935ac2/raw/cat_02.jpg" | |
"https://gist.github.com/rm-hull/8859515c9dce89935ac2/raw/cat_03.jpg" | |
"https://gist.github.com/rm-hull/8859515c9dce89935ac2/raw/cat_04.jpg" | |
"https://gist.github.com/rm-hull/8859515c9dce89935ac2/raw/cat_05.jpg" | |
"https://gist.github.com/rm-hull/8859515c9dce89935ac2/raw/cat_06.jpg" | |
"https://gist.github.com/rm-hull/8859515c9dce89935ac2/raw/cat_07.jpg" | |
"https://gist.github.com/rm-hull/8859515c9dce89935ac2/raw/cat_08.jpg" | |
]) | |
(defn random-cat [] | |
(nth cat-resources (rand-int (count cat-resources)))) | |
(defn load-image! [url & [callback-fn]] | |
(let [img (js/Image.)] | |
(when callback-fn | |
(set! (.-onload img) (fn [] (callback-fn img)))) | |
(set! (.-crossOrigin img) "anonymous") | |
(set! (.-src img) (proxy-request url))) | |
img) | |
(defn offset [[x y] w] | |
(* (+ (* y w) x) 4)) | |
(defn pisano-period [n] | |
(fn [x y] | |
[(mod y n) (mod (+ x y) n)])) | |
(defn draw-frame! [ctx n mapper-fn] | |
(let [image-in (. ctx (getImageData 0 0 n n)) | |
image-out (. ctx (createImageData n n)) | |
data-in (.-data image-in) | |
data-out (.-data image-out)] | |
(doseq [y (range n) | |
x (range n) | |
:let [i (offset [x y] n) | |
o (offset (mapper-fn x y) n)] | |
c (range 4)] | |
(aset data-out (+ o c) (aget data-in (+ i c)))) | |
(. ctx (putImageData image-out 0 0)) | |
ctx)) | |
(defn animate [img] | |
(let [width (.-width img) | |
height (.-height img)] | |
(draw-image ctx img { :x 0 :y 0 :w width :h height }) | |
(wait | |
2000 | |
(fn [] | |
(let [n (max width height) | |
mapper-fn (pisano-period n)] | |
(letfn [(loop [] | |
(animation-frame loop) | |
(draw-frame! ctx n mapper-fn))] | |
(loop))))))) | |
(show canvas) | |
(load-image! (random-cat) animate) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment