# Rotate super-imposed images over each other

**URL:** <https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599>\
**Category:** help\
**Created:** [September 24, 2026, 10:22am UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599 "2026-09-24T10:22:21Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![canina](https://avatars.discourse-cdn.com/v4/letter/c/8e7dd6/32.png) [@canina](https://users.rust-lang.org/u/canina)\
**Post date:** [September 24, 2026, 10:22am UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/1 "2026-09-24T10:22:21Z")

</div>

**A better explanation is here: [Rotate super-imposed images over each other - #4 by canina](https://users.rust-lang.org/t/implenting-async-correctly/142599/4)**

I have to use `async` to rotate two images over each other translucently. When trying myself I assumed I needed a big function like.

```rust
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**

> ****
>
> ```rust
> 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**

> ****
>
> ```rust
> 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
> }
> 
> ```

---

<div class="post-metadata">

**Author:** ![Anlis](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/anlis/32/53804_2.png) [@Anlis](https://users.rust-lang.org/u/Anlis)\
**Post date:** [September 24, 2026, 10:43am UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/2 "2026-09-24T10:43:08Z")

</div>

I don’t really get why you need async here? All your code seems to be synchronous, am I missing something?

---

<div class="post-metadata">

**Author:** ![nerditation](https://avatars.discourse-cdn.com/v4/letter/n/e79b87/32.png) [@nerditation](https://users.rust-lang.org/u/nerditation)\
**Post date:** [September 24, 2026, 10:47am UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/3 "2026-09-24T10:47:41Z")

</div>

first of all, do you understand what the `async` keyword in rust is used for? I don't know why you want `async`, but it's completely irrelevant for an image operation.

now, on the image operation: you are conflating two different operations: rotation and blending. you can rotate an image clockwise, or counter-clockwise, or you can rotate by some angle, but there's no such thing as "rotate **translucently**".

I think you should understand the problem clearly and clarify the correct concepts and terminologies before writing the actual code.

---

<div class="post-metadata">

**Author:** ![canina](https://avatars.discourse-cdn.com/v4/letter/c/8e7dd6/32.png) [@canina](https://users.rust-lang.org/u/canina)\
**Post date:** [September 24, 2026, 11:00am UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/4 "2026-09-24T11:00:00Z")

</div>

I want to rotate to images at the same time in a different direction over each other. As shown in the image below. I don't think this can be done synchronously, because I need to modfiy the buffer per pixel.

> ****
>
> ![image](https://us1.discourse-cdn.com/flex019/uploads/rust_lang/original/3X/e/b/eba9c07f1298c00f5f2535de6202ca1e514e155c.jpeg)

@nerditation I could have made my isssue a bit clearer, sorry for the confusion. With rotating translucently I meant that I decreased the brightness of all the pixels, so that you can see both images at the same time. The issue is specifically about mode 4 by the way. You can ignore all the other modes. Hopefully this clarifies it a bit.

---

<div class="post-metadata">

**Author:** ![mroth](https://avatars.discourse-cdn.com/v4/letter/m/a8b319/32.png) [@mroth](https://users.rust-lang.org/u/mroth)\
**Post date:** [September 24, 2026, 12:37pm UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/5 "2026-09-24T12:37:38Z")

</div>

`async` is (mainly) for _IO_. IO means: Waiting for data receiving from a network connection, or waiting until the operating system has written data to the disk, or waiting for the user to move the mouse and so on.

But you have to _compute_ your final image, you don't have to wait for something to happen.

> [@canina](#):
>
> I want to rotate to images at the same time in a different direction over each other. As shown in the image below. I don't think this can be done synchronously, because I need to modfiy the buffer per pixel.

Ignoring multiple CPU cores, absolute nothing happens in a computer at the same time (conceptually). All steps are purely sequential. It might be, that these steps are so fast, that it looks like they happen parallel. But this is an illusion.

For your image rotation,this is something like this:

```rust
let orig_image_a = ...;
let orig_image_b = ...;

let temporary_buffer_a = rotate(orig_image_a, angle_a);
let temporary_buffer_b = rotate(orig_image_b, angle_b);

let result_buffer = blend_together(temporary_buffer_a, temporary_buffer_b);

```

---

<div class="post-metadata">

**Author:** ![nerditation](https://avatars.discourse-cdn.com/v4/letter/n/e79b87/32.png) [@nerditation](https://users.rust-lang.org/u/nerditation)\
**Post date:** [September 24, 2026, 1:04pm UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/6 "2026-09-24T13:04:39Z")

</div>

> [@canina](#):
>
> I don't think this can be done synchronously, because I need to modfiy the buffer per pixel.

do you mean you want to return a new image instead of modifying the pixels of the old image? what you need is a heap allocation for the buffer, that's nothing to do with `async`.

you can either clone the buffer of an old image, or allocate a new buffer initialized with zeros. which is more efficient depending on the algorithm you perform.

please learn and understand the concept before trying to use a feature, use terminologies properly. the term "synchronously" has a specific definition in programming languages, don't just guess what a keyword (such as `async`) means.

> [@canina](#):
>
> With rotating translucently I meant that I decreased the brightness of all the pixels, so that you can see both images at the same time.

again, that's two different things, the rotation only cares about the angle (and maybe the pivot if your origin has been translated), and the translucency is a property of the composition.

you can perform a rotation followed by an alpha blending, in two separate steps, that's fine, just don't call it `rotate_translucently`, that name is gibberish. use proper names in code, if you want it to be understandable by human.

---

<div class="post-metadata">

**Author:** ![Anlis](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/anlis/32/53804_2.png) [@Anlis](https://users.rust-lang.org/u/Anlis)\
**Post date:** [September 24, 2026, 1:33pm UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/7 "2026-09-24T13:33:09Z")

</div>

Honestly, I don't really understand what's your question about then. I mentioned in your code, that you're trying to set value in buffer from a function and it doesn't compile. To solve this one specifically, you could just return a color you calculated from this function and set it in your main function or elsewhere the buffer is in scope.

But also I'd like to say, that it looks like you're trying to solve quite complex task from the start. I'd like to recommend you to read [rustbook](https://doc.rust-lang.org/book/) thoroughly, it's an excellent starting point where you can find really good explanations how to write your code without compilation errors, what is asynchronous code and where it makes sense to use it, it also has some example projects. I believe it can improve your skill and the code you write significantly.

---

<div class="post-metadata">

**Author:** ![canina](https://avatars.discourse-cdn.com/v4/letter/c/8e7dd6/32.png) [@canina](https://users.rust-lang.org/u/canina)\
**Post date:** [September 25, 2026, 11:58am UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/8 "2026-09-25T11:58:20Z")

</div>

Performance can be improved obviously, but it works fine.

```rust
let brightness: f32 = 0.5;
            let cos = rotation.cos();
            let sin = rotation.sin();
            
            for x in 0..HEIGHT {
                for y in 0..WIDTH {
                    let translated_x_image = x as f32 - x_offset as f32;
                    let translated_y_image = y as f32 - y_offset as f32;
                    
                    // Position image1
                    let rotated_x_image1 = translated_x_image * cos + translated_y_image * sin;
                    let rotated_y_image1 = translated_x_image * sin - translated_y_image * cos;
                    
                    // Position image2
                    let rotated_x_image2 = translated_x_image * cos - translated_y_image * sin;
                    let rotated_y_image2 = translated_x_image * sin + translated_y_image * cos;
                    
                    // Set brightness for colors
                    let color1 = get_color_new(&image1, rotated_y_image1, rotated_x_image1);
                    let color2 = get_color_new(&image2, rotated_y_image2, rotated_x_image2);
                    let final_color = blend_colors(color1, color2, brightness);
                    buffer[y * WIDTH + x] = final_color;
                }
            }

```

Edit: nevermind it crashes after a while:

```rust
thread 'main' (121476) panicked at src/main.rs:256:29:
index out of bounds: the len is 225920 but the index is 225920
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: queue 0x5721ccca73e0 destroyed while proxies still attached:
  wl_buffer#19 still attached
  wl_shm_pool#18 still attached
  wl_buffer#17 still attached
  wl_shm_pool#16 still attached
  wl_surface#15 still attached
  wl_shm_pool#14 still attached
  xdg_toplevel#13 still attached
  xdg_surface#12 still attached
  xdg_wm_base#11 still attached
  wl_buffer#10 still attached
  wl_shm_pool#9 still attached
  wl_surface#8 still attached
  wl_shm#7 still attached
  wl_compositor#6 still attached
  wl_pointer#5 still attached
  wl_keyboard#4 still attached
  wl_seat#3 still attached
  wl_registry#2 still attached

```

---

<div class="post-metadata">

**Author:** ![mroth](https://avatars.discourse-cdn.com/v4/letter/m/a8b319/32.png) [@mroth](https://users.rust-lang.org/u/mroth)\
**Post date:** [September 25, 2026, 8:17pm UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/9 "2026-09-25T20:17:59Z")

</div>

> [@canina](#):
>
> ```rust
> thread 'main' (121476) panicked at src/main.rs:256:29:
> index out of bounds: the len is 225920 but the index is 225920
> 
> ```

What is the source code in line 256 at your `main.rs`?

Maybe you have a classic [Off-by-one error - Wikipedia](https://en.wikipedia.org/wiki/Off-by-one_error) ?

---

<div class="post-metadata">

**Author:** ![canina](https://avatars.discourse-cdn.com/v4/letter/c/8e7dd6/32.png) [@canina](https://users.rust-lang.org/u/canina)\
**Post date:** [September 25, 2026, 9:33pm UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/10 "2026-09-25T21:33:06Z")

</div>

**Full code main.rs**

> ****
>
> ```rust
> 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;
> 
> // Custom added constants
> let x_offset: f32 = WIDTH as f32 / 2 as f32;
> let y_offset: f32 = HEIGHT as f32 / 2 as f32;
> let brightness: f32 = 0.5;
>     
> // 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 {
> let cos: f32 = rotation.cos();
> let sin: f32 = rotation.sin();
> // TODO: Offset and rotate image 1
> for x in 0..HEIGHT {
> for y in 0..WIDTH {
> let translated_x = x as f32 - x_offset;
> let translated_y = y as f32 - y_offset;
> 
> let rotated_x = translated_x * cos + translated_y * sin;
> let rotated_y = translated_x * sin - translated_y * cos;
> 
> let color = get_color_with_float_coordinates(&image1, rotated_y, rotated_x);
> buffer[y * WIDTH + x] = color;
> }
> }
> } else if mode == 4 {
> // Offset and rotate two superimposed images in opposite directions
> let cos: f32 = rotation.cos();
> let sin: f32 = rotation.sin();
> 
> for x in 0..HEIGHT {
> let translated_x_image = x as f32 - x_offset;
> 
> for y in 0..WIDTH {
> let translated_y_image = y as f32 - y_offset;
> 
> // Position image1
> let rotated_x_image1 = translated_x_image * cos + translated_y_image * sin;
> let rotated_y_image1 = translated_x_image * sin - translated_y_image * cos;
> 
> // Position image2
> let rotated_x_image2 = translated_x_image * cos - translated_y_image * sin;
> let rotated_y_image2 = translated_x_image * sin + translated_y_image * cos;
> 
> // Set brightness for colors
> let color1 = get_color_with_float_coordinates(&image1, rotated_y_image1, rotated_x_image1);
> let color2 = get_color_with_float_coordinates(&image2, rotated_y_image2, rotated_x_image2);
> let final_color = blend_colors(color1, color2, brightness);
> buffer[y * WIDTH + x] = final_color;
> }
> }
> } else if mode == 5 {
> // Optimized
> // For optimization code can be combined here instead of the deduplication
> // in the name of speed
> let cos: f32 = rotation.cos();
> let sin: f32 = rotation.sin();
>             
> for x in 0..900 {
> let translated_x_image = x as f32 - x_offset;
> let translated_x_image_cos = translated_x_image * cos;
> let translated_x_image_sin = translated_x_image * sin;
> 
> for y in 0..900 {
> let translated_y_image = y as f32 - y_offset;
> 
> let translated_y_image_cos = translated_y_image * cos;
> let translated_y_image_sin = translated_y_image * sin;
> 
> let final_color = {
> let mut color_1 = image1.buffer[
> ((translated_x_image_sin - translated_y_image_cos).rem_euclid(image1.height as f32) as usize).rem_euclid(image1.height)
> * image1.width
> + (translated_x_image_cos + translated_y_image_sin).rem_euclid(image1.width as f32) as usize
> ];
> let mut color_2 = image2.buffer[
> ((translated_x_image_sin + translated_y_image_cos).rem_euclid(image2.height as f32) as usize).rem_euclid(image2.height)
> * image2.width
> + (translated_x_image_cos - translated_y_image_sin).rem_euclid(image2.width as f32) as usize
> ];
> 
> color_1 = {
> for value in color_1.to_ne_bytes() {
> {
> (value as f32 * 0.5) as u8;
> };
> }
> color_1
> };
> let [blue_color_1, green_color_1, red_color_1, alpha_color_1] = color_1.to_ne_bytes();
> 
> color_2 = {
> for value in color_2.to_ne_bytes() {
> {
> (value as f32 * 0.5) as u8;
> };
> }
> 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
> };
> buffer[y * 900 + x] = final_color;
> }
> }
> }
> 
> // 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_with_float_coordinates(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
> }
> 
> ```

**Output**

> ****
>
> ```rust
> hread 'main' (19885) panicked at src/main.rs:241:29:
> index out of bounds: the len is 225920 but the index is 225920
> note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
> warning: queue 0x5be7cb5e23e0 destroyed while proxies still attached:
> wl_buffer#20 still attached
> wl_buffer#19 still attached
> wl_shm_pool#18 still attached
> wl_buffer#17 still attached
> wl_shm_pool#16 still attached
> wl_surface#15 still attached
> wl_shm_pool#14 still attached
> xdg_toplevel#13 still attached
> xdg_surface#12 still attached
> xdg_wm_base#11 still attached
> wl_buffer#10 still attached
> wl_shm_pool#9 still attached
> wl_surface#8 still attached
> wl_shm#7 still attached
> wl_compositor#6 still attached
> wl_pointer#5 still attached
> wl_keyboard#4 still attached
> wl_seat#3 still attached
> wl_registry#2 still attached
> 
> ```

The `lib.rs` is unchanged. Thank you for offering help btw!

---

<div class="post-metadata">

**Author:** ![mroth](https://avatars.discourse-cdn.com/v4/letter/m/a8b319/32.png) [@mroth](https://users.rust-lang.org/u/mroth)\
**Post date:** [September 26, 2026, 10:47am UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/11 "2026-09-26T10:47:59Z")

</div>

You have floating point rounding issues:

```rust
let rotated_x_image1 = translated_x_image * cos + translated_y_image * sin;
let rotated_y_image1 = translated_x_image * sin - translated_y_image * cos;

let rotated_x_image2 = translated_x_image * cos - translated_y_image * sin;
let rotated_y_image2 = translated_x_image * sin + translated_y_image * cos;

let color1 = get_color_with_float_coordinates(&image1, rotated_y_image1, rotated_x_image1);

// ...

fn get_color_with_float_coordinates(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
}

```

Quote from: [f32.rem\_euclid](https://doc.rust-lang.org/std/primitive.f32.html#method.rem_euclid)

> In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in most cases. However, **due to a floating point round-off error it can result in `r == rhs.abs()`, violating the mathematical definition**, if `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.

Floating point numbers are always only an approximation. You have to anticipate errors when working with floats. Adding and especially subtracting floats introduce often relatively huge errors.

A quick fix for your use case might be:

```rust
let x1 = (x.rem_euclid(image.width as f32) as usize).clamp(0, image.width - 1);
let y1 = (y.rem_euclid(image.height as f32) as usize).clamp(0, image.height - 1);

```

Please note the important `-1`...

---

<div class="post-metadata">

**Author:** ![canina](https://avatars.discourse-cdn.com/v4/letter/c/8e7dd6/32.png) [@canina](https://users.rust-lang.org/u/canina)\
**Post date:** [September 26, 2026, 6:06pm UTC](https://users.rust-lang.org/t/rotate-super-imposed-images-over-each-other/142599/12 "2026-09-26T18:06:44Z")

</div>

Thank you that makes sense, and it worked for me!
