main.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. extern crate cairo;
  2. extern crate palette;
  3. extern crate rand;
  4. use rand::Rng;
  5. use cairo::Gradient;
  6. const WIDTH: i32 = 3840;
  7. const HEIGHT: i32 = 2160;
  8. fn cloud(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
  9. let x_scale = rng.gen::<f64>() * 2.0 + 1.0;
  10. let x = (rng.gen::<f64>() * WIDTH as f64) / x_scale;
  11. let y = rng.gen::<f64>() * HEIGHT as f64;
  12. let num_circles = 2 + (rng.gen::<isize>() % 2);
  13. let vec: Vec<(f64, f64)> = (0..num_circles).map(|_| {
  14. let width = 60.0 + rng.gen::<f64>() * 200.0;
  15. let dist = 30.0 + rng.gen::<f64>() * 30.0;
  16. (width, dist)
  17. }).collect();
  18. let surf = cairo::Context::new(&ctx.get_target().create_similar(cairo::Content::Alpha, WIDTH, HEIGHT));
  19. surf.save();
  20. let mut max_y = 0.0;
  21. let mut offset = x;
  22. surf.scale(x_scale, 1.0);
  23. surf.set_source_rgba(1.0, 1.0, 1.0, 1.0);
  24. for (width, dist) in vec {
  25. surf.arc(offset, y, width, 0.0, 3.14159 * 2.0);
  26. surf.fill();
  27. offset = offset + width + dist;
  28. max_y = if width > max_y { width } else { max_y };
  29. }
  30. surf.set_source_rgba(0.0, 0.0, 0.0, 0.0);
  31. surf.set_operator(cairo::Operator::Source);
  32. surf.rectangle(x - 260.0, y, offset + 260.0, max_y);
  33. surf.fill();
  34. surf.restore();
  35. surf.set_source_rgba(1.0, 1.0, 1.0, 0.8);
  36. ctx.mask(&cairo::SurfacePattern::create(&surf.get_target()));
  37. }
  38. fn shinedies(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
  39. let r = rng.gen::<f64>();
  40. for _ in 0..20 {
  41. let surf = cairo::Context::new(&ctx.get_target().create_similar(cairo::Content::Alpha, WIDTH, HEIGHT));
  42. surf.save();
  43. surf.scale(0.5, 0.5);
  44. surf.translate(rng.gen::<f64>() * WIDTH as f64 * 2.0, rng.gen::<f64>() * HEIGHT as f64 * 2.0);
  45. surf.rotate(r);
  46. surf.set_source_rgba(1.0, 1.0, 1.0, 1.0);
  47. let w = 300.0 + rng.gen::<f64>() * 1200.0;
  48. let r = rng.gen::<f64>() * 300.0;
  49. surf.arc(0.0, 0.0, r, 0.0, 3.14159 * 2.0);
  50. surf.fill();
  51. surf.arc(w, 0.0, r, 0.0, 3.14159 * 2.0);
  52. surf.fill();
  53. surf.rectangle(0.0, -r, w, r * 2.0);
  54. surf.fill();
  55. surf.restore();
  56. ctx.set_source_rgba(1.0, 1.0, 1.0, 0.3);
  57. ctx.mask(&cairo::SurfacePattern::create(&surf.get_target()));
  58. }
  59. }
  60. fn stars(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
  61. ctx.set_source_rgba(1.0, 1.0, 1.0, 0.8);
  62. for _ in 0..200 {
  63. let x = rng.gen::<f64>() * WIDTH as f64;
  64. let y = rng.gen::<f64>() * HEIGHT as f64;
  65. let s = 4.0 + rng.gen::<f64>() * 6.0 as f64;
  66. ctx.arc(x, y, s, 0.0, 3.14159 * 2.0);
  67. ctx.fill();
  68. }
  69. }
  70. fn get_sky_colors(rng: &mut rand::ThreadRng) -> (palette::Rgb, palette::Rgb) {
  71. use palette::{RgbHue, Hsv, Hue};
  72. let default_dark: Hsv = Hsv::from(palette::Rgb::new(0.188, 0.333, 0.51));
  73. let default_light: Hsv = Hsv::from(palette::Rgb::new(0.482, 0.749, 0.839));
  74. let shift = RgbHue::from_radians(rng.gen::<f32>() * 3.14159 * 2.0);
  75. (default_dark.shift_hue(shift).into(), default_light.shift_hue(shift).into())
  76. }
  77. fn main() {
  78. let surf = cairo::ImageSurface::create(
  79. cairo::Format::Rgb24,
  80. WIDTH,
  81. HEIGHT
  82. ).unwrap();
  83. let mut rng = rand::thread_rng();
  84. let ctx = cairo::Context::new(&surf);
  85. let w = rng.gen::<u8>() % 3;
  86. ctx.set_source_rgb(
  87. if w == 0 { 0.4 } else { 0.2 },
  88. if w == 1 { 0.4 } else { 0.2 },
  89. if w == 2 { 0.4 } else { 0.2 },
  90. );
  91. ctx.paint();
  92. let g = cairo::LinearGradient::new(
  93. 0.0, 0.0, 0.0, HEIGHT as f64
  94. );
  95. let (dark, light) = get_sky_colors(&mut rng);
  96. g.add_color_stop_rgb(0.0, dark.red as f64, dark.green as f64, dark.blue as f64);
  97. g.add_color_stop_rgb(1.0, light.red as f64, light.green as f64, light.blue as f64);
  98. ctx.set_source(&g);
  99. ctx.paint();
  100. stars(&ctx, &mut rng);
  101. for _ in 0..10 {
  102. cloud(&ctx, &mut rng);
  103. }
  104. shinedies(&ctx, &mut rng);
  105. {
  106. let mut f = std::fs::File::create("image.png").unwrap();
  107. surf.write_to_png(&mut f).unwrap();
  108. }
  109. }