1use core::fmt::{Debug, Formatter};
3use core::marker::PhantomData;
4use core::mem::size_of;
5use core::slice;
6
7#[allow(unused_imports)]
8use crate::compat::*;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12#[non_exhaustive]
13pub enum PixelType {
14 U8,
15 U8x2,
16 U8x3,
17 U8x4,
18 U16,
19 U16x2,
20 U16x3,
21 U16x4,
22 I32,
23 F32,
24 F32x2,
25 F32x3,
26 F32x4,
27}
28
29impl PixelType {
30 pub fn size(&self) -> usize {
32 match self {
33 Self::U8 => 1,
34 Self::U8x2 => 2,
35 Self::U8x3 => 3,
36 Self::U16 => 2,
37 Self::U16x2 => 4,
38 Self::U16x3 => 6,
39 Self::U16x4 => 8,
40 Self::F32x2 => 8,
41 Self::F32x3 => 12,
42 Self::F32x4 => 16,
43 _ => 4,
44 }
45 }
46
47 pub(crate) fn is_aligned(&self, buffer: &[u8]) -> bool {
49 match self {
50 Self::U8 => true,
51 Self::U8x2 => unsafe { buffer.align_to::<U8x2>().0.is_empty() },
52 Self::U8x3 => unsafe { buffer.align_to::<U8x3>().0.is_empty() },
53 Self::U8x4 => unsafe { buffer.align_to::<U8x4>().0.is_empty() },
54 Self::U16 => unsafe { buffer.align_to::<U16>().0.is_empty() },
55 Self::U16x2 => unsafe { buffer.align_to::<U16x2>().0.is_empty() },
56 Self::U16x3 => unsafe { buffer.align_to::<U16x3>().0.is_empty() },
57 Self::U16x4 => unsafe { buffer.align_to::<U16x4>().0.is_empty() },
58 Self::I32 => unsafe { buffer.align_to::<I32>().0.is_empty() },
59 Self::F32 => unsafe { buffer.align_to::<F32>().0.is_empty() },
60 Self::F32x2 => unsafe { buffer.align_to::<F32x2>().0.is_empty() },
61 Self::F32x3 => unsafe { buffer.align_to::<F32x3>().0.is_empty() },
62 Self::F32x4 => unsafe { buffer.align_to::<F32x4>().0.is_empty() },
63 }
64 }
65}
66
67pub trait GetCount {
68 fn count() -> usize;
69}
70
71pub struct Count<const N: usize>;
73
74impl<const N: usize> GetCount for Count<N> {
75 #[inline(always)]
76 fn count() -> usize {
77 N
78 }
79}
80
81pub trait GetCountOfValues {
82 fn count_of_values() -> usize;
83}
84
85pub struct Values<const N: usize>;
87
88impl<const N: usize> GetCountOfValues for Values<N> {
89 fn count_of_values() -> usize {
90 N
91 }
92}
93
94pub trait PixelComponent
96where
97 Self: Sized + Copy + Debug + PartialEq + 'static,
98{
99 type CountOfComponentValues: GetCountOfValues;
102
103 fn count_of_values() -> usize {
105 Self::CountOfComponentValues::count_of_values()
106 }
107}
108
109impl PixelComponent for u8 {
110 type CountOfComponentValues = Values<0x100>;
111}
112
113impl PixelComponent for u16 {
114 type CountOfComponentValues = Values<0x10000>;
115}
116
117impl PixelComponent for i32 {
118 type CountOfComponentValues = Values<0>;
119}
120
121impl PixelComponent for f32 {
122 type CountOfComponentValues = Values<0>;
123}
124
125mod private {
127 pub trait Sealed {}
128}
129
130pub trait InnerPixel:
137 private::Sealed + Copy + Clone + Sized + Debug + PartialEq + Default + Send + Sync + 'static
138{
139 type Component: PixelComponent;
141 type CountOfComponents: GetCount;
143
144 fn pixel_type() -> PixelType;
145
146 fn count_of_components() -> usize {
148 Self::CountOfComponents::count()
149 }
150
151 fn count_of_component_values() -> usize {
153 Self::Component::count_of_values()
154 }
155
156 fn components_is_u8() -> bool {
157 Self::count_of_component_values() == 256
158 }
159
160 fn size() -> usize {
170 size_of::<Self>()
171 }
172
173 fn components(buf: &[Self]) -> &[Self::Component] {
175 let size = buf.len() * Self::count_of_components();
176 let components_ptr = buf.as_ptr() as *const Self::Component;
177 unsafe { slice::from_raw_parts(components_ptr, size) }
178 }
179
180 fn components_mut(buf: &mut [Self]) -> &mut [Self::Component] {
182 let size = buf.len() * Self::count_of_components();
183 let components_ptr = buf.as_mut_ptr() as *mut Self::Component;
184 unsafe { slice::from_raw_parts_mut(components_ptr, size) }
185 }
186
187 fn empty() -> Self {
189 Self::default()
190 }
191}
192
193#[derive(Copy, Clone, PartialEq, Default)]
195#[repr(C)]
196pub struct Pixel<T: Default, C, const COUNT_OF_COMPONENTS: usize>(
197 pub T,
198 PhantomData<[C; COUNT_OF_COMPONENTS]>,
199)
200where
201 T: Sized + Copy + Clone + PartialEq + 'static,
202 C: PixelComponent;
203
204impl<T, C, const COUNT_OF_COMPONENTS: usize> Pixel<T, C, COUNT_OF_COMPONENTS>
205where
206 T: Sized + Copy + Clone + PartialEq + Default + 'static,
207 C: PixelComponent,
208{
209 #[inline(always)]
210 pub const fn new(v: T) -> Self {
211 Self(v, PhantomData)
212 }
213}
214
215#[cfg(feature = "bytemuck")]
220unsafe impl<T: bytemuck::Zeroable, C, const COUNT_OF_COMPONENTS: usize> bytemuck::Zeroable
221 for Pixel<T, C, COUNT_OF_COMPONENTS>
222where
223 T: Sized + Copy + Clone + PartialEq + Default + 'static,
224 C: PixelComponent,
225{
226}
227
228#[cfg(feature = "bytemuck")]
230unsafe impl<T: bytemuck::Pod, C, const COUNT_OF_COMPONENTS: usize> bytemuck::Pod
231 for Pixel<T, C, COUNT_OF_COMPONENTS>
232where
233 T: Sized + Copy + Clone + PartialEq + Default + 'static,
234 C: PixelComponent,
235{
236}
237
238macro_rules! pixel_struct {
239 ($name:ident, $type:tt, $comp_type:tt, $comp_count:literal, $pixel_type:expr, $doc:expr) => {
240 #[doc = $doc]
241 pub type $name = Pixel<$type, $comp_type, $comp_count>;
242
243 impl private::Sealed for $name {}
244
245 impl InnerPixel for $name {
246 type Component = $comp_type;
247 type CountOfComponents = Count<$comp_count>;
248
249 fn pixel_type() -> PixelType {
250 $pixel_type
251 }
252 }
253
254 impl Debug for $name {
255 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
256 let components_ptr = self as *const _ as *const $comp_type;
257 let components: &[$comp_type] =
258 unsafe { slice::from_raw_parts(components_ptr, $comp_count) };
259 write!(f, "{}{:?}", stringify!($name), components)
260 }
261 }
262 };
263}
264
265pixel_struct!(U8, u8, u8, 1, PixelType::U8, "One byte per pixel (e.g. L8)");
266pixel_struct!(
267 U8x2,
268 [u8; 2],
269 u8,
270 2,
271 PixelType::U8x2,
272 "Two bytes per pixel (e.g. LA8)"
273);
274pixel_struct!(
275 U8x3,
276 [u8; 3],
277 u8,
278 3,
279 PixelType::U8x3,
280 "Three bytes per pixel (e.g. RGB8)"
281);
282pixel_struct!(
283 U8x4,
284 [u8; 4],
285 u8,
286 4,
287 PixelType::U8x4,
288 "Four bytes per pixel (RGBA8, RGBx8, CMYK8 and other)"
289);
290pixel_struct!(
291 U16,
292 u16,
293 u16,
294 1,
295 PixelType::U16,
296 "One `u16` component per pixel (e.g. L16)"
297);
298pixel_struct!(
299 U16x2,
300 [u16; 2],
301 u16,
302 2,
303 PixelType::U16x2,
304 "Two `u16` components per pixel (e.g. LA16)"
305);
306pixel_struct!(
307 U16x3,
308 [u16; 3],
309 u16,
310 3,
311 PixelType::U16x3,
312 "Three `u16` components per pixel (e.g. RGB16)"
313);
314pixel_struct!(
315 U16x4,
316 [u16; 4],
317 u16,
318 4,
319 PixelType::U16x4,
320 "Four `u16` components per pixel (e.g. RGBA16)"
321);
322pixel_struct!(
323 I32,
324 i32,
325 i32,
326 1,
327 PixelType::I32,
328 "One `i32` component per pixel"
329);
330pixel_struct!(
331 F32,
332 f32,
333 f32,
334 1,
335 PixelType::F32,
336 "One `f32` component per pixel"
337);
338pixel_struct!(
339 F32x2,
340 [f32; 2],
341 f32,
342 2,
343 PixelType::F32x2,
344 "Two `f32` component per pixel (e.g. LA32F)"
345);
346pixel_struct!(
347 F32x3,
348 [f32; 3],
349 f32,
350 3,
351 PixelType::F32x3,
352 "Three `f32` components per pixel (e.g. RGB32F)"
353);
354pixel_struct!(
355 F32x4,
356 [f32; 4],
357 f32,
358 4,
359 PixelType::F32x4,
360 "Four `f32` components per pixel (e.g. RGBA32F)"
361);
362
363pub trait IntoPixelComponent<Out: PixelComponent>
364where
365 Self: PixelComponent,
366{
367 fn into_component(self) -> Out;
368}
369
370impl<C: PixelComponent> IntoPixelComponent<C> for C {
371 fn into_component(self) -> C {
372 self
373 }
374}
375
376impl IntoPixelComponent<u16> for u8 {
379 fn into_component(self) -> u16 {
380 u16::from_le_bytes([self, self])
381 }
382}
383
384impl IntoPixelComponent<i32> for u8 {
385 fn into_component(self) -> i32 {
386 (self as i32) << 23
387 }
388}
389
390impl IntoPixelComponent<f32> for u8 {
391 fn into_component(self) -> f32 {
392 (self as f32) / u8::MAX as f32
393 }
394}
395
396impl IntoPixelComponent<u8> for u16 {
399 fn into_component(self) -> u8 {
400 self.to_le_bytes()[1]
401 }
402}
403
404impl IntoPixelComponent<i32> for u16 {
405 fn into_component(self) -> i32 {
406 (self as i32) << 15
407 }
408}
409
410impl IntoPixelComponent<f32> for u16 {
411 fn into_component(self) -> f32 {
412 (self as f32) / u16::MAX as f32
413 }
414}
415
416impl IntoPixelComponent<u8> for i32 {
419 fn into_component(self) -> u8 {
420 (self.max(0).saturating_add(1 << 22) >> 23) as u8
421 }
422}
423
424impl IntoPixelComponent<u16> for i32 {
425 fn into_component(self) -> u16 {
426 (self.max(0).saturating_add(1 << 14) >> 15) as u16
427 }
428}
429
430impl IntoPixelComponent<f32> for i32 {
431 fn into_component(self) -> f32 {
432 if self < 0 {
433 (self as f32) / i32::MIN as f32
434 } else {
435 (self as f32) / i32::MAX as f32
436 }
437 }
438}
439
440impl IntoPixelComponent<u8> for f32 {
443 fn into_component(self) -> u8 {
444 (self.clamp(0., 1.) * u8::MAX as f32).round() as u8
445 }
446}
447
448impl IntoPixelComponent<u16> for f32 {
449 fn into_component(self) -> u16 {
450 (self.clamp(0., 1.) * u16::MAX as f32).round() as u16
451 }
452}
453
454impl IntoPixelComponent<i32> for f32 {
455 fn into_component(self) -> i32 {
456 let max = if self < 0. {
457 i32::MIN as f32
458 } else {
459 i32::MAX as f32
460 };
461 (self.clamp(-1., 1.) * max).round() as i32
462 }
463}