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 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 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#[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
590impl 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}