| Crates.io | swizzler |
| lib.rs | swizzler |
| version | 0.1.0 |
| created_at | 2025-10-07 19:05:33.070008+00 |
| updated_at | 2025-10-07 19:05:33.070008+00 |
| description | Reorder values in a slice, for example to convert an image from BGRA to RGBA colors |
| homepage | |
| repository | https://codeberg.org/vilcans/swizzler |
| max_upload_size | |
| id | 1872356 |
| size | 8,653 |
Rust functions to create a copy of a slice, reordering the entries in the slice according to a pattern (swizzling).
Typical usage is converting pixel colors between different byte orderings
like RGBA or BGRA.
This crate also provides functions that provide the same functionality
but with names that signal intent better when doing color conversions:
[bgra_to_rgba] and [rgba_to_bgra].
Currently, swizzler only swizzles values in groups of four,
which is the common use case.
Other sizes shouldn't be difficult to add if there is a use case for it.
Add to your Cargo.toml:
[dependencies]
swizzler = "*" # or latest version
# Enable optimization in debug builds (see "Motivation" below)
[profile.dev.package.swizzler]
opt-level = 3
By default, only the feature u8 is implemented, which enables swizzling of bytes.
You may also want to enable the features u16 and u32 to enable swizzling those data types.
Swizzle in groups of 4 bytes, using order (2, 1, 0, 3):
let mut swizzled = [0u8; 8];
swizzler::u8::copy_2103(&[10, 11, 12, 13, 20, 21, 22, 23], &mut swizzled);
assert_eq!(swizzled, [12, 11, 10, 13, 22, 21, 20, 23]);
The copy_2103 copies
for each i divisable by 4.
Why this crate? The functionality is easy to implement, for example:
fn copy_2103<T: Copy>(src: &[T], dst: &mut [T]) {
let pattern_len = 4;
assert_eq!(src.len(), dst.len(), "src and dst need to be the same size");
assert!(
src.len().is_multiple_of(pattern_len),
"length must be divisable by {}, but is {}",
pattern_len,
src.len()
);
for i in 0..src.len() / pattern_len {
dst[i * pattern_len] = src[i * pattern_len + 2];
dst[i * pattern_len + 1] = src[i * pattern_len + 1];
dst[i * pattern_len + 2] = src[i * pattern_len];
dst[i * pattern_len + 3] = src[i * pattern_len + 3];
}
}
let mut swizzled = [0u8; 4];
copy_2103(&[10, 11, 12, 13], &mut swizzled);
assert_eq!(&swizzled, &[12, 11, 10, 13]);
My motivation for writing this crate is when code like the above took too long to run on a complete video frame. In release mode it was fast enough, but I wanted to run the code in debug mode during development. It is not possible to enable optimization on a section of code unless you put it in a separate crate. Therefore I made this crate.
swizzler is not heavily hand-optimized,
but the public functions are neither using generics nor macros,
so they will be compiled with optimization (if set up to be so in Cargo.toml, see above),
which was good enough for my case at least.
There are alternatives like image_swizzle which uses SIMD intrinsics if possible. For my case it was slow even if I enabled optimization for it because it uses macros and SIMD requires nightly.