Title: Poor contrast in duck fractal
Post by: Sigillum Militum on April 02, 2012, 10:46:38 AM
I figured I'd have a go at rendering the duck fractal described here: http://www.algorithmic-worlds.net/blog/blog.php?Post=20110227 Now I think I'm doing it more or less right because I'm getting the duck shape (with a different orientation, probably because of how I'm rendering it vis à vis mapping the subset of the complex plane I'm looking at to pixels) ... but contrast is not good. Here is how it is shown in the blog: (http://www.algorithmic-worlds.net/blog/20110227-DucksM.jpg) and here's mine: (http://i.imgur.com/oGCRW.png) Right now I'm taking cumulative moving averages of the magnitude of z at each point, multiplying that by 100, then using floor() to make sure they're all integers. Then I find the minimum and maximum averages and create a linear gradient from white to black with [(maximum avg - minimum avg) + 1] steps. Then I biject from the averages to the list representing the gradient. For whatever its worth, here is the code, in OCaml (ps I see too many posts where no one uses the code tags; they're there for a reason!): open Complex;; open Batteries_uni;;
let x = 500;; let y = 875;; let nw_corner = {re = (-1.); im = 0.};; let se_corner = {re = 1.; im = Float.neg (4. *. atan 1.)};; let width = se_corner.re -. nw_corner.re;; let height = nw_corner.im -. se_corner.im;;
let () = begin prerr_float width; prerr_newline (); prerr_float height; prerr_newline (); end;;
let pixel_coordinates_to_complex_plane (i, j) (x, y) origin width height = {re = origin.re +. width *. (float_of_int i /. float_of_int x); im = origin.im -. height *. (float_of_int j /. float_of_int y)};;
let labs z = if z.im >= 0. then z else conj z;;
let matrix_of_means_of_norms_of_z = Array.make_matrix y x 0.;; let z = ref zero;; let iterations = 50;;
let () = for i = 0 to x - 1 do prerr_int i; prerr_newline ();
for j = 0 to y - 1 do let point = pixel_coordinates_to_complex_plane (i, j) (x, y) nw_corner width height in begin (* prerr_int i; prerr_string " "; prerr_int j; prerr_string ": "; prerr_float point.re; prerr_string " "; prerr_float point.im; prerr_newline (); *)
z := zero;
for t = 0 to iterations - 1 do begin z := Complex.log (Complex.add (labs !z) point);
(* cumulative moving average *) matrix_of_means_of_norms_of_z.(j).(i) <- (norm !z +. (float_of_int t) *. matrix_of_means_of_norms_of_z.(j).(i)) /. float_of_int (t + 1) end done end done done;;
let magnification = 100.;;
let color_matrix = matrix_of_means_of_norms_of_z |> Array.map (fun row -> row |> Array.map (fun mean -> mean *. magnification |> floor |> int_of_float));;
let () = begin Array.to_list color_matrix |> Array.concat |> Array.fold_left max 0 |> prerr_int; prerr_newline();
Array.to_list color_matrix |> Array.concat |> Array.fold_left min max_int |> prerr_int; prerr_newline(); end;;
let palette = [[255; 255; 255]; [255; 255; 255]; [254; 254; 254]; [253; 253; 253]; [252; 252; 252]; [251; 251; 251]; [250; 250; 250]; [249; 249; 249]; [249; 249; 249]; [248; 248; 248]; [247; 247; 247]; [246; 246; 246]; [245; 245; 245]; [244; 244; 244]; [243; 243; 243]; [242; 242; 242]; [242; 242; 242]; [241; 241; 241]; [240; 240; 240]; [239; 239; 239]; [238; 238; 238]; [237; 237; 237]; [236; 236; 236]; [235; 235; 235]; [235; 235; 235]; [234; 234; 234]; [233; 233; 233]; [232; 232; 232]; [231; 231; 231]; [230; 230; 230]; [229; 229; 229]; [229; 229; 229]; [228; 228; 228]; [227; 227; 227]; [226; 226; 226]; [225; 225; 225]; [224; 224; 224]; [223; 223; 223]; [222; 222; 222]; [222; 222; 222]; [221; 221; 221]; [220; 220; 220]; [219; 219; 219]; [218; 218; 218]; [217; 217; 217]; [216; 216; 216]; [215; 215; 215]; [215; 215; 215]; [214; 214; 214]; [213; 213; 213]; [212; 212; 212]; [211; 211; 211]; [210; 210; 210]; [209; 209; 209]; [209; 209; 209]; [208; 208; 208]; [207; 207; 207]; [206; 206; 206]; [205; 205; 205]; [204; 204; 204]; [203; 203; 203]; [202; 202; 202]; [202; 202; 202]; [201; 201; 201]; [200; 200; 200]; [199; 199; 199]; [198; 198; 198]; [197; 197; 197]; [196; 196; 196]; [195; 195; 195]; [195; 195; 195]; [194; 194; 194]; [193; 193; 193]; [192; 192; 192]; [191; 191; 191]; [190; 190; 190]; [189; 189; 189]; [188; 188; 188]; [188; 188; 188]; [187; 187; 187]; [186; 186; 186]; [185; 185; 185]; [184; 184; 184]; [183; 183; 183]; [182; 182; 182]; [182; 182; 182]; [181; 181; 181]; [180; 180; 180]; [179; 179; 179]; [178; 178; 178]; [177; 177; 177]; [176; 176; 176]; [175; 175; 175]; [175; 175; 175]; [174; 174; 174]; [173; 173; 173]; [172; 172; 172]; [171; 171; 171]; [170; 170; 170]; [169; 169; 169]; [168; 168; 168]; [168; 168; 168]; [167; 167; 167]; [166; 166; 166]; [165; 165; 165]; [164; 164; 164]; [163; 163; 163]; [162; 162; 162]; [162; 162; 162]; [161; 161; 161]; [160; 160; 160]; [159; 159; 159]; [158; 158; 158]; [157; 157; 157]; [156; 156; 156]; [155; 155; 155]; [155; 155; 155]; [154; 154; 154]; [153; 153; 153]; [152; 152; 152]; [151; 151; 151]; [150; 150; 150]; [149; 149; 149]; [148; 148; 148]; [148; 148; 148]; [147; 147; 147]; [146; 146; 146]; [145; 145; 145]; [144; 144; 144]; [143; 143; 143]; [142; 142; 142]; [141; 141; 141]; [141; 141; 141]; [140; 140; 140]; [139; 139; 139]; [138; 138; 138]; [137; 137; 137]; [136; 136; 136]; [135; 135; 135]; [135; 135; 135]; [134; 134; 134]; [133; 133; 133]; [132; 132; 132]; [131; 131; 131]; [130; 130; 130]; [129; 129; 129]; [128; 128; 128]; [128; 128; 128]; [127; 127; 127]; [126; 126; 126]; [125; 125; 125]; [124; 124; 124]; [123; 123; 123]; [122; 122; 122]; [121; 121; 121]; [121; 121; 121]; [120; 120; 120]; [119; 119; 119]; [118; 118; 118]; [117; 117; 117]; [116; 116; 116]; [115; 115; 115]; [115; 115; 115]; [114; 114; 114]; [113; 113; 113]; [112; 112; 112]; [111; 111; 111]; [110; 110; 110]; [109; 109; 109]; [108; 108; 108]; [108; 108; 108]; [107; 107; 107]; [106; 106; 106]; [105; 105; 105]; [104; 104; 104]; [103; 103; 103]; [102; 102; 102]; [101; 101; 101]; [101; 101; 101]; [100; 100; 100]; [99; 99; 99]; [98; 98; 98]; [97; 97; 97]; [96; 96; 96]; [95; 95; 95]; [94; 94; 94]; [94; 94; 94]; [93; 93; 93]; [92; 92; 92]; [91; 91; 91]; [90; 90; 90]; [89; 89; 89]; [88; 88; 88]; [88; 88; 88]; [87; 87; 87]; [86; 86; 86]; [85; 85; 85]; [84; 84; 84]; [83; 83; 83]; [82; 82; 82]; [81; 81; 81]; [81; 81; 81]; [80; 80; 80]; [79; 79; 79]; [78; 78; 78]; [77; 77; 77]; [76; 76; 76]; [75; 75; 75]; [74; 74; 74]; [74; 74; 74]; [73; 73; 73]; [72; 72; 72]; [71; 71; 71]; [70; 70; 70]; [69; 69; 69]; [68; 68; 68]; [68; 68; 68]; [67; 67; 67]; [66; 66; 66]; [65; 65; 65]; [64; 64; 64]; [63; 63; 63]; [62; 62; 62]; [61; 61; 61]; [61; 61; 61]; [60; 60; 60]; [59; 59; 59]; [58; 58; 58]; [57; 57; 57]; [56; 56; 56]; [55; 55; 55]; [54; 54; 54]; [54; 54; 54]; [53; 53; 53]; [52; 52; 52]; [51; 51; 51]; [50; 50; 50]; [49; 49; 49]; [48; 48; 48]; [47; 47; 47]; [47; 47; 47]; [46; 46; 46]; [45; 45; 45]; [44; 44; 44]; [43; 43; 43]; [42; 42; 42]; [41; 41; 41]; [41; 41; 41]; [40; 40; 40]; [39; 39; 39]; [38; 38; 38]; [37; 37; 37]; [36; 36; 36]; [35; 35; 35]; [34; 34; 34]; [34; 34; 34]; [33; 33; 33]; [32; 32; 32]; [31; 31; 31]; [30; 30; 30]; [29; 29; 29]; [28; 28; 28]; [27; 27; 27]; [27; 27; 27]; [26; 26; 26]; [25; 25; 25]; [24; 24; 24]; [23; 23; 23]; [22; 22; 22]; [21; 21; 21]; [21; 21; 21]; [20; 20; 20]; [19; 19; 19]; [18; 18; 18]; [17; 17; 17]; [16; 16; 16]; [15; 15; 15]; [14; 14; 14]; [14; 14; 14]; [13; 13; 13]; [12; 12; 12]; [11; 11; 11]; [10; 10; 10]; [9; 9; 9]; [8; 8; 8]; [7; 7; 7]; [7; 7; 7]; [6; 6; 6]; [5; 5; 5]; [4; 4; 4]; [3; 3; 3]; [2; 2; 2]; [1; 1; 1]];;
let () = Printf.printf "P3\n"; Printf.printf "%d %d\n" x y; Printf.printf "255\n";
for j = 0 to y - 1 do for i = 0 to x - 1 do let color = List.nth palette color_matrix.(j).(i) in let r = List.nth color 0 and g = List.nth color 1 and b = List.nth color 2 in Printf.printf "%d\t%d\t%d\t" r g b; done;
print_newline (); done;; The output is PNM, as described here: http://en.wikipedia.org/wiki/Netpbm_format Statements with prerr are notifications and you can overlook them. What can I be doing better?
Title: Re: Poor contrast in duck fractal
Post by: Sigillum Militum on April 02, 2012, 12:50:03 PM
Before anyone answers, I noticed that the function mapping pixels to points on the complex plane didn't use equal increments in the x and y directions and have rectified this.
The outcome is better but not quite optimal:
(http://i.imgur.com/m9EEp.png)
Title: Re: Poor contrast in duck fractal
Post by: Syntopia on April 02, 2012, 12:58:59 PM
Ther are many ways to color fractals, but I'd suggest using a formula for coloring instead of the discrete palette. For instance I used the following formula for the attached image: Brightness = 0.5+0.5*cos(6.0 * log2(log2(mean/C)))
where C is an arbitrary constant (~0.5 in the image), and 'mean' is the average length. The double log term is a leftover from the smoothened iteration count often used for coloring the Mandelbrot set, but doesn't carry any real meaning here.
Title: Re: Poor contrast in duck fractal
Post by: Sigillum Militum on April 02, 2012, 01:05:29 PM
Ther are many ways to color fractals, but I'd suggest using a formula for coloring instead of the discrete palette. For instance I used the following formula for the attached image: Brightness = 0.5+0.5*cos(6.0 * log2(log2(mean/C)))
where C is an arbitrary constant (~0.5 in the image), and 'mean' is the average length. The double log term is a leftover from the smoothened iteration count often used for coloring the Mandelbrot set, but doesn't carry any real meaning here. What does the 6.0 stand for? (never mind; figured it out; it has to do with angular frequency) Is there any way I can simplify this expression?
Title: Re: Poor contrast in duck fractal
Post by: s31415 on April 02, 2012, 08:49:36 PM
Hi,
My original picture was made in Ultrafractal. Ultrafractal takes a real number for each pixel (the "index") and maps it onto a periodic gradient. In the case of the image above, the periodic gradient was going from white to black and back. You can see on the picture the places where it reaches white and goes back toward black. Had I made sure that the maximal value of the index was mapped to white and the minimal to black, I guess I'd have got the same picture as you, with less contrast.
Best,
Sam
Title: Re: Poor contrast in duck fractal
Post by: Sigillum Militum on April 03, 2012, 04:10:13 PM
Hi,
My original picture was made in Ultrafractal. Ultrafractal takes a real number for each pixel (the "index") and maps it onto a periodic gradient. In the case of the image above, the periodic gradient was going from white to black and back. You can see on the picture the places where it reaches white and goes back toward black. Had I made sure that the maximal value of the index was mapped to white and the minimal to black, I guess I'd have got the same picture as you, with less contrast.
Best,
Sam
Thank you but the cosine strategy named above is working fine. Here is my first Duck Julia set: (http://i41.tinypic.com/abkwfo.png)
|