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)]
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 fn channel_type(self) -> ChannelType {
105 match self {
106 MemoryFormat::B8g8r8a8Premultiplied
107 | MemoryFormat::A8r8g8b8Premultiplied
108 | MemoryFormat::R8g8b8a8Premultiplied
109 | MemoryFormat::B8g8r8a8
110 | MemoryFormat::A8r8g8b8
111 | MemoryFormat::R8g8b8a8
112 | MemoryFormat::A8b8g8r8
113 | MemoryFormat::R8g8b8
114 | MemoryFormat::B8g8r8
115 | MemoryFormat::G8a8Premultiplied
116 | MemoryFormat::G8a8
117 | MemoryFormat::G8 => ChannelType::U8,
118
119 MemoryFormat::R16g16b16
120 | MemoryFormat::R16g16b16a16Premultiplied
121 | MemoryFormat::R16g16b16a16
122 | MemoryFormat::G16a16Premultiplied
123 | MemoryFormat::G16a16
124 | MemoryFormat::G16 => ChannelType::U16,
125
126 MemoryFormat::R16g16b16Float | MemoryFormat::R16g16b16a16Float => ChannelType::F16,
127
128 MemoryFormat::R32g32b32Float
129 | MemoryFormat::R32g32b32a32FloatPremultiplied
130 | MemoryFormat::R32g32b32a32Float => ChannelType::F32,
131 }
132 }
133
134 pub const fn has_alpha(self) -> bool {
135 match self {
136 MemoryFormat::B8g8r8a8Premultiplied
137 | MemoryFormat::A8r8g8b8Premultiplied
138 | MemoryFormat::R8g8b8a8Premultiplied
139 | MemoryFormat::B8g8r8a8
140 | MemoryFormat::A8r8g8b8
141 | MemoryFormat::R8g8b8a8
142 | MemoryFormat::A8b8g8r8
143 | MemoryFormat::R16g16b16a16Premultiplied
144 | MemoryFormat::R32g32b32a32FloatPremultiplied
145 | MemoryFormat::R32g32b32a32Float
146 | MemoryFormat::G8a8Premultiplied
147 | MemoryFormat::G8a8
148 | MemoryFormat::R16g16b16a16
149 | MemoryFormat::R16g16b16a16Float
150 | MemoryFormat::G16a16Premultiplied
151 | MemoryFormat::G16a16 => true,
152
153 MemoryFormat::R8g8b8
154 | MemoryFormat::B8g8r8
155 | MemoryFormat::R16g16b16
156 | MemoryFormat::R16g16b16Float
157 | MemoryFormat::R32g32b32Float
158 | MemoryFormat::G8
159 | MemoryFormat::G16 => false,
160 }
161 }
162
163 pub const fn is_premultiplied(self) -> bool {
164 match self {
165 MemoryFormat::B8g8r8a8Premultiplied
166 | MemoryFormat::A8r8g8b8Premultiplied
167 | MemoryFormat::R8g8b8a8Premultiplied
168 | MemoryFormat::R16g16b16a16Premultiplied
169 | MemoryFormat::R32g32b32a32FloatPremultiplied
170 | MemoryFormat::G8a8Premultiplied
171 | MemoryFormat::G16a16Premultiplied => true,
172
173 MemoryFormat::B8g8r8a8
174 | MemoryFormat::A8r8g8b8
175 | MemoryFormat::R8g8b8a8
176 | MemoryFormat::A8b8g8r8
177 | MemoryFormat::R8g8b8
178 | MemoryFormat::B8g8r8
179 | MemoryFormat::R16g16b16
180 | MemoryFormat::R16g16b16a16
181 | MemoryFormat::R16g16b16Float
182 | MemoryFormat::R16g16b16a16Float
183 | MemoryFormat::R32g32b32Float
184 | MemoryFormat::R32g32b32a32Float
185 | MemoryFormat::G8a8
186 | MemoryFormat::G8
187 | MemoryFormat::G16a16
188 | MemoryFormat::G16 => false,
189 }
190 }
191
192 pub const fn source_definition(self) -> [Source; 4] {
196 match self {
197 MemoryFormat::B8g8r8a8Premultiplied | MemoryFormat::B8g8r8a8 => {
198 [Source::C2, Source::C1, Source::C0, Source::C3]
199 }
200
201 MemoryFormat::A8r8g8b8Premultiplied | MemoryFormat::A8r8g8b8 => {
202 [Source::C1, Source::C2, Source::C3, Source::C0]
203 }
204
205 MemoryFormat::R8g8b8a8Premultiplied
206 | MemoryFormat::R8g8b8a8
207 | MemoryFormat::R16g16b16a16Premultiplied
208 | MemoryFormat::R16g16b16a16
209 | MemoryFormat::R16g16b16a16Float
210 | MemoryFormat::R32g32b32a32FloatPremultiplied
211 | MemoryFormat::R32g32b32a32Float => [Source::C0, Source::C1, Source::C2, Source::C3],
212
213 MemoryFormat::A8b8g8r8 => [Source::C1, Source::C2, Source::C3, Source::C0],
214
215 MemoryFormat::R8g8b8
216 | MemoryFormat::R16g16b16
217 | MemoryFormat::R16g16b16Float
218 | MemoryFormat::R32g32b32Float => [Source::C0, Source::C1, Source::C2, Source::Opaque],
219
220 MemoryFormat::B8g8r8 => [Source::C2, Source::C1, Source::C0, Source::Opaque],
221
222 MemoryFormat::G8a8Premultiplied
223 | MemoryFormat::G8a8
224 | MemoryFormat::G16a16Premultiplied
225 | MemoryFormat::G16a16 => [Source::C0, Source::C0, Source::C0, Source::C1],
226
227 MemoryFormat::G8 | MemoryFormat::G16 => {
228 [Source::C0, Source::C0, Source::C0, Source::Opaque]
229 }
230 }
231 }
232
233 pub const fn target_definition(self) -> &'static [Target] {
234 match self {
235 MemoryFormat::B8g8r8a8Premultiplied | MemoryFormat::B8g8r8a8 => {
236 &[Target::B, Target::G, Target::R, Target::A]
237 }
238 MemoryFormat::A8r8g8b8Premultiplied | MemoryFormat::A8r8g8b8 => {
239 &[Target::A, Target::R, Target::G, Target::B]
240 }
241 MemoryFormat::R8g8b8a8Premultiplied
242 | MemoryFormat::R8g8b8a8
243 | MemoryFormat::R16g16b16a16Premultiplied
244 | MemoryFormat::R16g16b16a16
245 | MemoryFormat::R16g16b16a16Float
246 | MemoryFormat::R32g32b32a32FloatPremultiplied
247 | MemoryFormat::R32g32b32a32Float => &[Target::R, Target::G, Target::B, Target::A],
248 MemoryFormat::A8b8g8r8 => &[Target::A, Target::B, Target::G, Target::R],
249 MemoryFormat::R8g8b8
250 | MemoryFormat::R16g16b16
251 | MemoryFormat::R16g16b16Float
252 | MemoryFormat::R32g32b32Float => &[Target::R, Target::G, Target::B],
253 MemoryFormat::B8g8r8 => &[Target::B, Target::G, Target::R],
254 MemoryFormat::G8a8Premultiplied
255 | MemoryFormat::G8a8
256 | MemoryFormat::G16a16Premultiplied
257 | MemoryFormat::G16a16 => &[Target::RgbAvg, Target::A],
258 MemoryFormat::G8 | MemoryFormat::G16 => &[Target::RgbAvg],
259 }
260 }
261
262 #[inline]
263 pub fn transform(src_format: Self, src: &[u8], target_format: Self, target: &mut [u8]) {
264 let channels_f32 = Self::to_f32(src_format, src);
265 Self::from_f32(channels_f32, target_format, target);
266 }
267
268 #[inline]
269 pub fn to_f32(src_format: Self, mut src: &[u8]) -> [f32; 4] {
270 match src_format.channel_type() {
271 ChannelType::U8 => {
272 Self::to_f32_internal::<u8>(FromBytes::ref_from_bytes(src).unwrap(), src_format)
273 }
274 ChannelType::U16 => {
275 Self::to_f32_internal::<u16>(FromBytes::ref_from_bytes(src).unwrap(), src_format)
276 }
277 ChannelType::F16 => {
278 let bytes = &mut [0; 2];
279 let mut f16_data = Vec::new();
280 while let Ok(()) = src.read_exact(bytes) {
281 f16_data.push(half::f16::from_ne_bytes(*bytes));
282 }
283 Self::to_f32_internal::<half::f16>(&f16_data, src_format)
284 }
285 ChannelType::F32 => {
286 Self::to_f32_internal::<f32>(FromBytes::ref_from_bytes(src).unwrap(), src_format)
287 }
288 }
289 }
290
291 #[inline]
292 fn to_f32_internal<T: ChannelValue>(source_channels: &[T], source_format: Self) -> [f32; 4] {
293 let mut channels_f32 = [0.0_f32; 4];
294
295 let source_definition = source_format.source_definition();
296
297 for (n, channel) in channels_f32.iter_mut().enumerate() {
298 *channel = match source_definition[n] {
299 Source::C0 => (source_channels[0]).to_f32_normed(),
300 Source::C1 => (source_channels[1]).to_f32_normed(),
301 Source::C2 => (source_channels[2]).to_f32_normed(),
302 Source::C3 => (source_channels[3]).to_f32_normed(),
303 Source::Opaque => 1.,
304 };
305 }
306
307 if source_format.is_premultiplied() && channels_f32[3] > 0. {
308 channels_f32[0] /= channels_f32[3];
309 channels_f32[1] /= channels_f32[3];
310 channels_f32[2] /= channels_f32[3];
311 }
312
313 channels_f32
314 }
315
316 #[inline]
317 pub(crate) fn from_f32(channels_f32: [f32; 4], target_format: Self, target: &mut [u8]) {
318 match target_format.channel_type() {
319 ChannelType::U8 => Self::from_f32_internal::<u8>(channels_f32, target_format, target),
320 ChannelType::U16 => Self::from_f32_internal::<u16>(channels_f32, target_format, target),
321 ChannelType::F16 => {
322 Self::from_f32_internal::<half::f16>(channels_f32, target_format, target)
323 }
324 ChannelType::F32 => Self::from_f32_internal::<f32>(channels_f32, target_format, target),
325 }
326 }
327
328 #[inline]
329 fn from_f32_internal<T: ChannelValue>(
330 channels_f32: [f32; 4],
331 target_format: Self,
332 target: &mut [u8],
333 ) {
334 let target_channel_size = target_format.channel_type().size();
335
336 let premultiply = if target_format.is_premultiplied() {
337 channels_f32[3]
338 } else {
339 1.
340 };
341
342 for (n, def) in target_format.target_definition().iter().enumerate() {
343 let new_channel = match def {
344 Target::R => T::from_f32_normed(channels_f32[0] * premultiply),
345 Target::G => T::from_f32_normed(channels_f32[1] * premultiply),
346 Target::B => T::from_f32_normed(channels_f32[2] * premultiply),
347 Target::A => T::from_f32_normed(channels_f32[3]),
348 Target::RgbAvg => {
349 T::from_f32_normed((channels_f32[0] + channels_f32[1] + channels_f32[2]) / 3.)
350 }
351 };
352
353 let bytes = new_channel.as_bytes_wrapper();
354
355 for i in 0..target_channel_size {
356 target[n * target_channel_size + i] = bytes[i];
357 }
358 }
359 }
360}
361
362#[derive(Debug, Clone, Copy)]
363pub enum ExtendedMemoryFormat {
364 Basic(MemoryFormat),
365 Y8Cb8Cr8,
366}
367
368impl MemoryFormatInfo for ExtendedMemoryFormat {
369 fn n_bytes(self) -> MemoryFormatBytes {
370 match self {
371 Self::Basic(basic) => basic.n_bytes(),
372 Self::Y8Cb8Cr8 => MemoryFormatBytes::B3,
373 }
374 }
375
376 fn n_channels(self) -> u8 {
377 match self {
378 Self::Basic(basic) => basic.n_channels(),
379 Self::Y8Cb8Cr8 => 3,
380 }
381 }
382}
383
384trait ChannelValue: Default + Copy {
385 fn from_f32_normed(value: f32) -> Self;
386 fn to_f32_normed(self) -> f32;
387 fn as_bytes_wrapper(&self) -> &[u8];
388}
389
390impl ChannelValue for u8 {
391 fn from_f32_normed(value: f32) -> Self {
392 (value * Self::MAX as f32).round() as Self
393 }
394
395 fn to_f32_normed(self) -> f32 {
396 (self as f32) / Self::MAX as f32
397 }
398
399 fn as_bytes_wrapper(&self) -> &[u8] {
400 self.as_bytes()
401 }
402}
403
404impl ChannelValue for u16 {
405 fn from_f32_normed(value: f32) -> Self {
406 (value * Self::MAX as f32).round() as Self
407 }
408
409 fn to_f32_normed(self) -> f32 {
410 (self as f32) / Self::MAX as f32
411 }
412
413 fn as_bytes_wrapper(&self) -> &[u8] {
414 self.as_bytes()
415 }
416}
417
418impl ChannelValue for half::f16 {
419 fn from_f32_normed(value: f32) -> Self {
420 Self::from_f32(value)
421 }
422
423 fn to_f32_normed(self) -> f32 {
424 self.into()
425 }
426
427 fn as_bytes_wrapper(&self) -> &[u8] {
428 self.as_bytes()
429 }
430}
431
432impl ChannelValue for f32 {
433 fn from_f32_normed(value: f32) -> Self {
434 value
435 }
436
437 fn to_f32_normed(self) -> f32 {
438 self
439 }
440
441 fn as_bytes_wrapper(&self) -> &[u8] {
442 self.as_bytes()
443 }
444}
445
446#[derive(Debug, Clone, Copy, PartialEq, Eq)]
447pub enum Target {
448 R,
449 G,
450 B,
451 A,
452 RgbAvg,
453}
454
455#[derive(Debug, Clone, Copy, PartialEq, Eq)]
459pub enum Source {
460 C0,
461 C1,
462 C2,
463 C3,
464 Opaque,
465}
466
467#[derive(Debug, PartialEq, Eq)]
468pub enum ChannelType {
469 U8,
470 U16,
471 F16,
472 F32,
473}
474
475impl ChannelType {
476 pub fn size(self) -> usize {
477 match self {
478 Self::U8 => 1,
479 Self::U16 => 2,
480 Self::F16 => 2,
481 Self::F32 => 4,
482 }
483 }
484}
485
486impl From<MemoryFormat> for ExtendedMemoryFormat {
487 fn from(value: MemoryFormat) -> Self {
488 Self::Basic(value)
489 }
490}
491
492#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
493pub enum MemoryFormatBytes {
494 B1 = 1,
495 B2 = 2,
496 B3 = 3,
497 B4 = 4,
498 B6 = 6,
499 B8 = 8,
500 B12 = 12,
501 B16 = 16,
502}
503
504impl MemoryFormatBytes {
506 pub fn u8(self) -> u8 {
507 self as u8
508 }
509
510 pub fn u32(self) -> u32 {
511 self as u32
512 }
513
514 pub fn u64(self) -> u64 {
515 self as u64
516 }
517
518 pub fn usize(self) -> usize {
519 self as usize
520 }
521}
522
523#[cfg(test)]
524mod tests {
525 use super::*;
526
527 #[test]
528 fn simple() {
529 let target = &mut [0; 4];
530
531 MemoryFormat::transform(
532 MemoryFormat::R8g8b8,
533 &[255, 85, 127],
534 MemoryFormat::B8g8r8a8,
535 target,
536 );
537
538 assert_eq!(*target, [127, 85, 255, 255]);
539 }
540
541 #[test]
542 fn grayscale() {
543 let target = &mut [0; 1];
544
545 MemoryFormat::transform(
546 MemoryFormat::R8g8b8,
547 &[255, 0, 127],
548 MemoryFormat::G8,
549 target,
550 );
551
552 assert_eq!(*target, [127]);
553 }
554
555 #[test]
556 fn u16() {
557 let target = &mut [0; 6];
558
559 MemoryFormat::transform(
560 MemoryFormat::R8g8b8,
561 &[255, 0, 127],
562 MemoryFormat::R16g16b16,
563 target,
564 );
565
566 assert_eq!(*target, [255, 255, 0, 0, 127, 127]);
567 }
568}