ff_format/color.rs
1//! Color space and related type definitions.
2//!
3//! This module provides enums for color-related metadata commonly found
4//! in video streams, including color space, color range, and color primaries.
5//!
6//! # Examples
7//!
8//! ```
9//! use ff_format::color::{ColorSpace, ColorRange, ColorPrimaries};
10//!
11//! // HD video typically uses BT.709
12//! let space = ColorSpace::Bt709;
13//! let range = ColorRange::Limited;
14//! let primaries = ColorPrimaries::Bt709;
15//!
16//! assert!(space.is_hd());
17//! assert!(!range.is_full());
18//! ```
19
20use std::fmt;
21
22/// Color space (matrix coefficients) for YUV to RGB conversion.
23///
24/// The color space defines how YUV values are converted to RGB and vice versa.
25/// Different standards use different matrix coefficients for this conversion.
26///
27/// # Common Usage
28///
29/// - **BT.709**: HD content (720p, 1080p)
30/// - **BT.601**: SD content (480i, 576i)
31/// - **BT.2020**: UHD/HDR content (4K, 8K)
32/// - **sRGB**: Computer graphics, web content
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
34#[non_exhaustive]
35pub enum ColorSpace {
36 /// ITU-R BT.709 - HD television standard (most common for HD video)
37 #[default]
38 Bt709,
39 /// ITU-R BT.601 - SD television standard
40 Bt601,
41 /// ITU-R BT.2020 - UHD/HDR television standard
42 Bt2020,
43 /// DCI-P3 - digital cinema wide color gamut
44 DciP3,
45 /// sRGB color space - computer graphics and web
46 Srgb,
47 /// Color space is not specified or unknown
48 Unknown,
49}
50
51impl ColorSpace {
52 /// Returns the name of the color space as a human-readable string.
53 ///
54 /// # Examples
55 ///
56 /// ```
57 /// use ff_format::color::ColorSpace;
58 ///
59 /// assert_eq!(ColorSpace::Bt709.name(), "bt709");
60 /// assert_eq!(ColorSpace::Bt601.name(), "bt601");
61 /// ```
62 #[must_use]
63 pub const fn name(&self) -> &'static str {
64 match self {
65 Self::Bt709 => "bt709",
66 Self::Bt601 => "bt601",
67 Self::Bt2020 => "bt2020",
68 Self::DciP3 => "dcip3",
69 Self::Srgb => "srgb",
70 Self::Unknown => "unknown",
71 }
72 }
73
74 /// Returns `true` if this is an HD color space (BT.709).
75 ///
76 /// # Examples
77 ///
78 /// ```
79 /// use ff_format::color::ColorSpace;
80 ///
81 /// assert!(ColorSpace::Bt709.is_hd());
82 /// assert!(!ColorSpace::Bt601.is_hd());
83 /// ```
84 #[must_use]
85 pub const fn is_hd(&self) -> bool {
86 matches!(self, Self::Bt709)
87 }
88
89 /// Returns `true` if this is an SD color space (BT.601).
90 ///
91 /// # Examples
92 ///
93 /// ```
94 /// use ff_format::color::ColorSpace;
95 ///
96 /// assert!(ColorSpace::Bt601.is_sd());
97 /// assert!(!ColorSpace::Bt709.is_sd());
98 /// ```
99 #[must_use]
100 pub const fn is_sd(&self) -> bool {
101 matches!(self, Self::Bt601)
102 }
103
104 /// Returns `true` if this is a UHD/HDR color space (BT.2020).
105 ///
106 /// # Examples
107 ///
108 /// ```
109 /// use ff_format::color::ColorSpace;
110 ///
111 /// assert!(ColorSpace::Bt2020.is_uhd());
112 /// assert!(!ColorSpace::Bt709.is_uhd());
113 /// ```
114 #[must_use]
115 pub const fn is_uhd(&self) -> bool {
116 matches!(self, Self::Bt2020)
117 }
118
119 /// Returns `true` if this is a cinema/DCI color space (DCI-P3).
120 ///
121 /// # Examples
122 ///
123 /// ```
124 /// use ff_format::color::ColorSpace;
125 ///
126 /// assert!(ColorSpace::DciP3.is_cinema());
127 /// assert!(!ColorSpace::Bt709.is_cinema());
128 /// ```
129 #[must_use]
130 pub const fn is_cinema(&self) -> bool {
131 matches!(self, Self::DciP3)
132 }
133
134 /// Returns `true` if the color space is unknown.
135 ///
136 /// # Examples
137 ///
138 /// ```
139 /// use ff_format::color::ColorSpace;
140 ///
141 /// assert!(ColorSpace::Unknown.is_unknown());
142 /// assert!(!ColorSpace::Bt709.is_unknown());
143 /// ```
144 #[must_use]
145 pub const fn is_unknown(&self) -> bool {
146 matches!(self, Self::Unknown)
147 }
148}
149
150impl fmt::Display for ColorSpace {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 write!(f, "{}", self.name())
153 }
154}
155
156/// Color range defining the valid range of color values.
157///
158/// Video typically uses "limited" range where black is at level 16 and white
159/// at level 235 (for 8-bit). Computer graphics typically use "full" range
160/// where black is 0 and white is 255.
161///
162/// # Common Usage
163///
164/// - **Limited**: Broadcast video, Blu-ray, streaming services
165/// - **Full**: Computer graphics, screenshots, game capture
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
167#[non_exhaustive]
168pub enum ColorRange {
169 /// Limited/TV range (16-235 for Y, 16-240 for UV in 8-bit)
170 #[default]
171 Limited,
172 /// Full/PC range (0-255 for all components in 8-bit)
173 Full,
174 /// Color range is not specified or unknown
175 Unknown,
176}
177
178impl ColorRange {
179 /// Returns the name of the color range as a human-readable string.
180 ///
181 /// # Examples
182 ///
183 /// ```
184 /// use ff_format::color::ColorRange;
185 ///
186 /// assert_eq!(ColorRange::Limited.name(), "limited");
187 /// assert_eq!(ColorRange::Full.name(), "full");
188 /// ```
189 #[must_use]
190 pub const fn name(&self) -> &'static str {
191 match self {
192 Self::Limited => "limited",
193 Self::Full => "full",
194 Self::Unknown => "unknown",
195 }
196 }
197
198 /// Returns `true` if this is full (PC) range.
199 ///
200 /// # Examples
201 ///
202 /// ```
203 /// use ff_format::color::ColorRange;
204 ///
205 /// assert!(ColorRange::Full.is_full());
206 /// assert!(!ColorRange::Limited.is_full());
207 /// ```
208 #[must_use]
209 pub const fn is_full(&self) -> bool {
210 matches!(self, Self::Full)
211 }
212
213 /// Returns `true` if this is limited (TV) range.
214 ///
215 /// # Examples
216 ///
217 /// ```
218 /// use ff_format::color::ColorRange;
219 ///
220 /// assert!(ColorRange::Limited.is_limited());
221 /// assert!(!ColorRange::Full.is_limited());
222 /// ```
223 #[must_use]
224 pub const fn is_limited(&self) -> bool {
225 matches!(self, Self::Limited)
226 }
227
228 /// Returns `true` if the color range is unknown.
229 ///
230 /// # Examples
231 ///
232 /// ```
233 /// use ff_format::color::ColorRange;
234 ///
235 /// assert!(ColorRange::Unknown.is_unknown());
236 /// assert!(!ColorRange::Limited.is_unknown());
237 /// ```
238 #[must_use]
239 pub const fn is_unknown(&self) -> bool {
240 matches!(self, Self::Unknown)
241 }
242
243 /// Returns the minimum value for luma (Y) in 8-bit.
244 ///
245 /// # Examples
246 ///
247 /// ```
248 /// use ff_format::color::ColorRange;
249 ///
250 /// assert_eq!(ColorRange::Limited.luma_min_8bit(), 16);
251 /// assert_eq!(ColorRange::Full.luma_min_8bit(), 0);
252 /// ```
253 #[must_use]
254 pub const fn luma_min_8bit(&self) -> u8 {
255 match self {
256 Self::Limited => 16,
257 Self::Full | Self::Unknown => 0,
258 }
259 }
260
261 /// Returns the maximum value for luma (Y) in 8-bit.
262 ///
263 /// # Examples
264 ///
265 /// ```
266 /// use ff_format::color::ColorRange;
267 ///
268 /// assert_eq!(ColorRange::Limited.luma_max_8bit(), 235);
269 /// assert_eq!(ColorRange::Full.luma_max_8bit(), 255);
270 /// ```
271 #[must_use]
272 pub const fn luma_max_8bit(&self) -> u8 {
273 match self {
274 Self::Limited => 235,
275 Self::Full | Self::Unknown => 255,
276 }
277 }
278}
279
280impl fmt::Display for ColorRange {
281 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282 write!(f, "{}", self.name())
283 }
284}
285
286/// Color primaries defining the color gamut (the range of colors that can be represented).
287///
288/// Different standards define different primary colors (red, green, blue points)
289/// which determine the overall range of colors that can be displayed.
290///
291/// # Common Usage
292///
293/// - **BT.709**: HD content, same as sRGB primaries
294/// - **BT.601**: SD content (NTSC or PAL)
295/// - **BT.2020**: Wide color gamut for UHD/HDR
296#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
297#[non_exhaustive]
298pub enum ColorPrimaries {
299 /// ITU-R BT.709 primaries (same as sRGB, most common)
300 #[default]
301 Bt709,
302 /// ITU-R BT.601 primaries (SD video)
303 Bt601,
304 /// ITU-R BT.2020 primaries (wide color gamut for UHD/HDR)
305 Bt2020,
306 /// Color primaries are not specified or unknown
307 Unknown,
308}
309
310impl ColorPrimaries {
311 /// Returns the name of the color primaries as a human-readable string.
312 ///
313 /// # Examples
314 ///
315 /// ```
316 /// use ff_format::color::ColorPrimaries;
317 ///
318 /// assert_eq!(ColorPrimaries::Bt709.name(), "bt709");
319 /// assert_eq!(ColorPrimaries::Bt2020.name(), "bt2020");
320 /// ```
321 #[must_use]
322 pub const fn name(&self) -> &'static str {
323 match self {
324 Self::Bt709 => "bt709",
325 Self::Bt601 => "bt601",
326 Self::Bt2020 => "bt2020",
327 Self::Unknown => "unknown",
328 }
329 }
330
331 /// Returns `true` if this uses wide color gamut (BT.2020).
332 ///
333 /// # Examples
334 ///
335 /// ```
336 /// use ff_format::color::ColorPrimaries;
337 ///
338 /// assert!(ColorPrimaries::Bt2020.is_wide_gamut());
339 /// assert!(!ColorPrimaries::Bt709.is_wide_gamut());
340 /// ```
341 #[must_use]
342 pub const fn is_wide_gamut(&self) -> bool {
343 matches!(self, Self::Bt2020)
344 }
345
346 /// Returns `true` if the color primaries are unknown.
347 ///
348 /// # Examples
349 ///
350 /// ```
351 /// use ff_format::color::ColorPrimaries;
352 ///
353 /// assert!(ColorPrimaries::Unknown.is_unknown());
354 /// assert!(!ColorPrimaries::Bt709.is_unknown());
355 /// ```
356 #[must_use]
357 pub const fn is_unknown(&self) -> bool {
358 matches!(self, Self::Unknown)
359 }
360}
361
362impl fmt::Display for ColorPrimaries {
363 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
364 write!(f, "{}", self.name())
365 }
366}
367
368/// Color transfer characteristic (opto-electronic transfer function).
369///
370/// The transfer characteristic defines how scene luminance maps to the signal
371/// level stored in the video bitstream. Different HDR and SDR standards use
372/// different curves.
373///
374/// # Common Usage
375///
376/// - **`Bt709`**: Standard SDR video (HD television)
377/// - **`Pq`**: HDR10 and Dolby Vision (SMPTE ST 2084 / Perceptual Quantizer)
378/// - **`Hlg`**: Hybrid Log-Gamma — broadcast-compatible HDR (ARIB STD-B67)
379/// - **`Bt2020_10`** / **`Bt2020_12`**: BT.2020 SDR at 10/12-bit depth
380/// - **`Linear`**: Linear light, no gamma applied
381#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
382#[non_exhaustive]
383pub enum ColorTransfer {
384 /// ITU-R BT.709 transfer characteristic (standard SDR)
385 #[default]
386 Bt709,
387 /// ITU-R BT.2020 for 10-bit content
388 Bt2020_10,
389 /// ITU-R BT.2020 for 12-bit content
390 Bt2020_12,
391 /// Hybrid Log-Gamma (ARIB STD-B67) — broadcast HDR
392 Hlg,
393 /// Perceptual Quantizer / SMPTE ST 2084 — HDR10
394 Pq,
395 /// Linear light transfer (no gamma)
396 Linear,
397 /// Transfer characteristic is not specified or unknown
398 Unknown,
399}
400
401impl ColorTransfer {
402 /// Returns the name of the color transfer characteristic as a string.
403 ///
404 /// # Examples
405 ///
406 /// ```
407 /// use ff_format::color::ColorTransfer;
408 ///
409 /// assert_eq!(ColorTransfer::Bt709.name(), "bt709");
410 /// assert_eq!(ColorTransfer::Hlg.name(), "hlg");
411 /// assert_eq!(ColorTransfer::Pq.name(), "pq");
412 /// ```
413 #[must_use]
414 pub const fn name(&self) -> &'static str {
415 match self {
416 Self::Bt709 => "bt709",
417 Self::Bt2020_10 => "bt2020-10",
418 Self::Bt2020_12 => "bt2020-12",
419 Self::Hlg => "hlg",
420 Self::Pq => "pq",
421 Self::Linear => "linear",
422 Self::Unknown => "unknown",
423 }
424 }
425
426 /// Returns `true` if this is an HDR transfer characteristic (`Pq` or `Hlg`).
427 ///
428 /// # Examples
429 ///
430 /// ```
431 /// use ff_format::color::ColorTransfer;
432 ///
433 /// assert!(ColorTransfer::Pq.is_hdr());
434 /// assert!(ColorTransfer::Hlg.is_hdr());
435 /// assert!(!ColorTransfer::Bt709.is_hdr());
436 /// ```
437 #[must_use]
438 pub const fn is_hdr(&self) -> bool {
439 matches!(self, Self::Pq | Self::Hlg)
440 }
441
442 /// Returns `true` if this is Hybrid Log-Gamma (HLG).
443 ///
444 /// # Examples
445 ///
446 /// ```
447 /// use ff_format::color::ColorTransfer;
448 ///
449 /// assert!(ColorTransfer::Hlg.is_hlg());
450 /// assert!(!ColorTransfer::Pq.is_hlg());
451 /// ```
452 #[must_use]
453 pub const fn is_hlg(&self) -> bool {
454 matches!(self, Self::Hlg)
455 }
456
457 /// Returns `true` if this is Perceptual Quantizer / SMPTE ST 2084 (PQ).
458 ///
459 /// # Examples
460 ///
461 /// ```
462 /// use ff_format::color::ColorTransfer;
463 ///
464 /// assert!(ColorTransfer::Pq.is_pq());
465 /// assert!(!ColorTransfer::Hlg.is_pq());
466 /// ```
467 #[must_use]
468 pub const fn is_pq(&self) -> bool {
469 matches!(self, Self::Pq)
470 }
471
472 /// Returns `true` if the transfer characteristic is unknown.
473 ///
474 /// # Examples
475 ///
476 /// ```
477 /// use ff_format::color::ColorTransfer;
478 ///
479 /// assert!(ColorTransfer::Unknown.is_unknown());
480 /// assert!(!ColorTransfer::Bt709.is_unknown());
481 /// ```
482 #[must_use]
483 pub const fn is_unknown(&self) -> bool {
484 matches!(self, Self::Unknown)
485 }
486}
487
488impl fmt::Display for ColorTransfer {
489 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
490 write!(f, "{}", self.name())
491 }
492}
493
494#[cfg(test)]
495mod tests {
496 use super::*;
497
498 mod color_space_tests {
499 use super::*;
500
501 #[test]
502 fn test_names() {
503 assert_eq!(ColorSpace::Bt709.name(), "bt709");
504 assert_eq!(ColorSpace::Bt601.name(), "bt601");
505 assert_eq!(ColorSpace::Bt2020.name(), "bt2020");
506 assert_eq!(ColorSpace::DciP3.name(), "dcip3");
507 assert_eq!(ColorSpace::Srgb.name(), "srgb");
508 assert_eq!(ColorSpace::Unknown.name(), "unknown");
509 }
510
511 #[test]
512 fn test_display() {
513 assert_eq!(format!("{}", ColorSpace::Bt709), "bt709");
514 assert_eq!(format!("{}", ColorSpace::Bt2020), "bt2020");
515 }
516
517 #[test]
518 fn test_default() {
519 assert_eq!(ColorSpace::default(), ColorSpace::Bt709);
520 }
521
522 #[test]
523 fn test_is_hd_sd_uhd() {
524 assert!(ColorSpace::Bt709.is_hd());
525 assert!(!ColorSpace::Bt709.is_sd());
526 assert!(!ColorSpace::Bt709.is_uhd());
527
528 assert!(!ColorSpace::Bt601.is_hd());
529 assert!(ColorSpace::Bt601.is_sd());
530 assert!(!ColorSpace::Bt601.is_uhd());
531
532 assert!(!ColorSpace::Bt2020.is_hd());
533 assert!(!ColorSpace::Bt2020.is_sd());
534 assert!(ColorSpace::Bt2020.is_uhd());
535 }
536
537 #[test]
538 fn dcip3_is_cinema_should_return_true() {
539 assert!(ColorSpace::DciP3.is_cinema());
540 assert!(!ColorSpace::Bt709.is_cinema());
541 assert!(!ColorSpace::Bt2020.is_cinema());
542 }
543
544 #[test]
545 fn test_is_unknown() {
546 assert!(ColorSpace::Unknown.is_unknown());
547 assert!(!ColorSpace::Bt709.is_unknown());
548 }
549
550 #[test]
551 fn test_debug() {
552 assert_eq!(format!("{:?}", ColorSpace::Bt709), "Bt709");
553 assert_eq!(format!("{:?}", ColorSpace::Srgb), "Srgb");
554 }
555
556 #[test]
557 fn test_equality_and_hash() {
558 use std::collections::HashSet;
559
560 assert_eq!(ColorSpace::Bt709, ColorSpace::Bt709);
561 assert_ne!(ColorSpace::Bt709, ColorSpace::Bt601);
562
563 let mut set = HashSet::new();
564 set.insert(ColorSpace::Bt709);
565 set.insert(ColorSpace::Bt601);
566 assert!(set.contains(&ColorSpace::Bt709));
567 assert!(!set.contains(&ColorSpace::Bt2020));
568 }
569
570 #[test]
571 fn test_copy() {
572 let space = ColorSpace::Bt709;
573 let copied = space;
574 assert_eq!(space, copied);
575 }
576 }
577
578 mod color_range_tests {
579 use super::*;
580
581 #[test]
582 fn test_names() {
583 assert_eq!(ColorRange::Limited.name(), "limited");
584 assert_eq!(ColorRange::Full.name(), "full");
585 assert_eq!(ColorRange::Unknown.name(), "unknown");
586 }
587
588 #[test]
589 fn test_display() {
590 assert_eq!(format!("{}", ColorRange::Limited), "limited");
591 assert_eq!(format!("{}", ColorRange::Full), "full");
592 }
593
594 #[test]
595 fn test_default() {
596 assert_eq!(ColorRange::default(), ColorRange::Limited);
597 }
598
599 #[test]
600 fn test_is_full_limited() {
601 assert!(ColorRange::Full.is_full());
602 assert!(!ColorRange::Full.is_limited());
603
604 assert!(!ColorRange::Limited.is_full());
605 assert!(ColorRange::Limited.is_limited());
606 }
607
608 #[test]
609 fn test_is_unknown() {
610 assert!(ColorRange::Unknown.is_unknown());
611 assert!(!ColorRange::Limited.is_unknown());
612 }
613
614 #[test]
615 fn test_luma_values() {
616 assert_eq!(ColorRange::Limited.luma_min_8bit(), 16);
617 assert_eq!(ColorRange::Limited.luma_max_8bit(), 235);
618
619 assert_eq!(ColorRange::Full.luma_min_8bit(), 0);
620 assert_eq!(ColorRange::Full.luma_max_8bit(), 255);
621
622 assert_eq!(ColorRange::Unknown.luma_min_8bit(), 0);
623 assert_eq!(ColorRange::Unknown.luma_max_8bit(), 255);
624 }
625
626 #[test]
627 fn test_equality_and_hash() {
628 use std::collections::HashSet;
629
630 assert_eq!(ColorRange::Limited, ColorRange::Limited);
631 assert_ne!(ColorRange::Limited, ColorRange::Full);
632
633 let mut set = HashSet::new();
634 set.insert(ColorRange::Limited);
635 set.insert(ColorRange::Full);
636 assert!(set.contains(&ColorRange::Limited));
637 assert!(!set.contains(&ColorRange::Unknown));
638 }
639 }
640
641 mod color_primaries_tests {
642 use super::*;
643
644 #[test]
645 fn test_names() {
646 assert_eq!(ColorPrimaries::Bt709.name(), "bt709");
647 assert_eq!(ColorPrimaries::Bt601.name(), "bt601");
648 assert_eq!(ColorPrimaries::Bt2020.name(), "bt2020");
649 assert_eq!(ColorPrimaries::Unknown.name(), "unknown");
650 }
651
652 #[test]
653 fn test_display() {
654 assert_eq!(format!("{}", ColorPrimaries::Bt709), "bt709");
655 assert_eq!(format!("{}", ColorPrimaries::Bt2020), "bt2020");
656 }
657
658 #[test]
659 fn test_default() {
660 assert_eq!(ColorPrimaries::default(), ColorPrimaries::Bt709);
661 }
662
663 #[test]
664 fn test_is_wide_gamut() {
665 assert!(ColorPrimaries::Bt2020.is_wide_gamut());
666 assert!(!ColorPrimaries::Bt709.is_wide_gamut());
667 assert!(!ColorPrimaries::Bt601.is_wide_gamut());
668 }
669
670 #[test]
671 fn test_is_unknown() {
672 assert!(ColorPrimaries::Unknown.is_unknown());
673 assert!(!ColorPrimaries::Bt709.is_unknown());
674 }
675
676 #[test]
677 fn test_equality_and_hash() {
678 use std::collections::HashSet;
679
680 assert_eq!(ColorPrimaries::Bt709, ColorPrimaries::Bt709);
681 assert_ne!(ColorPrimaries::Bt709, ColorPrimaries::Bt2020);
682
683 let mut set = HashSet::new();
684 set.insert(ColorPrimaries::Bt709);
685 set.insert(ColorPrimaries::Bt2020);
686 assert!(set.contains(&ColorPrimaries::Bt709));
687 assert!(!set.contains(&ColorPrimaries::Bt601));
688 }
689 }
690
691 mod color_transfer_tests {
692 use super::*;
693
694 #[test]
695 fn test_names() {
696 assert_eq!(ColorTransfer::Bt709.name(), "bt709");
697 assert_eq!(ColorTransfer::Bt2020_10.name(), "bt2020-10");
698 assert_eq!(ColorTransfer::Bt2020_12.name(), "bt2020-12");
699 assert_eq!(ColorTransfer::Hlg.name(), "hlg");
700 assert_eq!(ColorTransfer::Pq.name(), "pq");
701 assert_eq!(ColorTransfer::Linear.name(), "linear");
702 assert_eq!(ColorTransfer::Unknown.name(), "unknown");
703 }
704
705 #[test]
706 fn test_display() {
707 assert_eq!(format!("{}", ColorTransfer::Hlg), "hlg");
708 assert_eq!(format!("{}", ColorTransfer::Pq), "pq");
709 assert_eq!(format!("{}", ColorTransfer::Bt709), "bt709");
710 }
711
712 #[test]
713 fn test_default() {
714 assert_eq!(ColorTransfer::default(), ColorTransfer::Bt709);
715 }
716
717 #[test]
718 fn hlg_is_hdr_should_return_true() {
719 assert!(ColorTransfer::Hlg.is_hdr());
720 assert!(ColorTransfer::Hlg.is_hlg());
721 assert!(!ColorTransfer::Hlg.is_pq());
722 }
723
724 #[test]
725 fn pq_is_hdr_should_return_true() {
726 assert!(ColorTransfer::Pq.is_hdr());
727 assert!(ColorTransfer::Pq.is_pq());
728 assert!(!ColorTransfer::Pq.is_hlg());
729 }
730
731 #[test]
732 fn sdr_transfers_are_not_hdr() {
733 assert!(!ColorTransfer::Bt709.is_hdr());
734 assert!(!ColorTransfer::Bt2020_10.is_hdr());
735 assert!(!ColorTransfer::Bt2020_12.is_hdr());
736 assert!(!ColorTransfer::Linear.is_hdr());
737 }
738
739 #[test]
740 fn is_unknown_should_only_match_unknown() {
741 assert!(ColorTransfer::Unknown.is_unknown());
742 assert!(!ColorTransfer::Bt709.is_unknown());
743 assert!(!ColorTransfer::Hlg.is_unknown());
744 }
745
746 #[test]
747 fn test_equality_and_hash() {
748 use std::collections::HashSet;
749
750 assert_eq!(ColorTransfer::Hlg, ColorTransfer::Hlg);
751 assert_ne!(ColorTransfer::Hlg, ColorTransfer::Pq);
752
753 let mut set = HashSet::new();
754 set.insert(ColorTransfer::Hlg);
755 set.insert(ColorTransfer::Pq);
756 assert!(set.contains(&ColorTransfer::Hlg));
757 assert!(!set.contains(&ColorTransfer::Bt709));
758 }
759 }
760}