How to concatenate integers?

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| {
                    
                    // println!("{:?}", color);
                    // Is --> Rgba { r: 188, g: 147, b: 129, a: 255 }
                    // Should be --> u32
                    
                    let b = color.b;
                    let g = color.g;
                    let r = color.r;
                    let a = color.a;
                    let value = format!("{b}{g}{r}{a}");
                    // return  0x11223344;
                    return value as u32;
                })
                .collect(),
        }
    }
}

How can I concatenate the integer values and convert the string back to u32?

If you have 4 bytes (r, g, b and a), you can combine them way more efficiently into one u32 by using u32::from_[le|ne|be]_bytes instead of serialising them to and from a UTF-8 string.

Thank you, that was exactly what I needed!

For the sake of completeness, manually you’d do it using bit operations like this:

// given the u8’s r, g, b, a

let val = b as u32 << 24 | g as u32 << 16 | r as u32 << 8 | a as u32;

which gives 0xBBGGRRAA, with the advantage that you don’t have to worry about endianess.

you do have to care about endianess. it's just expressed in a different way.

with bit twiddling, the endianess is encoded in the formula directly, while with the u32::from_xx_bytes(), this information was in the name of the function and the sequence of the components of the array.

for example, these 3 are equivalent:

// the shift amounts for the component `b, g, r, a` in this order `24, 16, 8, 0` 
let val = b as u32 << 24 | g as u32 << 16 | r as u32 << 8 | a as u32 << 0;
// equivalent to `[b, g, r, a]` in "big" endian
let val = u32::from_be_bytes([b, g, r, a]);
// which is equivalent to `[a, r, g, b]` in "little" endian
let val = u32::from_le_bytes([a, r, g, b]);

while these 3 are equivalent, with opposite endianess of the above:

// `b, g, r, a` ordered in 0, 8, 16, 24 
let val = b as u32 << 0 | g as u32 << 8 | r as u32 << 16 | a as u32 << 24;
// so, `[b, g, r, a]` in "little" endian
let val = u32::from_le_bytes([b, g, r, a]);
// the reverse
let val = u32::from_be_bytes([a, r, g, b]);

To answer your original question: this is how you do it with string concatenation and parsing

u32::from_str_radix(&format!("{b:02X}{g:02X}{r:02X}{a:02X}"), 16).unwrap()

it formats the bytes as two digit hex each and parses the concatenated string as a base 16 number. This is ofc less efficient and less readable than the accepted proper solution.

If you really have four integers of u8 and you want to combine them to a u32, then
a + b * 256 + c * 256 * 256 + d * 256 * 256 * 256
which doesn't have any knowledge of representation or endianess, but colors are not really numbers (integers), so I think previous answers are better here.

Typo or intended?

Whoops. Typo. Corrected.

This is precisely what the function u32::from_le_bytes([a, b, c, d]) does. Your formula defines what "little-endian" means.