1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
//! # garb
//!
//! *Dress your pixels for the occasion.*
//!
//! You can't show up to a function in the wrong style. Swap your BGR for your RGB, your ARGB for your RGBA, and tie up loose
//! ends like that unreliable alpha BGRX.
//!
//! SIMD-optimized pixel format conversions for row-level and whole-image
//! operations. Supports x86-64 AVX2, ARM NEON, and WASM SIMD128 with
//! automatic fallback to scalar code.
//!
//! ## Modules
//!
//! - [`bytes`] — Core `&[u8]` conversions (contiguous and strided).
//! - [`typed_rgb`] — Type-safe wrappers using `rgb` crate pixel types (feature `rgb`).
//! - [`imgref`] — Whole-image conversions on `ImgVec` / `ImgRef` (feature `imgref`).
//!
//! ## Naming convention
//!
//! All functions follow the pattern `{src}_to_{dst}` for copy operations and
//! `{src}_to_{dst}_inplace` for in-place mutations. Append `_strided` for
//! multi-row buffers with stride.
//!
//! ## Strides
//!
//! A **stride** (also called "pitch" or "row pitch") is the distance between
//! the start of one row and the start of the next, measured in units of the
//! slice's element type:
//!
//! - For `&[u8]` functions: stride is in **bytes**.
//! - For typed APIs (`imgref`, `typed_rgb`): stride is in **elements** of the
//! slice's item type — e.g. pixel count for `ImgRef<Rgba<u8>>`, but byte
//! count for `ImgRef<u8>`.
//!
//! When `stride == width` (in the appropriate unit) the image is contiguous.
//! When `stride > width` the gap at the end of each row is padding — garb
//! never reads or writes it.
//!
//! The required buffer length (in elements) for a strided image is:
//! `(height - 1) * stride + width`
//!
//! All `_strided` functions take dimensions *before* strides:
//! - In-place: `(buf, width, height, stride)`
//! - Copy: `(src, dst, width, height, src_stride, dst_stride)`
//!
//! ## Feature flags
//!
//! - **`std`** — Enables `std` on dependencies (e.g. `archmage`).
//! - **`experimental`** — Gray layout, weighted luma, depth conversion, f32
//! alpha premultiply/unpremultiply. API may change between minor versions.
//! - **`rgb`** — Type-safe conversions using [`rgb`] crate pixel types
//! via bytemuck. Zero-copy in-place swaps return reinterpreted references.
//! - **`imgref`** — Multi-row conversions using `ImgRef` / `ImgRefMut`
//! from the [`imgref`](https://docs.rs/imgref) crate. No allocation — caller owns all buffers.
extern crate alloc;
/// Pixel buffer size or alignment error.
///
/// Returned when a buffer's length is not a multiple of the pixel size,
/// a destination buffer is too small, or stride/dimensions are inconsistent.
// ===========================================================================
// Generic conversion traits
// ===========================================================================
/// Copy-convert a pixel slice: `&[Src]` → `&mut [Dst]`.
///
/// Implemented for every valid `(Src, Dst)` pair when `feature = "rgb"`.
/// Use [`convert`] for the free-function form.
/// In-place pixel conversion: `&mut [Src]` → `&mut [Dst]` (same pixel size).
///
/// Only implemented for same-size pixel pairs (e.g. 4bpp↔4bpp, 3bpp↔3bpp).
/// Use [`convert_inplace`] for the free-function form.
/// Copy-convert pixel slices. Type inference selects the right conversion.
///
/// ```rust
/// use rgb::{Rgb, Bgra};
/// use garb::convert;
///
/// let rgb = vec![Rgb::new(255u8, 0, 128); 2];
/// let mut bgra = vec![Bgra::default(); 2];
/// convert(&rgb, &mut bgra).unwrap();
/// assert_eq!(bgra[0], Bgra { b: 128, g: 0, r: 255, a: 255 });
/// ```
/// In-place pixel conversion. Returns the buffer reinterpreted as the target type.
///
/// ```rust
/// use rgb::{Rgba, Bgra};
/// use garb::convert_inplace;
///
/// let mut pixels = vec![Rgba::new(255u8, 0, 128, 255); 2];
/// let bgra: &mut [Bgra<u8>] = convert_inplace(&mut pixels);
/// assert_eq!(bgra[0], Bgra { b: 128, g: 0, r: 255, a: 255 });
/// ```
/// Copy-convert an image: `ImgRef<Src>` → `ImgRefMut<Dst>`.
///
/// Implemented for every valid `(Src, Dst)` pair when `feature = "imgref"`.
/// Use [`convert_imgref`] for the free-function form.
/// In-place image conversion: consumes `ImgVec<Src>`, returns `ImgVec<Dst>`.
///
/// Only implemented for same-size pixel pairs.
/// Use [`convert_imgref_inplace`] for the free-function form.
/// Copy-convert an image. Type inference selects the right conversion.
///
/// ```rust
/// use rgb::{Rgb, Bgra};
/// use imgref::{ImgVec, ImgRefMut};
/// use garb::convert_imgref;
///
/// let src = ImgVec::new(vec![Rgb::new(255u8, 0, 128); 4], 2, 2);
/// let mut dst_buf = vec![Bgra::default(); 4];
/// let dst = ImgRefMut::new(&mut dst_buf, 2, 2);
/// convert_imgref(src.as_ref(), dst).unwrap();
/// ```
/// In-place image conversion. Consumes and returns the image with reinterpreted pixels.
///
/// ```rust
/// use rgb::{Rgba, Bgra};
/// use imgref::ImgVec;
/// use garb::convert_imgref_inplace;
///
/// let img = ImgVec::new(vec![Rgba::new(255u8, 0, 128, 200); 4], 2, 2);
/// let bgra_img: ImgVec<Bgra<u8>> = convert_imgref_inplace(img);
/// ```