Last active
May 31, 2024 03:10
-
-
Save kujirahand/bcf2363c86e369a5f075806c4f616816 to your computer and use it in GitHub Desktop.
マンデルブロ集合の画像を連続で書き出しするプログラム
This file contains 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
use image::{ImageBuffer, Rgb}; | |
fn main() { | |
let (sx, sy) = (1280, 720); | |
let (cx, cy, _zoom) = (0.2713912051561837, 0.005142969158296763, 1.4210854715202004e-14); | |
let fps = 24; | |
let image_count = fps * 30; | |
let mut zoom = 4.0; | |
for i in 0..image_count { | |
println!("{:04}/{} - m{:04}.png - zoom*{:.8}", i, image_count, i, zoom); | |
let fname = format!("m{:04}.png", i); | |
draw(sx, sy, cx, cy, zoom, &fname); | |
zoom *= 0.95; | |
} | |
} | |
// マンデルブロ集合の計算 | |
fn mandelbrot(c: (f64, f64), max_iter: u32) -> u32 { | |
let mut z = (0.0, 0.0); | |
let mut n = 0; | |
while n < max_iter { | |
if z.0 * z.0 + z.1 * z.1 > 4.0 { | |
break; | |
} | |
z = (z.0 * z.0 - z.1 * z.1 + c.0, 2.0 * z.0 * z.1 + c.1); | |
n += 1; | |
} | |
n | |
} | |
// imageにマンデルブロ集合を描画してファイルに保存する関数 | |
fn draw(imgx: u32, imgy: u32, cx: f64, cy: f64, zoom: f64, filename: &str) { | |
let max_iter = 1000; | |
let left = cx - zoom / 2.0; | |
let top = cy - zoom / 2.0; | |
let right = left + zoom; | |
let bottom = top + zoom; | |
// マンデルブロ集合のパラメータを指定 | |
let r = imgx as f64 / imgy as f64; | |
let scale_x = (right - left) / imgx as f64 * r * 0.8; | |
let scale_y = (bottom - top) / imgy as f64 * 0.8; | |
// 画像をメモリ上に作成 | |
let mut imgbuf = ImageBuffer::new(imgx, imgy); | |
// 図形を描画する | |
for (x, y, pixel) in imgbuf.enumerate_pixels_mut() { | |
let cx = left + x as f64 * scale_x; | |
let cy = top + y as f64 * scale_y; | |
// マンデルブロ集合の計算 | |
let i = mandelbrot((cx as f64, cy as f64), max_iter); | |
// 色を設定する | |
*pixel = if i == max_iter { | |
Rgb([255, 255, 255]) | |
} else { | |
let cc = i as f64 / max_iter as f64; | |
Rgb(hsl_to_rgb(cc, 1.0, 0.5).into()) | |
// Rgb(hsl_to_rgb(0.1, 0.5, cc).into()) // ゴールドっぽい | |
}; | |
} | |
// Save the image as a PNG file | |
imgbuf.save(filename).unwrap(); | |
println!("Saved {}", filename); | |
} | |
// HSLからRGBに変換する | |
fn hsl_to_rgb(h: f64, s: f64, l: f64) -> (u8, u8, u8) { | |
let (mut r, mut g, mut b) = (l, l, l); | |
if s != 0.0 { | |
let hue2rgb = |p: f64, q: f64, t: f64| -> f64 { | |
let mut t = t; | |
if t < 0.0 { t += 1.0; } | |
if t > 1.0 { t -= 1.0; } | |
if t < 1.0 / 6.0 { return p + (q - p) * 6.0 * t; } | |
if t < 1.0 / 2.0 { return q; } | |
if t < 2.0 / 3.0 { return p + (q - p) * (2.0 / 3.0 - t) * 6.0; } | |
p | |
}; | |
let q = if l < 0.5 { l * (1.0 + s) } else { l + s - l * s }; | |
let p = 2.0 * l - q; | |
r = hue2rgb(p, q, h + 1.0 / 3.0); | |
g = hue2rgb(p, q, h); | |
b = hue2rgb(p, q, h - 1.0 / 3.0); | |
} | |
((r * 255.0).round() as u8, (g * 255.0).round() as u8, (b * 255.0).round() as u8) | |
} |
静止画を描画する場合のメモ
draw(sx, sy, -3.0, -1.5, 4.0, "z0.png");
draw(sx, sy, 0.11, -0.67, 0.06, "z1.png");
draw(sx, sy, 0.11, -0.67, 0.03, "z2.png");
draw(sx, sy, 0.11, -0.67, 0.015, "z3.png");
draw(sx, sy, -0.8278906250000001, -0.1983593749999999, 0.03125, "z4.png");
draw(sx, sy, -0.8137109375, -0.1865917968749999, 0.00390625, "z5.png");
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
良かったパラメータのメモ
// let (cx, cy, zoom) = (-0.90546875, -0.62873046875, 0.0078125);
// let (cx, cy, zoom) = (0.057809906005859384, 0.6565466308593749, 0.000030517578125);
// let (cx, cy, zoom) = (-1.1557366959459607, -0.2777253744623158, 4.656612873077393e-10);