A better explanation is here: Rotate super-imposed images over each other - #4 by canina
I have to use async to rotate two images over each other translucently. When trying myself I assumed I needed a big function like.
async fn rotate_translucently(translated_x: f32, translated_y: f32, cos: f32, sin: f32, image: Image, brightness: f32,y: usize, buffer: Vec<u32>, x: usize){
let rotated_x: f32 = translated_x * cos + translated_y * sin;
let rotated_y: f32 = translated_x * sin - translated_y * cos;
let mut color: u32 = get_color_new(&image, rotated_y, rotated_x);
let [blue, green, red, alpha] = color.to_ne_bytes();
color = u32::from_ne_bytes([
set_pixel_value(brightness, blue),
set_pixel_value(brightness, green),
set_pixel_value(brightness, red),
alpha,
]);
buffer[y * WIDTH + x] = color;
}
Then I could call it for both image1 and image2. But it seems to big. And I can't call my buffer right since it is a global. What would be the best way to try this? My current solution only rotates image2 because the buffer gets overwritten immeditatly after updating the buffer for image 1.
main.rs
use graphics::{blend_colors, set_pixel_value};
const WIDTH: usize = 900;
const HEIGHT: usize = 900;
struct Image {
width: usize,
height: usize,
buffer: Vec<u32>,
}
impl Image {
fn load(filename: &str) -> Image {
let image =
lodepng::decode32_file(&filename).expect(&format!("Couldn't load {}", &filename));
Image {
width: image.width,
height: image.height,
buffer: image
.buffer
.iter()
.map(|color| {
return u32::from_le_bytes([color.b, color.g, color.r, color.a]);
})
.collect(),
}
}
}
fn main() {
let image1 = Image::load("mainframe1.png");
let image2 = Image::load("mainframe2.png");
let mut window = minifb::Window::new(
"Rotating images",
WIDTH as usize,
HEIGHT as usize,
minifb::WindowOptions {
resize: false,
topmost: true,
borderless: true,
none: true,
transparency: true,
scale: minifb::Scale::X1,
..minifb::WindowOptions::default()
},
)
.expect("Unable to create window");
// The output buffer that we'll render the output image to
let mut buffer = vec![0u32; (WIDTH * HEIGHT) as usize];
// The current rotation in radians (0..2*Pi)
let mut rotation: f32 = 0.0;
// Offsets
let x_offset = WIDTH as f32 / 2 as f32;
let y_offset = HEIGHT as f32 / 2 as f32;
// Whether we are just drawing a single image (0), rotating a single image (1),
// or rotating two superimposed images in different directions (2).
let mut mode = 4;
let mut fps_time = std::time::Instant::now();
let mut fps_count = 0;
while window.is_open() && !window.is_key_down(minifb::Key::Escape) {
rotation += 0.01;
if window.is_key_pressed(minifb::Key::Space, minifb::KeyRepeat::No) {
mode = (mode + 1) % 3;
}
// Draw!
// To prevent code duplication, you may want to move your code from
// your `modes` answers into a function or a method of `Image`.
if mode == 0 {
window.update_with_buffer(&image1.buffer, image1.width, image1.height).unwrap();
} else if mode == 1 {
let mut buffer: Vec<u32> = image1.buffer.to_vec();
let brightness: f32 = 0.25;
for pixel in buffer.iter_mut() {
let [blue, green, red, alpha] = pixel.to_ne_bytes();
*pixel = u32::from_ne_bytes([
set_pixel_value(brightness, blue),
set_pixel_value(brightness, green),
set_pixel_value(brightness, red),
alpha,
]);
}
window.update_with_buffer(&buffer, image1.width, image1.height).unwrap();
} else if mode == 2 {
let brightness: f32 = 0.5;
for y in 0..HEIGHT {
for x in 0..WIDTH {
// for positive integers, the euclidean remainder is the same as the `%` operator
let color_1 = get_color(&image1, y, x);
let color_2 = get_color(&image2, y, x);
// Blend two colors use whatever formula you wants
let final_color = blend_colors(color_1, color_2, brightness);
buffer[y * WIDTH + x] = final_color;
}
}
} else if mode == 3 {
// TODO: Offset and rotate image 1
for x in 0..HEIGHT {
for y in 0..WIDTH {
let translated_x = x as f32 - x_offset as f32;
let translated_y = y as f32 - y_offset as f32;
let rotated_x = translated_x * rotation.cos() + translated_y * rotation.sin();
let rotated_y = translated_x * rotation.sin() - translated_y * rotation.cos();
// let color = get_color(&image1, rotated_y as usize, rotated_x as usize);
let color = get_color_new(&image1, rotated_y, rotated_x);
buffer[y * WIDTH + x] = color;
}
}
} else if mode == 4 {
let cos: f32 = rotation.cos();
let sin: f32 = rotation.sin();
let brightness: f32 = 0.5;
for x in 0..HEIGHT {
for y in 0..WIDTH {
let translated_x = x as f32 - x_offset as f32;
let translated_y = y as f32 - y_offset as f32;
for i in 0..2 {
if i == 0 {
let rotated_x = translated_x * cos + translated_y * sin;
let rotated_y = translated_x * sin - translated_y * cos;
let mut color = get_color_new(&image1, rotated_y, rotated_x);
let [blue, green, red, alpha] = color.to_ne_bytes();
color = u32::from_ne_bytes([
set_pixel_value(brightness, blue),
set_pixel_value(brightness, green),
set_pixel_value(brightness, red),
alpha,
]);
buffer[y * WIDTH + x] = color;
}
else if i == 1 {
let rotated_x = translated_x * cos - translated_y * sin;
let rotated_y = translated_x * sin + translated_y * cos;
let mut color = get_color_new(&image2, rotated_y, rotated_x);
let [blue, green, red, alpha] = color.to_ne_bytes();
color = u32::from_ne_bytes([
set_pixel_value(brightness, blue),
set_pixel_value(brightness, green),
set_pixel_value(brightness, red),
alpha,
]);
buffer[y * WIDTH + x] = color;
}
}
}
}
// TODO: Everything together!
// Offset and rotate two superimposed images in opposite directions
} else {
// Optimized
// For optimization code can be combined here instead of the deduplication
// in the name of speed
}
// Show the buffer in the window
if ![0, 1].contains(&mode) {
window.update_with_buffer(&buffer, WIDTH as usize, HEIGHT as usize).unwrap();
}
// Display the FPS rate 3 times per second
let now = std::time::Instant::now();
let duration = (now - fps_time).as_secs_f32();
fps_count += 1;
if duration >= 0.33 {
println!("{} fps", (fps_count as f32 / duration).round() as u32);
fps_time = now;
fps_count = 0;
}
}
}
fn get_color(image: &Image, y: usize, x: usize) -> u32 {
let x1 = x.rem_euclid(image.width);
let y1 = y.rem_euclid(image.height);
let color = image.buffer[y1 * image.width + x1];
color
}
fn get_color_new(image: &Image, y: f32, x: f32) -> u32 {
let x1 = x.rem_euclid(image.width as f32) as usize;
let y1 = y.rem_euclid(image.height as f32) as usize;
let color = image.buffer[y1.rem_euclid(image.height) * image.width + x1];
color
}
async fn rotate_translucently(translated_x: f32, translated_y: f32, cos: f32, sin: f32, image: Image, brightness: f32,y: usize, buffer: Vec<u32>, x: usize){
let rotated_x: f32 = translated_x * cos + translated_y * sin;
let rotated_y: f32 = translated_x * sin - translated_y * cos;
let mut color: u32 = get_color_new(&image, rotated_y, rotated_x);
let [blue, green, red, alpha] = color.to_ne_bytes();
color = u32::from_ne_bytes([
set_pixel_value(brightness, blue),
set_pixel_value(brightness, green),
set_pixel_value(brightness, red),
alpha,
]);
buffer[y * WIDTH + x] = color; // cannot borrow `buffer` as mutable, as it is not declared as mutable
cannot borrow as mutable
}
lib.rs
pub fn blend_colors(mut color_1: u32, mut color_2: u32, brightness: f32) -> u32 {
color_1 = set_all_pixels_to_value(brightness, color_1);
let [blue_color_1, green_color_1, red_color_1, alpha_color_1] = color_1.to_ne_bytes();
color_2 = set_all_pixels_to_value(brightness, color_2);
let [blue_color_2, green_color_2, red_color_2, alpha_color_2] = color_2.to_ne_bytes();
let final_color = u32::from_ne_bytes([
((blue_color_1 as u16 + blue_color_2 as u16) / 2) as u8,
((green_color_1 as u16 + green_color_2 as u16) / 2) as u8,
((red_color_1 as u16 + red_color_2 as u16) / 2) as u8,
((alpha_color_1 as u16 + alpha_color_2 as u16) / 2) as u8,
]);
final_color
}
pub fn set_pixel_value(factor: f32, pixel_color: u8) -> u8 {
let pixel_color = (pixel_color as f32 * factor) as u8;
pixel_color
}
pub fn set_all_pixels_to_value(factor: f32, pixel: u32) -> u32 {
for value in pixel.to_ne_bytes() {
set_pixel_value(factor, value);
}
pixel
}
