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