{- Red spiral by Michal Kot. compile and run. result image will be saved as red.ppm and can be opened using a default image browser. (in windows, use IrfanView or similar) please note that it could take about 30sec or longer depending on speed -} --draw function calculates values for each pixel draw fx tx fy ty s iter = rows s s where rows y x | x == 0 = rows (y-1) s rows y x | y == 0 = [] rows y x | (x > 0) && (y > 0) = iteration (fx+(x*cx)) (fy+(y*cy)) iter : rows y (x-1) cx = (tx-fx)/s cy = (ty-fy)/s --creates a ppm file ppm s cs = "P3\n" ++ show s ++ " " ++ show s ++ "\n255\n" ++ (f cs) where f [] = "" f (x:xs) = c (mod x 1000) 1000 ++ "\n" ++ f xs --depending on interation, choose a color c x max = fg (round ((1023/fromIntegral max) * fromIntegral x)) where fg n | n < 256 = show n ++ " 0 0" fg n | n < 512 = "255 " ++ show (n-256) ++ " 0" fg n | n < 768 = "0 " ++ show (767-n) ++ " " ++ show (n-512) fg n | n < 1024 = "0 0 " ++ show (1023-n) --most important function that calculates values for each point. it is amazing how simply it could be implemented in haskell iteration :: Double -> Double -> Int -> Int iteration x0 y0 iter = loop x0 y0 0 where loop x y i | ((x*x)+(y*y)) >4 = i loop x y i | i == iter = 0 loop x y i | otherwise = loop (x*x - y*y + x0) (2*x*y + y0) (i+1) --main: calculate all pixels, create ppm file and save main = writeFile "red.ppm" (ppm 1000 (draw (-0.338533147167322) (-0.335124997593271) (-0.641201519795881) (-0.63736432972578) 1000 1000))