99 lines
2.9 KiB
Rust
99 lines
2.9 KiB
Rust
use nannou::image::{self, GenericImageView};
|
|
use nannou::prelude::*;
|
|
use std::env;
|
|
|
|
struct Model {
|
|
image: image::DynamicImage,
|
|
}
|
|
|
|
const WIDTH: u32 = 800;
|
|
|
|
fn main() {
|
|
nannou::app(model).run();
|
|
}
|
|
|
|
fn model(app: &App) -> Model {
|
|
app.set_loop_mode(LoopMode::Wait);
|
|
app.new_window()
|
|
.size(WIDTH, WIDTH)
|
|
.view(view)
|
|
.build()
|
|
.unwrap();
|
|
|
|
let file = env::args().nth(1).ok_or("Please give me a file!").unwrap();
|
|
let image = image::open(file).unwrap();
|
|
|
|
Model { image }
|
|
}
|
|
|
|
fn view(app: &App, model: &Model, frame: Frame) {
|
|
let _block_size: usize = 32;
|
|
let draw = app
|
|
.draw()
|
|
.translate(vec3(WIDTH as f32 / 2.0, WIDTH as f32 / 2.0, 0.0))
|
|
.scale(-1.0);
|
|
|
|
let win = app.window_rect();
|
|
let tile_count = map_range(
|
|
clamp(app.mouse.x, WIDTH as f32 / -2.0, WIDTH as f32 / 2.0),
|
|
WIDTH as f32 / -2.0,
|
|
WIDTH as f32 / 2.0,
|
|
WIDTH / 4,
|
|
WIDTH / 20,
|
|
);
|
|
|
|
let rect_size = win.w() / tile_count as f32;
|
|
|
|
let scale_x = model.image.width() as f32 / win.w();
|
|
let scale_y = model.image.height() as f32 / win.h();
|
|
|
|
for grid_y in 0..tile_count as usize {
|
|
for grid_x in 0..tile_count as usize {
|
|
let pos_x = grid_x as f32 * rect_size;
|
|
let pos_y = grid_y as f32 * rect_size;
|
|
|
|
let img_x1 = (pos_x * scale_x) as u32;
|
|
let img_y1 = (pos_y * scale_y) as u32;
|
|
let img_x2 = ((pos_x + rect_size - 1.0) * scale_x) as u32;
|
|
let img_y2 = ((pos_y + rect_size - 1.0) * scale_y) as u32;
|
|
|
|
// extract colors from current rect
|
|
let mut cols: Vec<Hsv> = Vec::new();
|
|
for px_y in img_y1..img_y2 {
|
|
for px_x in img_x1..img_x2 {
|
|
let px = model.image.get_pixel(px_x, px_y);
|
|
let col = rgb(
|
|
px[0] as f32 / 255.0,
|
|
px[1] as f32 / 255.0,
|
|
px[2] as f32 / 255.0,
|
|
);
|
|
cols.push(col.clone().into());
|
|
}
|
|
}
|
|
|
|
// sort colors
|
|
cols.sort_by(|a, b| {
|
|
a.hue
|
|
.to_radians()
|
|
.partial_cmp(&b.hue.to_radians())
|
|
.unwrap()
|
|
.reverse()
|
|
});
|
|
|
|
// draw sorted colors
|
|
for y in 0..(img_y2 - img_y1) {
|
|
for x in 0..(img_x2 - img_x1) {
|
|
let i = (x * (rect_size as u32) + y) as usize;
|
|
let pos_x = pos_x + (rect_size * (x as f32 / rect_size));
|
|
let pos_y = pos_y + (rect_size * (y as f32 / rect_size));
|
|
draw.rect()
|
|
.x_y(pos_x, pos_y) // rects get drawn from the middle
|
|
.w_h(1.0, 1.0)
|
|
.color(cols[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
draw.to_frame(app, &frame).unwrap();
|
|
}
|