aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Janzen <jacob.a.s.janzen@gmail.com>2022-08-23 12:24:59 -0500
committerJacob Janzen <jacob.a.s.janzen@gmail.com>2022-08-23 12:24:59 -0500
commitd488fd578d8293fe267bdbad582b30771fa8c01f (patch)
tree3addc70cc27c37d224d830243cae237a93fdbec2
parentc463fb7d0ab36c44046a5a7edc88902f5b90e710 (diff)
refactored code into methods
-rw-r--r--Cargo.toml5
-rw-r--r--output.gifbin551037 -> 483541 bytes
-rw-r--r--src/lib.rs112
-rw-r--r--src/main.rs8
4 files changed, 65 insertions, 60 deletions
diff --git a/Cargo.toml b/Cargo.toml
index b30df36..eba99ab 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,6 +2,11 @@
name = "bubbles"
version = "0.1.0"
edition = "2021"
+authors = ["Jacob Janzen"]
+description = "Creates a procedurally generated image that sort of looks like bubbles"
+repository = "https://github.com/JacobJanzen/Bubbles/"
+license = "GPL-3.0"
+keywords = ["generative-art","gif"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/output.gif b/output.gif
index 4527bef..26afcb5 100644
--- a/output.gif
+++ b/output.gif
Binary files differ
diff --git a/src/lib.rs b/src/lib.rs
index 626d775..41edac9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -17,7 +17,7 @@ use std::vec;
use clap::Parser;
-pub struct Gif {
+pub struct Image {
pub height: u16,
pub width: u16,
pub frames: u16,
@@ -69,9 +69,9 @@ impl Args {
}
}
-impl Gif {
+impl Image {
pub fn create_from_args(args: &Args) -> Self {
- Gif {
+ Image {
height: args.height,
width: args.width,
frames: args.frames,
@@ -83,27 +83,64 @@ impl Gif {
};
args.height as usize * args.width as usize
],
- cross_distance: distance(
- &Point { x: 0, y: 0 },
- &Point {
- x: args.width - 1,
- y: args.height - 1,
- },
- ),
+ cross_distance: Point { x: 0, y: 0 }.distance(&Point {
+ x: args.width - 1,
+ y: args.height - 1,
+ }),
points: generate_points(args.width, args.height, args.num_cells),
}
}
+
+ pub fn fill_canvas(&mut self) {
+ self.generate_noise();
+ }
+
+ fn generate_noise(&mut self) {
+ let mut max_dist = 0.0;
+
+ // Get distance and nearest point for each point on the canvas
+ for y in 0..self.height {
+ for x in 0..self.width {
+ let index = y as usize * self.width as usize + x as usize;
+ self.point_data[index] = PointData::get_point_data(self, Point { x, y });
+ max_dist = f64::max(max_dist, self.point_data[index].min_dist);
+ }
+ }
+
+ // normalize distances to [0,1]
+ for y in 0..self.height {
+ for x in 0..self.width {
+ let index = y as usize * self.width as usize + x as usize;
+ self.point_data[index].min_dist /= max_dist;
+ }
+ }
+
+ // write pixels
+ for y in 0..self.height {
+ for x in 0..self.width {
+ let index = y as usize * self.width as usize + x as usize;
+ let val = 0xFF - (0xFF as f64 * self.point_data[index].min_dist) as u8;
+ self.set_pixel(val, val, val, Point { x, y });
+ }
+ }
+ }
+
+ fn set_pixel(&mut self, r: u8, g: u8, b: u8, p: Point) {
+ self.pixels[3 * (self.width as usize * p.y as usize + p.x as usize)] = r;
+ self.pixels[3 * (self.width as usize * p.y as usize + p.x as usize) + 1] = g;
+ self.pixels[3 * (self.width as usize * p.y as usize + p.x as usize) + 2] = b;
+ }
}
impl PointData {
- fn get_point_data(gif: &Gif, p: Point) -> Self {
+ fn get_point_data(image: &Image, p: Point) -> Self {
let mut pd = PointData {
- min_dist: gif.cross_distance,
+ min_dist: image.cross_distance,
closest_point: Point { x: 0, y: 0 },
};
- for point in &gif.points {
- let d = distance(&p, point);
+ for point in &image.points {
+ let d = p.distance(point);
if d < pd.min_dist {
pd.min_dist = d;
pd.closest_point = point.clone();
@@ -114,42 +151,12 @@ impl PointData {
}
}
-pub fn fill_canvas(gif: &mut Gif) {
- generate_noise(gif);
-}
-
-fn set_pixel(gif: &mut Gif, r: u8, g: u8, b: u8, x: u16, y: u16) {
- gif.pixels[3 * (gif.width as usize * y as usize + x as usize)] = r;
- gif.pixels[3 * (gif.width as usize * y as usize + x as usize) + 1] = g;
- gif.pixels[3 * (gif.width as usize * y as usize + x as usize) + 2] = b;
-}
-
-fn generate_noise(gif: &mut Gif) {
- let mut max_dist = 0.0;
-
- // Get distance and nearest point for each point on the canvas
- for y in 0..gif.height {
- for x in 0..gif.width {
- let index = y as usize * gif.width as usize + x as usize;
- gif.point_data[index] = PointData::get_point_data(gif, Point { x, y });
- max_dist = f64::max(max_dist, gif.point_data[index].min_dist);
- }
- }
+impl Point {
+ fn distance(&self, other: &Point) -> f64 {
+ let x_dist: f64 = other.x as f64 - self.x as f64;
+ let y_dist: f64 = other.y as f64 - self.y as f64;
- // normalize distances to [0,1]
- for y in 0..gif.height {
- for x in 0..gif.width {
- let index = y as usize * gif.width as usize + x as usize;
- gif.point_data[index].min_dist /= max_dist;
- }
- }
-
- for y in 0..gif.height {
- for x in 0..gif.width {
- let index = y as usize * gif.width as usize + x as usize;
- let val = 0xFF - (0xFF as f64 * gif.point_data[index].min_dist) as u8;
- set_pixel(gif, val, val, val, x, y)
- }
+ (x_dist * x_dist + y_dist * y_dist).sqrt()
}
}
@@ -163,10 +170,3 @@ fn generate_points(width: u16, height: u16, num_cells: usize) -> Vec<Point> {
points
}
-
-fn distance(p1: &Point, p2: &Point) -> f64 {
- let x_dist: f64 = p2.x as f64 - p1.x as f64;
- let y_dist: f64 = p2.y as f64 - p1.y as f64;
-
- (x_dist * x_dist + y_dist * y_dist).sqrt()
-}
diff --git a/src/main.rs b/src/main.rs
index 59a14c6..3622bb5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -16,13 +16,13 @@ use std::fs::File;
use std::process;
use bubbles::Args;
-use bubbles::Gif;
+use bubbles::Image;
fn main() {
let args = Args::read();
// create Gif data
- let mut gif = Gif::create_from_args(&args);
+ let mut data = Image::create_from_args(&args);
// Create encoder
let mut image = File::create(args.out).unwrap();
@@ -34,8 +34,8 @@ fn main() {
}
// Create pixel array
- bubbles::fill_canvas(&mut gif);
- let frame = gif::Frame::from_rgb(gif.width, gif.height, &mut gif.pixels);
+ data.fill_canvas();
+ let frame = gif::Frame::from_rgb(data.width, data.height, &mut data.pixels);
// Write frame to file
encoder.write_frame(&frame).unwrap();