123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- extern crate cairo;
- extern crate palette;
- extern crate rand;
- use rand::Rng;
- use cairo::Gradient;
- const WIDTH: i32 = 3840;
- const HEIGHT: i32 = 2160;
- fn cloud(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
- let x_scale = rng.gen::<f64>() * 2.0 + 1.0;
- let x = (rng.gen::<f64>() * WIDTH as f64) / x_scale;
- let y = rng.gen::<f64>() * HEIGHT as f64;
- let num_circles = 2 + (rng.gen::<isize>() % 2);
- let vec: Vec<(f64, f64)> = (0..num_circles).map(|_| {
- let width = 60.0 + rng.gen::<f64>() * 200.0;
- let dist = 30.0 + rng.gen::<f64>() * 30.0;
- (width, dist)
- }).collect();
- let surf = cairo::Context::new(&ctx.get_target().create_similar(cairo::Content::Alpha, WIDTH, HEIGHT));
- surf.save();
- let mut max_y = 0.0;
- let mut offset = x;
- surf.scale(x_scale, 1.0);
- surf.set_source_rgba(1.0, 1.0, 1.0, 1.0);
- for (width, dist) in vec {
- surf.arc(offset, y, width, 0.0, 3.14159 * 2.0);
- surf.fill();
- offset = offset + width + dist;
- max_y = if width > max_y { width } else { max_y };
- }
- surf.set_source_rgba(0.0, 0.0, 0.0, 0.0);
- surf.set_operator(cairo::Operator::Source);
- surf.rectangle(x - 260.0, y, offset + 260.0, max_y);
- surf.fill();
- surf.restore();
- surf.set_source_rgba(1.0, 1.0, 1.0, 0.8);
- ctx.mask(&cairo::SurfacePattern::create(&surf.get_target()));
- }
- fn shinedies(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
- let r = rng.gen::<f64>();
- for _ in 0..20 {
- let surf = cairo::Context::new(&ctx.get_target().create_similar(cairo::Content::Alpha, WIDTH, HEIGHT));
- surf.save();
- surf.scale(0.5, 0.5);
- surf.translate(rng.gen::<f64>() * WIDTH as f64 * 2.0, rng.gen::<f64>() * HEIGHT as f64 * 2.0);
- surf.rotate(r);
- surf.set_source_rgba(1.0, 1.0, 1.0, 1.0);
- let w = 300.0 + rng.gen::<f64>() * 1200.0;
- let r = rng.gen::<f64>() * 300.0;
- surf.arc(0.0, 0.0, r, 0.0, 3.14159 * 2.0);
- surf.fill();
- surf.arc(w, 0.0, r, 0.0, 3.14159 * 2.0);
- surf.fill();
- surf.rectangle(0.0, -r, w, r * 2.0);
- surf.fill();
- surf.restore();
- ctx.set_source_rgba(1.0, 1.0, 1.0, 0.3);
- ctx.mask(&cairo::SurfacePattern::create(&surf.get_target()));
- }
- }
- fn stars(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
- ctx.set_source_rgba(1.0, 1.0, 1.0, 0.8);
- for _ in 0..200 {
- let x = rng.gen::<f64>() * WIDTH as f64;
- let y = rng.gen::<f64>() * HEIGHT as f64;
- let s = 4.0 + rng.gen::<f64>() * 6.0 as f64;
- ctx.arc(x, y, s, 0.0, 3.14159 * 2.0);
- ctx.fill();
- }
- }
- fn get_sky_colors(rng: &mut rand::ThreadRng) -> (palette::Rgb, palette::Rgb) {
- use palette::{RgbHue, Hsv, Hue};
- let default_dark: Hsv = Hsv::from(palette::Rgb::new(0.188, 0.333, 0.51));
- let default_light: Hsv = Hsv::from(palette::Rgb::new(0.482, 0.749, 0.839));
- let shift = RgbHue::from_radians(rng.gen::<f32>() * 3.14159 * 2.0);
- (default_dark.shift_hue(shift).into(), default_light.shift_hue(shift).into())
- }
- fn main() {
- let surf = cairo::ImageSurface::create(
- cairo::Format::Rgb24,
- WIDTH,
- HEIGHT
- ).unwrap();
- let mut rng = rand::thread_rng();
- let ctx = cairo::Context::new(&surf);
- let w = rng.gen::<u8>() % 3;
- ctx.set_source_rgb(
- if w == 0 { 0.4 } else { 0.2 },
- if w == 1 { 0.4 } else { 0.2 },
- if w == 2 { 0.4 } else { 0.2 },
- );
- ctx.paint();
- let g = cairo::LinearGradient::new(
- 0.0, 0.0, 0.0, HEIGHT as f64
- );
- let (dark, light) = get_sky_colors(&mut rng);
- g.add_color_stop_rgb(0.0, dark.red as f64, dark.green as f64, dark.blue as f64);
- g.add_color_stop_rgb(1.0, light.red as f64, light.green as f64, light.blue as f64);
- ctx.set_source(&g);
- ctx.paint();
- stars(&ctx, &mut rng);
- for _ in 0..10 {
- cloud(&ctx, &mut rng);
- }
- shinedies(&ctx, &mut rng);
- {
- let mut f = std::fs::File::create("image.png").unwrap();
- surf.write_to_png(&mut f).unwrap();
- }
- }
|