image_texel/layout/
planar.rs1use crate::{
2 layout::{
3 AlignedOffset, Decay, Layout, Matrix, MatrixBytes, MismatchedPixelError, PlaneOf, Relocate,
4 SliceLayout, TexelLayout, TryMend,
5 },
6 texel::Texel,
7};
8
9use super::relocated::Relocated;
10
11#[derive(Clone)]
15pub struct Planes<Storage: ?Sized> {
16 inner: Storage,
17}
18
19impl<Storage> Planes<Storage> {
20 pub fn into_inner(self) -> Storage {
21 self.inner
22 }
23}
24
25impl<Pl, const N: usize> Planes<[Pl; N]>
26where
27 Pl: Layout,
28{
29 pub fn new(inner: [Pl; N]) -> Self {
30 Self { inner }
31 }
32
33 pub fn as_ref(&self) -> Planes<[&'_ Pl; N]> {
34 Planes {
35 inner: self.inner.each_ref(),
36 }
37 }
38
39 pub fn as_mut(&mut self) -> Planes<[&'_ mut Pl; N]> {
40 Planes {
41 inner: self.inner.each_mut(),
42 }
43 }
44}
45
46impl<Pl, const N: usize> Layout for Planes<[Pl; N]>
47where
48 Pl: Layout,
49{
50 fn byte_len(&self) -> usize {
51 let lengths: [usize; N] = self.inner.each_ref().map(|p| p.byte_len());
52 lengths.iter().copied().max().unwrap_or(0)
53 }
54}
55
56impl<Pl> Layout for Planes<[Pl]>
57where
58 Pl: Layout,
59{
60 fn byte_len(&self) -> usize {
61 let lengths = self.inner.iter().map(|p| p.byte_len());
62 lengths.max().unwrap_or(0)
63 }
64}
65
66impl<Pl, const N: usize> PlaneOf<Planes<[Pl; N]>> for usize
67where
68 Pl: Layout + Clone,
69{
70 type Plane = Pl;
71
72 fn get_plane(self, layout: &Planes<[Pl; N]>) -> Option<Self::Plane> {
73 layout.inner.get(self).cloned()
74 }
75}
76
77impl<Pl> PlaneOf<Planes<[Pl]>> for usize
78where
79 Pl: Layout + Clone,
80{
81 type Plane = Pl;
82
83 fn get_plane(self, layout: &Planes<[Pl]>) -> Option<Self::Plane> {
84 layout.inner.get(self).cloned()
85 }
86}
87
88#[derive(Clone)]
107pub struct PlaneBytes<const N: usize> {
108 planes: Planes<[Relocated<MatrixBytes>; N]>,
109}
110
111impl<const N: usize> PlaneBytes<N> {
112 pub fn new(inner: [MatrixBytes; N]) -> Self {
120 let mut inner = inner.map(Relocated::new);
121 let mut offset = AlignedOffset::default();
122
123 for plane in inner.iter_mut() {
124 plane.relocate(offset);
125 offset = plane.next_aligned_offset().expect("layout too large");
126 }
127
128 PlaneBytes {
129 planes: Planes::new(inner),
130 }
131 }
132
133 pub fn from_repeated(matrix: MatrixBytes) -> Self {
134 Self::new([matrix; N])
135 }
136
137 pub fn plane_ref(&self, idx: usize) -> Option<&Relocated<MatrixBytes>> {
139 self.planes.inner.get(idx)
140 }
141
142 #[must_use]
167 pub fn retain_coefficients_like(&self, texel: TexelLayout) -> Self {
168 let matrices = self.planes.inner.clone();
169 let inner = matrices.map(|plane| {
170 if plane.inner.element() == texel {
171 plane
172 } else {
173 Relocated {
174 offset: plane.offset,
175 inner: MatrixBytes::empty(texel),
176 }
177 }
178 });
179
180 PlaneBytes {
181 planes: Planes::new(inner),
182 }
183 }
184}
185
186impl<const N: usize> Layout for PlaneBytes<N> {
187 fn byte_len(&self) -> usize {
188 if N == 0 {
189 0
190 } else {
191 self.planes.inner[N - 1].byte_len()
193 }
194 }
195}
196
197impl<const N: usize> Relocate for PlaneBytes<N> {
198 fn byte_offset(&self) -> usize {
199 if N == 0 {
200 0
201 } else {
202 self.planes.inner[0].byte_len()
203 }
204 }
205
206 fn relocate(&mut self, mut offset: AlignedOffset) {
207 for plane in self.planes.inner.iter_mut() {
208 plane.relocate(offset);
209 offset = plane.next_aligned_offset().expect("layout too large");
210 }
211 }
212}
213
214impl<const N: usize> PlaneOf<PlaneBytes<N>> for usize {
215 type Plane = Relocated<MatrixBytes>;
216
217 fn get_plane(self, layout: &PlaneBytes<N>) -> Option<Self::Plane> {
218 layout.planes.inner.get(self).copied()
219 }
220}
221
222impl<T, const N: usize> TryMend<PlaneBytes<N>> for Texel<T> {
224 type Into = PlaneMatrices<T, N>;
225
226 type Err = MismatchedPixelError;
227
228 fn try_mend(self, from: &PlaneBytes<N>) -> Result<Self::Into, Self::Err> {
229 let planes = from.planes.inner.each_ref();
230
231 let mut results: [Result<_, MismatchedPixelError>; N] = planes.map(|plane| {
233 let matrix = self.try_mend(&plane.inner)?;
234 Ok(Relocated {
235 offset: plane.offset,
236 inner: matrix,
237 })
238 });
239
240 if let Some(err) = results.iter().position(|e| e.is_err()) {
241 let mut replacement = Ok(Relocated::new(Matrix::empty(self)));
242 core::mem::swap(&mut results[err], &mut replacement);
243
244 return Err(match replacement {
245 Err(err) => err,
246 Ok(_) => unreachable!(),
247 });
248 }
249
250 let inner = results.map(|res| res.unwrap());
252
253 Ok(PlaneMatrices {
254 planes: Planes::new(inner),
255 texel: self,
256 })
257 }
258}
259
260#[derive(Clone)]
291pub struct PlaneMatrices<T, const N: usize> {
292 planes: Planes<[Relocated<Matrix<T>>; N]>,
293 texel: Texel<T>,
294}
295
296impl<T, const N: usize> PlaneMatrices<T, N> {
297 pub fn new(texel: Texel<T>, inner: [Matrix<T>; N]) -> Self {
305 use crate::layout::{Decay, TryMend};
306 let bytes = inner.each_ref().map(|m| MatrixBytes::decay(m));
307 let planes = PlaneBytes::new(bytes);
308 texel
309 .try_mend(&planes)
310 .expect("input matrices have this texel")
311 }
312
313 pub fn from_repeated(matrix: Matrix<T>) -> Self {
314 let texel = matrix.pixel();
315 Self::new(texel, [matrix; N])
316 }
317
318 pub fn plane_ref(&self, idx: usize) -> Option<&Relocated<Matrix<T>>> {
320 self.planes.inner.get(idx)
321 }
322}
323
324impl<T, const N: usize> PlaneOf<PlaneMatrices<T, N>> for usize {
325 type Plane = Relocated<Matrix<T>>;
326
327 fn get_plane(self, layout: &PlaneMatrices<T, N>) -> Option<Self::Plane> {
328 layout.planes.inner.get(self).copied()
329 }
330}
331
332impl<T, const N: usize> Layout for PlaneMatrices<T, N> {
333 fn byte_len(&self) -> usize {
334 if N == 0 {
335 0
336 } else {
337 self.planes.inner[N - 1].byte_len()
339 }
340 }
341}
342
343impl<T, const N: usize> SliceLayout for PlaneMatrices<T, N> {
344 type Sample = T;
345
346 fn sample(&self) -> Texel<Self::Sample> {
347 self.texel
348 }
349}
350
351impl<T, const N: usize> Decay<PlaneMatrices<T, N>> for PlaneBytes<N> {
352 fn decay(from: PlaneMatrices<T, N>) -> PlaneBytes<N> {
353 let bytes = from.planes.inner.each_ref().map(|rel| Relocated {
354 offset: rel.offset,
355 inner: MatrixBytes::decay(&rel.inner),
356 });
357
358 PlaneBytes {
359 planes: Planes::new(bytes),
360 }
361 }
362}