oxideav_core/format.rs
1//! Media-type and sample/pixel format enumerations.
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4pub enum MediaType {
5 Audio,
6 Video,
7 Subtitle,
8 Data,
9 Unknown,
10}
11
12/// Audio sample format.
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub enum SampleFormat {
15 /// Unsigned 8-bit, interleaved.
16 U8,
17 /// Signed 8-bit, interleaved. Native format of Amiga 8SVX and MOD samples.
18 S8,
19 /// Signed 16-bit little-endian, interleaved.
20 S16,
21 /// Signed 24-bit packed (3 bytes/sample) little-endian, interleaved.
22 S24,
23 /// Signed 32-bit little-endian, interleaved.
24 S32,
25 /// 32-bit IEEE float, interleaved.
26 F32,
27 /// 64-bit IEEE float, interleaved.
28 F64,
29 /// Planar variants — one plane per channel.
30 U8P,
31 S16P,
32 S32P,
33 F32P,
34 F64P,
35}
36
37impl SampleFormat {
38 pub fn is_planar(&self) -> bool {
39 matches!(
40 self,
41 Self::U8P | Self::S16P | Self::S32P | Self::F32P | Self::F64P
42 )
43 }
44
45 /// Bytes per sample *per channel*.
46 pub fn bytes_per_sample(&self) -> usize {
47 match self {
48 Self::U8 | Self::U8P | Self::S8 => 1,
49 Self::S16 | Self::S16P => 2,
50 Self::S24 => 3,
51 Self::S32 | Self::S32P | Self::F32 | Self::F32P => 4,
52 Self::F64 | Self::F64P => 8,
53 }
54 }
55
56 pub fn is_float(&self) -> bool {
57 matches!(self, Self::F32 | Self::F64 | Self::F32P | Self::F64P)
58 }
59}
60
61/// Video pixel format.
62///
63/// The first six variants (`Yuv420P` through `Gray8`) are the original
64/// formats produced by the early codec crates. Everything beyond that is
65/// additional surface handled by `oxideav-pixfmt` and the still-image
66/// codecs (PNG, GIF, still-JPEG). The enum is `#[non_exhaustive]` so new
67/// variants can land without breaking downstream crates — consumers that
68/// match must include a wildcard arm.
69#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
70#[non_exhaustive]
71pub enum PixelFormat {
72 /// 8-bit YUV 4:2:0, planar (Y, U, V).
73 Yuv420P,
74 /// 8-bit YUV 4:2:2, planar.
75 Yuv422P,
76 /// 8-bit YUV 4:4:4, planar.
77 Yuv444P,
78 /// Packed 8-bit RGB, 3 bytes/pixel.
79 Rgb24,
80 /// Packed 8-bit RGBA, 4 bytes/pixel.
81 Rgba,
82 /// Packed 8-bit grayscale.
83 Gray8,
84
85 // --- Palette ---
86 /// 8-bit palette indices — companion palette carried out of band.
87 Pal8,
88
89 // --- Packed RGB/BGR swizzles ---
90 /// Packed 8-bit BGR, 3 bytes/pixel.
91 Bgr24,
92 /// Packed 8-bit BGRA, 4 bytes/pixel.
93 Bgra,
94 /// Packed 8-bit ARGB, 4 bytes/pixel (alpha first).
95 Argb,
96 /// Packed 8-bit ABGR, 4 bytes/pixel.
97 Abgr,
98
99 // --- Deeper packed RGB ---
100 /// Packed 16-bit-per-channel RGB, little-endian, 6 bytes/pixel.
101 Rgb48Le,
102 /// Packed 16-bit-per-channel RGBA, little-endian, 8 bytes/pixel.
103 Rgba64Le,
104
105 // --- Grayscale deeper / partial bit depths ---
106 /// 16-bit little-endian grayscale.
107 Gray16Le,
108 /// 10-bit grayscale in a 16-bit little-endian word.
109 Gray10Le,
110 /// 12-bit grayscale in a 16-bit little-endian word.
111 Gray12Le,
112
113 // --- Higher-precision YUV ---
114 /// 10-bit YUV 4:2:0 planar, little-endian 16-bit storage.
115 Yuv420P10Le,
116 /// 10-bit YUV 4:2:2 planar, little-endian 16-bit storage.
117 Yuv422P10Le,
118 /// 10-bit YUV 4:4:4 planar, little-endian 16-bit storage.
119 Yuv444P10Le,
120 /// 12-bit YUV 4:2:0 planar, little-endian 16-bit storage.
121 Yuv420P12Le,
122
123 // --- Full-range ("J") YUV ---
124 /// JPEG/full-range YUV 4:2:0 planar.
125 YuvJ420P,
126 /// JPEG/full-range YUV 4:2:2 planar.
127 YuvJ422P,
128 /// JPEG/full-range YUV 4:4:4 planar.
129 YuvJ444P,
130
131 // --- Semi-planar YUV ---
132 /// YUV 4:2:0, planar Y + interleaved UV (NV12).
133 Nv12,
134 /// YUV 4:2:0, planar Y + interleaved VU (NV21).
135 Nv21,
136
137 // --- Gray + alpha / YUV + alpha ---
138 /// Packed grayscale + alpha, 2 bytes/pixel (Y, A).
139 Ya8,
140 /// Yuv420P with an additional full-resolution alpha plane.
141 Yuva420P,
142
143 // --- Mono (1 bit per pixel) ---
144 /// 1 bit per pixel, packed MSB-first, 0 = black.
145 MonoBlack,
146 /// 1 bit per pixel, packed MSB-first, 0 = white.
147 MonoWhite,
148
149 // --- Interleaved YUV 4:2:2 ---
150 /// Packed 4:2:2, byte order Y0 U0 Y1 V0.
151 Yuyv422,
152 /// Packed 4:2:2, byte order U0 Y0 V0 Y1.
153 Uyvy422,
154
155 // --- Print / prepress ---
156 /// Packed 8-bit CMYK, 4 bytes/pixel in byte order C, M, Y, K.
157 /// "Regular" convention: C=0 means no cyan ink (white), C=255 means
158 /// full cyan. Used by JPEG 4-component scans from non-Adobe encoders
159 /// and by many print-side image toolchains. Adobe Photoshop's
160 /// inverted CMYK (where 0 = full ink) is a separate variant reserved
161 /// for a future `CmykInverted`.
162 Cmyk,
163}
164
165impl PixelFormat {
166 /// True if this format stores its components in separate planes.
167 pub fn is_planar(&self) -> bool {
168 matches!(
169 self,
170 Self::Yuv420P
171 | Self::Yuv422P
172 | Self::Yuv444P
173 | Self::Yuv420P10Le
174 | Self::Yuv422P10Le
175 | Self::Yuv444P10Le
176 | Self::Yuv420P12Le
177 | Self::YuvJ420P
178 | Self::YuvJ422P
179 | Self::YuvJ444P
180 | Self::Nv12
181 | Self::Nv21
182 | Self::Yuva420P
183 )
184 }
185
186 /// True if the format is a palette index format (`Pal8`).
187 pub fn is_palette(&self) -> bool {
188 matches!(self, Self::Pal8)
189 }
190
191 /// True if this format carries an alpha channel.
192 pub fn has_alpha(&self) -> bool {
193 matches!(
194 self,
195 Self::Rgba
196 | Self::Bgra
197 | Self::Argb
198 | Self::Abgr
199 | Self::Rgba64Le
200 | Self::Ya8
201 | Self::Yuva420P
202 )
203 }
204
205 /// Number of planes in the stored layout. Packed and palette formats
206 /// return 1; NV12/NV21 return 2; planar YUV without alpha returns 3;
207 /// YuvA variants return 4.
208 pub fn plane_count(&self) -> usize {
209 match self {
210 Self::Nv12 | Self::Nv21 => 2,
211 Self::Yuv420P
212 | Self::Yuv422P
213 | Self::Yuv444P
214 | Self::Yuv420P10Le
215 | Self::Yuv422P10Le
216 | Self::Yuv444P10Le
217 | Self::Yuv420P12Le
218 | Self::YuvJ420P
219 | Self::YuvJ422P
220 | Self::YuvJ444P => 3,
221 Self::Yuva420P => 4,
222 _ => 1,
223 }
224 }
225
226 /// Rough bits-per-pixel estimate, useful for buffer sizing. Not exact
227 /// for chroma-subsampled YUV — intended for worst-case preallocation
228 /// rather than wire-accurate accounting.
229 pub fn bits_per_pixel_approx(&self) -> u32 {
230 match self {
231 Self::MonoBlack | Self::MonoWhite => 1,
232 Self::Gray8 | Self::Pal8 => 8,
233 Self::Ya8 => 16,
234 Self::Gray16Le | Self::Gray10Le | Self::Gray12Le => 16,
235 Self::Rgb24 | Self::Bgr24 => 24,
236 Self::Rgba | Self::Bgra | Self::Argb | Self::Abgr => 32,
237 Self::Rgb48Le => 48,
238 Self::Rgba64Le => 64,
239 Self::Yuyv422 | Self::Uyvy422 => 16,
240 Self::Cmyk => 32,
241 // Planar YUV: 4:2:0 ≈ 12, 4:2:2 ≈ 16, 4:4:4 ≈ 24
242 // 10/12-bit variants double the byte count but we report the
243 // packed-bits-per-pixel estimate for a uniform heuristic.
244 Self::Yuv420P | Self::YuvJ420P | Self::Nv12 | Self::Nv21 => 12,
245 Self::Yuv422P | Self::YuvJ422P => 16,
246 Self::Yuv444P | Self::YuvJ444P => 24,
247 Self::Yuv420P10Le | Self::Yuv420P12Le => 24,
248 Self::Yuv422P10Le => 32,
249 Self::Yuv444P10Le => 48,
250 Self::Yuva420P => 20,
251 }
252 }
253}