Skip to main content

glycin_common/
memory_format.rs

1use std::io::Read;
2
3use serde::{Deserialize, Serialize};
4use zerocopy::{FromBytes, IntoBytes};
5use zvariant::Type;
6
7pub trait MemoryFormatInfo: Sized {
8    fn n_bytes(self) -> MemoryFormatBytes;
9    fn n_channels(self) -> u8;
10}
11
12gufo_common::maybe_convertible_enum!(
13    #[repr(i32)]
14    #[derive(Deserialize, Serialize, Type, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
15    #[cfg_attr(feature = "gobject", derive(glib::Enum))]
16    #[cfg_attr(feature = "gobject", enum_type(name = "GlyMemoryFormat"))]
17    #[zvariant(signature = "u")]
18    /// Describes the formats the image data can have.
19    ///
20    /// Orderings like "RGB" are independent of the systems endianness. Single
21    /// channels like "R16" ([`u16`]) follow the endianness of the system.
22    pub enum MemoryFormat {
23        B8g8r8a8Premultiplied = 0,
24        A8r8g8b8Premultiplied = 1,
25        R8g8b8a8Premultiplied = 2,
26        B8g8r8a8 = 3,
27        A8r8g8b8 = 4,
28        R8g8b8a8 = 5,
29        A8b8g8r8 = 6,
30        R8g8b8 = 7,
31        B8g8r8 = 8,
32        R16g16b16 = 9,
33        R16g16b16a16Premultiplied = 10,
34        R16g16b16a16 = 11,
35        R16g16b16Float = 12,
36        R16g16b16a16Float = 13,
37        R32g32b32Float = 14,
38        R32g32b32a32FloatPremultiplied = 15,
39        R32g32b32a32Float = 16,
40        G8a8Premultiplied = 17,
41        G8a8 = 18,
42        G8 = 19,
43        G16a16Premultiplied = 20,
44        G16a16 = 21,
45        G16 = 22,
46    }
47);
48
49impl MemoryFormatInfo for MemoryFormat {
50    fn n_bytes(self) -> MemoryFormatBytes {
51        match self {
52            MemoryFormat::B8g8r8a8Premultiplied => MemoryFormatBytes::B4,
53            MemoryFormat::A8r8g8b8Premultiplied => MemoryFormatBytes::B4,
54            MemoryFormat::R8g8b8a8Premultiplied => MemoryFormatBytes::B4,
55            MemoryFormat::B8g8r8a8 => MemoryFormatBytes::B4,
56            MemoryFormat::A8r8g8b8 => MemoryFormatBytes::B4,
57            MemoryFormat::R8g8b8a8 => MemoryFormatBytes::B4,
58            MemoryFormat::A8b8g8r8 => MemoryFormatBytes::B4,
59            MemoryFormat::R8g8b8 => MemoryFormatBytes::B3,
60            MemoryFormat::B8g8r8 => MemoryFormatBytes::B3,
61            MemoryFormat::R16g16b16 => MemoryFormatBytes::B6,
62            MemoryFormat::R16g16b16a16Premultiplied => MemoryFormatBytes::B8,
63            MemoryFormat::R16g16b16a16 => MemoryFormatBytes::B8,
64            MemoryFormat::R16g16b16Float => MemoryFormatBytes::B6,
65            MemoryFormat::R16g16b16a16Float => MemoryFormatBytes::B8,
66            MemoryFormat::R32g32b32Float => MemoryFormatBytes::B12,
67            MemoryFormat::R32g32b32a32FloatPremultiplied => MemoryFormatBytes::B16,
68            MemoryFormat::R32g32b32a32Float => MemoryFormatBytes::B16,
69            MemoryFormat::G8a8Premultiplied => MemoryFormatBytes::B2,
70            MemoryFormat::G8a8 => MemoryFormatBytes::B2,
71            MemoryFormat::G8 => MemoryFormatBytes::B1,
72            MemoryFormat::G16a16Premultiplied => MemoryFormatBytes::B4,
73            MemoryFormat::G16a16 => MemoryFormatBytes::B4,
74            MemoryFormat::G16 => MemoryFormatBytes::B2,
75        }
76    }
77
78    fn n_channels(self) -> u8 {
79        match self {
80            MemoryFormat::B8g8r8a8Premultiplied
81            | MemoryFormat::A8r8g8b8Premultiplied
82            | MemoryFormat::R8g8b8a8Premultiplied
83            | MemoryFormat::B8g8r8a8
84            | MemoryFormat::A8r8g8b8
85            | MemoryFormat::R8g8b8a8
86            | MemoryFormat::A8b8g8r8
87            | MemoryFormat::R16g16b16a16Premultiplied
88            | MemoryFormat::R16g16b16a16
89            | MemoryFormat::R16g16b16a16Float
90            | MemoryFormat::R32g32b32a32FloatPremultiplied
91            | MemoryFormat::R32g32b32a32Float => 4,
92            MemoryFormat::R8g8b8
93            | MemoryFormat::B8g8r8
94            | MemoryFormat::R16g16b16
95            | MemoryFormat::R16g16b16Float
96            | MemoryFormat::R32g32b32Float => 3,
97            MemoryFormat::G8a8Premultiplied
98            | MemoryFormat::G8a8
99            | MemoryFormat::G16a16Premultiplied
100            | MemoryFormat::G16a16 => 2,
101            MemoryFormat::G8 | MemoryFormat::G16 => 1,
102        }
103    }
104}
105
106impl MemoryFormat {
107    pub const ALL: &[Self] = &[
108        Self::B8g8r8a8Premultiplied,
109        Self::A8r8g8b8Premultiplied,
110        Self::R8g8b8a8Premultiplied,
111        Self::B8g8r8a8,
112        Self::A8r8g8b8,
113        Self::R8g8b8a8,
114        Self::A8b8g8r8,
115        Self::R8g8b8,
116        Self::B8g8r8,
117        Self::R16g16b16,
118        Self::R16g16b16a16Premultiplied,
119        Self::R16g16b16a16,
120        Self::R16g16b16Float,
121        Self::R16g16b16a16Float,
122        Self::R32g32b32Float,
123        Self::R32g32b32a32FloatPremultiplied,
124        Self::R32g32b32a32Float,
125        Self::G8a8Premultiplied,
126        Self::G8a8,
127        Self::G8,
128        Self::G16a16Premultiplied,
129        Self::G16a16,
130        Self::G16,
131    ];
132
133    pub const fn channel_type(self) -> ChannelType {
134        match self {
135            MemoryFormat::B8g8r8a8Premultiplied
136            | MemoryFormat::A8r8g8b8Premultiplied
137            | MemoryFormat::R8g8b8a8Premultiplied
138            | MemoryFormat::B8g8r8a8
139            | MemoryFormat::A8r8g8b8
140            | MemoryFormat::R8g8b8a8
141            | MemoryFormat::A8b8g8r8
142            | MemoryFormat::R8g8b8
143            | MemoryFormat::B8g8r8
144            | MemoryFormat::G8a8Premultiplied
145            | MemoryFormat::G8a8
146            | MemoryFormat::G8 => ChannelType::U8,
147
148            MemoryFormat::R16g16b16
149            | MemoryFormat::R16g16b16a16Premultiplied
150            | MemoryFormat::R16g16b16a16
151            | MemoryFormat::G16a16Premultiplied
152            | MemoryFormat::G16a16
153            | MemoryFormat::G16 => ChannelType::U16,
154
155            MemoryFormat::R16g16b16Float | MemoryFormat::R16g16b16a16Float => ChannelType::F16,
156
157            MemoryFormat::R32g32b32Float
158            | MemoryFormat::R32g32b32a32FloatPremultiplied
159            | MemoryFormat::R32g32b32a32Float => ChannelType::F32,
160        }
161    }
162
163    pub const fn has_alpha(self) -> bool {
164        match self {
165            MemoryFormat::B8g8r8a8Premultiplied
166            | MemoryFormat::A8r8g8b8Premultiplied
167            | MemoryFormat::R8g8b8a8Premultiplied
168            | MemoryFormat::B8g8r8a8
169            | MemoryFormat::A8r8g8b8
170            | MemoryFormat::R8g8b8a8
171            | MemoryFormat::A8b8g8r8
172            | MemoryFormat::R16g16b16a16Premultiplied
173            | MemoryFormat::R32g32b32a32FloatPremultiplied
174            | MemoryFormat::R32g32b32a32Float
175            | MemoryFormat::G8a8Premultiplied
176            | MemoryFormat::G8a8
177            | MemoryFormat::R16g16b16a16
178            | MemoryFormat::R16g16b16a16Float
179            | MemoryFormat::G16a16Premultiplied
180            | MemoryFormat::G16a16 => true,
181
182            MemoryFormat::R8g8b8
183            | MemoryFormat::B8g8r8
184            | MemoryFormat::R16g16b16
185            | MemoryFormat::R16g16b16Float
186            | MemoryFormat::R32g32b32Float
187            | MemoryFormat::G8
188            | MemoryFormat::G16 => false,
189        }
190    }
191
192    pub const fn is_premultiplied(self) -> bool {
193        match self {
194            MemoryFormat::B8g8r8a8Premultiplied
195            | MemoryFormat::A8r8g8b8Premultiplied
196            | MemoryFormat::R8g8b8a8Premultiplied
197            | MemoryFormat::R16g16b16a16Premultiplied
198            | MemoryFormat::R32g32b32a32FloatPremultiplied
199            | MemoryFormat::G8a8Premultiplied
200            | MemoryFormat::G16a16Premultiplied => true,
201
202            MemoryFormat::B8g8r8a8
203            | MemoryFormat::A8r8g8b8
204            | MemoryFormat::R8g8b8a8
205            | MemoryFormat::A8b8g8r8
206            | MemoryFormat::R8g8b8
207            | MemoryFormat::B8g8r8
208            | MemoryFormat::R16g16b16
209            | MemoryFormat::R16g16b16a16
210            | MemoryFormat::R16g16b16Float
211            | MemoryFormat::R16g16b16a16Float
212            | MemoryFormat::R32g32b32Float
213            | MemoryFormat::R32g32b32a32Float
214            | MemoryFormat::G8a8
215            | MemoryFormat::G8
216            | MemoryFormat::G16a16
217            | MemoryFormat::G16 => false,
218        }
219    }
220
221    /// Defines from which channels to get the RGBA values
222    ///
223    /// The return value is in the order `[R, G, B, A]`.
224    pub const fn source_definition(self) -> [Source; 4] {
225        match self {
226            MemoryFormat::B8g8r8a8Premultiplied | MemoryFormat::B8g8r8a8 => {
227                [Source::C2, Source::C1, Source::C0, Source::C3]
228            }
229
230            MemoryFormat::A8r8g8b8Premultiplied | MemoryFormat::A8r8g8b8 => {
231                [Source::C1, Source::C2, Source::C3, Source::C0]
232            }
233
234            MemoryFormat::R8g8b8a8Premultiplied
235            | MemoryFormat::R8g8b8a8
236            | MemoryFormat::R16g16b16a16Premultiplied
237            | MemoryFormat::R16g16b16a16
238            | MemoryFormat::R16g16b16a16Float
239            | MemoryFormat::R32g32b32a32FloatPremultiplied
240            | MemoryFormat::R32g32b32a32Float => [Source::C0, Source::C1, Source::C2, Source::C3],
241
242            MemoryFormat::A8b8g8r8 => [Source::C1, Source::C2, Source::C3, Source::C0],
243
244            MemoryFormat::R8g8b8
245            | MemoryFormat::R16g16b16
246            | MemoryFormat::R16g16b16Float
247            | MemoryFormat::R32g32b32Float => [Source::C0, Source::C1, Source::C2, Source::Opaque],
248
249            MemoryFormat::B8g8r8 => [Source::C2, Source::C1, Source::C0, Source::Opaque],
250
251            MemoryFormat::G8a8Premultiplied
252            | MemoryFormat::G8a8
253            | MemoryFormat::G16a16Premultiplied
254            | MemoryFormat::G16a16 => [Source::C0, Source::C0, Source::C0, Source::C1],
255
256            MemoryFormat::G8 | MemoryFormat::G16 => {
257                [Source::C0, Source::C0, Source::C0, Source::Opaque]
258            }
259        }
260    }
261
262    pub const fn target_definition(self) -> &'static [Target] {
263        match self {
264            MemoryFormat::B8g8r8a8Premultiplied | MemoryFormat::B8g8r8a8 => {
265                &[Target::B, Target::G, Target::R, Target::A]
266            }
267            MemoryFormat::A8r8g8b8Premultiplied | MemoryFormat::A8r8g8b8 => {
268                &[Target::A, Target::R, Target::G, Target::B]
269            }
270            MemoryFormat::R8g8b8a8Premultiplied
271            | MemoryFormat::R8g8b8a8
272            | MemoryFormat::R16g16b16a16Premultiplied
273            | MemoryFormat::R16g16b16a16
274            | MemoryFormat::R16g16b16a16Float
275            | MemoryFormat::R32g32b32a32FloatPremultiplied
276            | MemoryFormat::R32g32b32a32Float => &[Target::R, Target::G, Target::B, Target::A],
277            MemoryFormat::A8b8g8r8 => &[Target::A, Target::B, Target::G, Target::R],
278            MemoryFormat::R8g8b8
279            | MemoryFormat::R16g16b16
280            | MemoryFormat::R16g16b16Float
281            | MemoryFormat::R32g32b32Float => &[Target::R, Target::G, Target::B],
282            MemoryFormat::B8g8r8 => &[Target::B, Target::G, Target::R],
283            MemoryFormat::G8a8Premultiplied
284            | MemoryFormat::G8a8
285            | MemoryFormat::G16a16Premultiplied
286            | MemoryFormat::G16a16 => &[Target::RgbAvg, Target::A],
287            MemoryFormat::G8 | MemoryFormat::G16 => &[Target::RgbAvg],
288        }
289    }
290
291    #[inline]
292    pub fn transform(src_format: Self, src: &[u8], target_format: Self, target: &mut [u8]) {
293        let channels_f32 = Self::to_f32(src_format, src);
294        Self::from_f32(channels_f32, target_format, target);
295    }
296
297    #[inline]
298    pub fn to_f32(src_format: Self, mut src: &[u8]) -> [f32; 4] {
299        match src_format.channel_type() {
300            ChannelType::U8 => {
301                Self::to_f32_internal::<u8>(FromBytes::ref_from_bytes(src).unwrap(), src_format)
302            }
303            ChannelType::U16 => {
304                Self::to_f32_internal::<u16>(FromBytes::ref_from_bytes(src).unwrap(), src_format)
305            }
306            ChannelType::F16 => {
307                let bytes = &mut [0; 2];
308                let mut f16_data = Vec::new();
309                while let Ok(()) = src.read_exact(bytes) {
310                    f16_data.push(half::f16::from_ne_bytes(*bytes));
311                }
312                Self::to_f32_internal::<half::f16>(&f16_data, src_format)
313            }
314            ChannelType::F32 => {
315                Self::to_f32_internal::<f32>(FromBytes::ref_from_bytes(src).unwrap(), src_format)
316            }
317        }
318    }
319
320    #[inline]
321    fn to_f32_internal<T: ChannelValue>(source_channels: &[T], source_format: Self) -> [f32; 4] {
322        let mut channels_f32 = [0.0_f32; 4];
323
324        let source_definition = source_format.source_definition();
325
326        for (n, channel) in channels_f32.iter_mut().enumerate() {
327            *channel = match source_definition[n] {
328                Source::C0 => (source_channels[0]).to_f32_normed(),
329                Source::C1 => (source_channels[1]).to_f32_normed(),
330                Source::C2 => (source_channels[2]).to_f32_normed(),
331                Source::C3 => (source_channels[3]).to_f32_normed(),
332                Source::Opaque => 1.,
333            };
334        }
335
336        if source_format.is_premultiplied() && channels_f32[3] > 0. {
337            channels_f32[0] /= channels_f32[3];
338            channels_f32[1] /= channels_f32[3];
339            channels_f32[2] /= channels_f32[3];
340        }
341
342        channels_f32
343    }
344
345    #[inline]
346    pub(crate) fn from_f32(channels_f32: [f32; 4], target_format: Self, target: &mut [u8]) {
347        match target_format.channel_type() {
348            ChannelType::U8 => Self::from_f32_internal::<u8>(channels_f32, target_format, target),
349            ChannelType::U16 => Self::from_f32_internal::<u16>(channels_f32, target_format, target),
350            ChannelType::F16 => {
351                Self::from_f32_internal::<half::f16>(channels_f32, target_format, target)
352            }
353            ChannelType::F32 => Self::from_f32_internal::<f32>(channels_f32, target_format, target),
354        }
355    }
356
357    #[inline]
358    fn from_f32_internal<T: ChannelValue>(
359        channels_f32: [f32; 4],
360        target_format: Self,
361        target: &mut [u8],
362    ) {
363        let target_channel_size = target_format.channel_type().size() as usize;
364
365        let premultiply = if target_format.is_premultiplied() {
366            channels_f32[3]
367        } else {
368            1.
369        };
370
371        for (n, def) in target_format.target_definition().iter().enumerate() {
372            let new_channel = match def {
373                Target::R => T::from_f32_normed(channels_f32[0] * premultiply),
374                Target::G => T::from_f32_normed(channels_f32[1] * premultiply),
375                Target::B => T::from_f32_normed(channels_f32[2] * premultiply),
376                Target::A => T::from_f32_normed(channels_f32[3]),
377                Target::RgbAvg => {
378                    T::from_f32_normed((channels_f32[0] + channels_f32[1] + channels_f32[2]) / 3.)
379                }
380            };
381
382            let bytes = new_channel.as_bytes_wrapper();
383
384            for i in 0..target_channel_size {
385                target[n * target_channel_size + i] = bytes[i];
386            }
387        }
388    }
389
390    pub fn try_from_str(s: &str) -> Option<Self> {
391        Some(match s {
392            "B8g8r8a8Premultiplied" => Self::B8g8r8a8Premultiplied,
393            "A8r8g8b8Premultiplied" => Self::A8r8g8b8Premultiplied,
394            "R8g8b8a8Premultiplied" => Self::R8g8b8a8Premultiplied,
395            "B8g8r8a8" => Self::B8g8r8a8,
396            "A8r8g8b8" => Self::A8r8g8b8,
397            "R8g8b8a8" => Self::R8g8b8a8,
398            "A8b8g8r8" => Self::A8b8g8r8,
399            "R8g8b8" => Self::R8g8b8,
400            "B8g8r8" => Self::B8g8r8,
401            "R16g16b16" => Self::R16g16b16,
402            "R16g16b16a16Premultiplied" => Self::R16g16b16a16Premultiplied,
403            "R16g16b16a16" => Self::R16g16b16a16,
404            "R16g16b16Float" => Self::R16g16b16Float,
405            "R16g16b16a16Float" => Self::R16g16b16a16Float,
406            "R32g32b32Float" => Self::R32g32b32Float,
407            "R32g32b32a32FloatPremultiplied" => Self::R32g32b32a32FloatPremultiplied,
408            "R32g32b32a32Float" => Self::R32g32b32a32Float,
409            "G8a8Premultiplied" => Self::G8a8Premultiplied,
410            "G8a8" => Self::G8a8,
411            "G8" => Self::G8,
412            "G16a16Premultiplied" => Self::G16a16Premultiplied,
413            "G16a16" => Self::G16a16,
414            "G16" => Self::G16,
415            _ => return None,
416        })
417    }
418
419    pub const fn display(&self) -> &'static str {
420        match self {
421            Self::B8g8r8a8Premultiplied => "BGRA8 Premultiplied",
422            Self::A8r8g8b8Premultiplied => "ARGB8 Premultiplied",
423            Self::R8g8b8a8Premultiplied => "RGBA8 Premultiplied",
424            Self::B8g8r8a8 => "BGRA8",
425            Self::A8r8g8b8 => "ARGB8",
426            Self::R8g8b8a8 => "RGBA8",
427            Self::A8b8g8r8 => "ABGR8",
428            Self::R8g8b8 => "RGB8",
429            Self::B8g8r8 => "BGR8",
430            Self::R16g16b16 => "RGB16",
431            Self::R16g16b16a16Premultiplied => "RGBA16 Premultiplied",
432            Self::R16g16b16a16 => "RGBA16",
433            Self::R16g16b16Float => "RGB16Float",
434            Self::R16g16b16a16Float => "RGBA16Float",
435            Self::R32g32b32Float => "RGB32Float",
436            Self::R32g32b32a32FloatPremultiplied => "RGBA32Float Premultiplied",
437            Self::R32g32b32a32Float => "RGBA32Float",
438            Self::G8a8Premultiplied => "GA8 Premultiplied",
439            Self::G8a8 => "GA8",
440            Self::G8 => "G8",
441            Self::G16a16Premultiplied => "GA16 Premultiplied",
442            Self::G16a16 => "GA16",
443            Self::G16 => "G16",
444        }
445    }
446}
447
448#[derive(Debug, Clone, Copy)]
449pub enum ExtendedMemoryFormat {
450    Basic(MemoryFormat),
451    Y8Cb8Cr8,
452    Y8Cb8Cr8K8,
453}
454
455impl MemoryFormatInfo for ExtendedMemoryFormat {
456    fn n_bytes(self) -> MemoryFormatBytes {
457        match self {
458            Self::Basic(basic) => basic.n_bytes(),
459            Self::Y8Cb8Cr8 => MemoryFormatBytes::B3,
460            Self::Y8Cb8Cr8K8 => MemoryFormatBytes::B4,
461        }
462    }
463
464    fn n_channels(self) -> u8 {
465        match self {
466            Self::Basic(basic) => basic.n_channels(),
467            Self::Y8Cb8Cr8 => 3,
468            Self::Y8Cb8Cr8K8 => 4,
469        }
470    }
471}
472
473trait ChannelValue: Default + Copy {
474    fn from_f32_normed(value: f32) -> Self;
475    fn to_f32_normed(self) -> f32;
476    fn as_bytes_wrapper(&self) -> &[u8];
477}
478
479impl ChannelValue for u8 {
480    fn from_f32_normed(value: f32) -> Self {
481        (value * Self::MAX as f32).round() as Self
482    }
483
484    fn to_f32_normed(self) -> f32 {
485        (self as f32) / Self::MAX as f32
486    }
487
488    fn as_bytes_wrapper(&self) -> &[u8] {
489        self.as_bytes()
490    }
491}
492
493impl ChannelValue for u16 {
494    fn from_f32_normed(value: f32) -> Self {
495        (value * Self::MAX as f32).round() as Self
496    }
497
498    fn to_f32_normed(self) -> f32 {
499        (self as f32) / Self::MAX as f32
500    }
501
502    fn as_bytes_wrapper(&self) -> &[u8] {
503        self.as_bytes()
504    }
505}
506
507impl ChannelValue for half::f16 {
508    fn from_f32_normed(value: f32) -> Self {
509        Self::from_f32(value)
510    }
511
512    fn to_f32_normed(self) -> f32 {
513        self.into()
514    }
515
516    fn as_bytes_wrapper(&self) -> &[u8] {
517        self.as_bytes()
518    }
519}
520
521impl ChannelValue for f32 {
522    fn from_f32_normed(value: f32) -> Self {
523        value
524    }
525
526    fn to_f32_normed(self) -> f32 {
527        self
528    }
529
530    fn as_bytes_wrapper(&self) -> &[u8] {
531        self.as_bytes()
532    }
533}
534
535#[derive(Debug, Clone, Copy, PartialEq, Eq)]
536pub enum Target {
537    R,
538    G,
539    B,
540    A,
541    RgbAvg,
542}
543
544/// Defines a channel from which to take the value for a color/opacity
545///
546/// These are usually used in an array of sources of the order [R, G, B, A].
547#[derive(Debug, Clone, Copy, PartialEq, Eq)]
548pub enum Source {
549    C0,
550    C1,
551    C2,
552    C3,
553    Opaque,
554}
555
556#[derive(Debug, PartialEq, Eq)]
557pub enum ChannelType {
558    U8,
559    U16,
560    F16,
561    F32,
562}
563
564impl ChannelType {
565    pub const fn size(self) -> u8 {
566        match self {
567            Self::U8 => 1,
568            Self::U16 => 2,
569            Self::F16 => 2,
570            Self::F32 => 4,
571        }
572    }
573}
574
575impl From<MemoryFormat> for ExtendedMemoryFormat {
576    fn from(value: MemoryFormat) -> Self {
577        Self::Basic(value)
578    }
579}
580
581#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
582pub enum MemoryFormatBytes {
583    B1 = 1,
584    B2 = 2,
585    B3 = 3,
586    B4 = 4,
587    B6 = 6,
588    B8 = 8,
589    B12 = 12,
590    B16 = 16,
591}
592
593// TODO: Convert to From trait impls
594impl MemoryFormatBytes {
595    pub fn u8(self) -> u8 {
596        self as u8
597    }
598
599    pub fn u32(self) -> u32 {
600        self as u32
601    }
602
603    pub fn u64(self) -> u64 {
604        self as u64
605    }
606
607    pub fn usize(self) -> usize {
608        self as usize
609    }
610}
611
612#[cfg(test)]
613mod tests {
614    use super::*;
615
616    #[test]
617    fn simple() {
618        let target = &mut [0; 4];
619
620        MemoryFormat::transform(
621            MemoryFormat::R8g8b8,
622            &[255, 85, 127],
623            MemoryFormat::B8g8r8a8,
624            target,
625        );
626
627        assert_eq!(*target, [127, 85, 255, 255]);
628    }
629
630    #[test]
631    fn grayscale() {
632        let target = &mut [0; 1];
633
634        MemoryFormat::transform(
635            MemoryFormat::R8g8b8,
636            &[255, 0, 127],
637            MemoryFormat::G8,
638            target,
639        );
640
641        assert_eq!(*target, [127]);
642    }
643
644    #[test]
645    fn u16() {
646        let target = &mut [0; 6];
647
648        MemoryFormat::transform(
649            MemoryFormat::R8g8b8,
650            &[255, 0, 127],
651            MemoryFormat::R16g16b16,
652            target,
653        );
654
655        assert_eq!(*target, [255, 255, 0, 0, 127, 127]);
656    }
657}