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