1use crate::error::{Jpeg2000Error, Result};
6use byteorder::{BigEndian, ReadBytesExt};
7use std::io::Read;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Marker {
12 Soc = 0xFF4F,
14 Sot = 0xFF90,
16 Sod = 0xFF93,
18 Eoc = 0xFFD9,
20 Siz = 0xFF51,
22 Cod = 0xFF52,
24 Coc = 0xFF53,
26 Qcd = 0xFF5C,
28 Qcc = 0xFF5D,
30 Rgn = 0xFF5E,
32 Poc = 0xFF5F,
34 Plm = 0xFF57,
36 Plt = 0xFF58,
38 Ppm = 0xFF60,
40 Ppt = 0xFF61,
42 Crg = 0xFF63,
44 Com = 0xFF64,
46}
47
48impl Marker {
49 pub fn from_u16(value: u16) -> Result<Self> {
51 match value {
52 0xFF4F => Ok(Self::Soc),
53 0xFF90 => Ok(Self::Sot),
54 0xFF93 => Ok(Self::Sod),
55 0xFFD9 => Ok(Self::Eoc),
56 0xFF51 => Ok(Self::Siz),
57 0xFF52 => Ok(Self::Cod),
58 0xFF53 => Ok(Self::Coc),
59 0xFF5C => Ok(Self::Qcd),
60 0xFF5D => Ok(Self::Qcc),
61 0xFF5E => Ok(Self::Rgn),
62 0xFF5F => Ok(Self::Poc),
63 0xFF57 => Ok(Self::Plm),
64 0xFF58 => Ok(Self::Plt),
65 0xFF60 => Ok(Self::Ppm),
66 0xFF61 => Ok(Self::Ppt),
67 0xFF63 => Ok(Self::Crg),
68 0xFF64 => Ok(Self::Com),
69 _ => Err(Jpeg2000Error::InvalidMarker(value)),
70 }
71 }
72
73 pub fn has_segment(&self) -> bool {
75 !matches!(self, Self::Soc | Self::Sod | Self::Eoc)
76 }
77}
78
79#[derive(Debug, Clone)]
81pub struct ImageSize {
82 pub width: u32,
84 pub height: u32,
86 pub x_offset: u32,
88 pub y_offset: u32,
90 pub tile_width: u32,
92 pub tile_height: u32,
94 pub tile_x_offset: u32,
96 pub tile_y_offset: u32,
98 pub num_components: u16,
100 pub components: Vec<ComponentSize>,
102}
103
104#[derive(Debug, Clone)]
106pub struct ComponentSize {
107 pub precision: u8,
109 pub is_signed: bool,
111 pub dx: u8,
113 pub dy: u8,
115}
116
117impl ImageSize {
118 pub fn parse<R: Read>(reader: &mut R, length: u16) -> Result<Self> {
120 let _capability = reader.read_u16::<BigEndian>()?;
121 let width = reader.read_u32::<BigEndian>()?;
122 let height = reader.read_u32::<BigEndian>()?;
123 let x_offset = reader.read_u32::<BigEndian>()?;
124 let y_offset = reader.read_u32::<BigEndian>()?;
125 let tile_width = reader.read_u32::<BigEndian>()?;
126 let tile_height = reader.read_u32::<BigEndian>()?;
127 let tile_x_offset = reader.read_u32::<BigEndian>()?;
128 let tile_y_offset = reader.read_u32::<BigEndian>()?;
129 let num_components = reader.read_u16::<BigEndian>()?;
130
131 if num_components == 0 {
132 return Err(Jpeg2000Error::InvalidImageHeader(
133 "Number of components must be > 0".to_string(),
134 ));
135 }
136
137 let expected_length = 36 + (num_components as usize * 3);
140 if length as usize != expected_length {
141 return Err(Jpeg2000Error::InvalidImageHeader(format!(
142 "Invalid SIZ segment length: expected {}, got {}",
143 expected_length, length
144 )));
145 }
146
147 let mut components = Vec::with_capacity(num_components as usize);
148 for _ in 0..num_components {
149 let ssiz = reader.read_u8()?;
150 let dx = reader.read_u8()?;
151 let dy = reader.read_u8()?;
152
153 let is_signed = (ssiz & 0x80) != 0;
154 let precision = (ssiz & 0x7F) + 1;
155
156 components.push(ComponentSize {
157 precision,
158 is_signed,
159 dx,
160 dy,
161 });
162 }
163
164 Ok(Self {
165 width,
166 height,
167 x_offset,
168 y_offset,
169 tile_width,
170 tile_height,
171 tile_x_offset,
172 tile_y_offset,
173 num_components,
174 components,
175 })
176 }
177
178 pub fn num_tiles_x(&self) -> u32 {
180 (self.width + self.tile_width - 1 - self.tile_x_offset) / self.tile_width
181 }
182
183 pub fn num_tiles_y(&self) -> u32 {
185 (self.height + self.tile_height - 1 - self.tile_y_offset) / self.tile_height
186 }
187
188 pub fn num_tiles(&self) -> u32 {
190 self.num_tiles_x() * self.num_tiles_y()
191 }
192}
193
194#[derive(Debug, Clone)]
196pub struct CodingStyle {
197 pub progression_order: ProgressionOrder,
199 pub num_layers: u16,
201 pub use_mct: bool,
203 pub num_levels: u8,
205 pub code_block_width: u8,
207 pub code_block_height: u8,
209 pub code_block_style: u8,
211 pub wavelet: WaveletTransform,
213}
214
215#[derive(Debug, Clone, Copy, PartialEq, Eq)]
217pub enum ProgressionOrder {
218 Lrcp = 0,
220 Rlcp = 1,
222 Rpcl = 2,
224 Pcrl = 3,
226 Cprl = 4,
228}
229
230impl ProgressionOrder {
231 pub fn from_u8(value: u8) -> Result<Self> {
233 match value {
234 0 => Ok(Self::Lrcp),
235 1 => Ok(Self::Rlcp),
236 2 => Ok(Self::Rpcl),
237 3 => Ok(Self::Pcrl),
238 4 => Ok(Self::Cprl),
239 _ => Err(Jpeg2000Error::CodestreamError(format!(
240 "Invalid progression order: {}",
241 value
242 ))),
243 }
244 }
245}
246
247#[derive(Debug, Clone, Copy, PartialEq, Eq)]
249pub enum WaveletTransform {
250 Irreversible97,
252 Reversible53,
254}
255
256impl WaveletTransform {
257 pub fn from_u8(value: u8) -> Result<Self> {
259 match value {
260 0 => Ok(Self::Irreversible97),
261 1 => Ok(Self::Reversible53),
262 _ => Err(Jpeg2000Error::CodestreamError(format!(
263 "Invalid wavelet transform: {}",
264 value
265 ))),
266 }
267 }
268}
269
270impl CodingStyle {
271 pub fn parse<R: Read>(reader: &mut R, _length: u16) -> Result<Self> {
273 let scod = reader.read_u8()?;
274 let progression_order = ProgressionOrder::from_u8(reader.read_u8()?)?;
275 let num_layers = reader.read_u16::<BigEndian>()?;
276 let mct = reader.read_u8()?;
277 let num_levels = reader.read_u8()?;
278 let code_block_width = reader.read_u8()?;
279 let code_block_height = reader.read_u8()?;
280 let code_block_style = reader.read_u8()?;
281 let wavelet = WaveletTransform::from_u8(reader.read_u8()?)?;
282
283 let use_mct = mct != 0;
284
285 if (scod & 0x01) != 0 {
287 return Err(Jpeg2000Error::UnsupportedFeature(
289 "Custom precinct sizes not yet supported".to_string(),
290 ));
291 }
292
293 Ok(Self {
294 progression_order,
295 num_layers,
296 use_mct,
297 num_levels,
298 code_block_width,
299 code_block_height,
300 code_block_style,
301 wavelet,
302 })
303 }
304}
305
306#[derive(Debug, Clone)]
308pub struct Quantization {
309 pub style: QuantizationStyle,
311 pub step_sizes: Vec<u16>,
313}
314
315#[derive(Debug, Clone, Copy, PartialEq, Eq)]
317pub enum QuantizationStyle {
318 NoQuantization,
320 ScalarDerived,
322 ScalarExpounded,
324}
325
326impl QuantizationStyle {
327 pub fn from_u8(value: u8) -> Result<Self> {
329 match value & 0x1F {
330 0 => Ok(Self::NoQuantization),
331 1 => Ok(Self::ScalarDerived),
332 2 => Ok(Self::ScalarExpounded),
333 _ => Err(Jpeg2000Error::CodestreamError(format!(
334 "Invalid quantization style: {}",
335 value
336 ))),
337 }
338 }
339}
340
341impl Quantization {
342 pub fn parse<R: Read>(reader: &mut R, length: u16) -> Result<Self> {
344 let sqcd = reader.read_u8()?;
345 let style = QuantizationStyle::from_u8(sqcd)?;
346
347 let mut step_sizes = Vec::new();
348 let remaining = (length - 1) as usize;
349
350 match style {
351 QuantizationStyle::NoQuantization | QuantizationStyle::ScalarDerived => {
352 for _ in 0..remaining {
354 step_sizes.push(u16::from(reader.read_u8()?));
355 }
356 }
357 QuantizationStyle::ScalarExpounded => {
358 for _ in 0..(remaining / 2) {
360 step_sizes.push(reader.read_u16::<BigEndian>()?);
361 }
362 }
363 }
364
365 Ok(Self { style, step_sizes })
366 }
367}
368
369pub struct CodestreamParser<R> {
371 reader: R,
372}
373
374impl<R: Read> CodestreamParser<R> {
375 pub fn new(reader: R) -> Self {
377 Self { reader }
378 }
379
380 pub fn read_marker(&mut self) -> Result<Option<Marker>> {
382 match self.reader.read_u16::<BigEndian>() {
383 Ok(value) => Ok(Some(Marker::from_u16(value)?)),
384 Err(ref e) if e.kind() == std::io::ErrorKind::UnexpectedEof => Ok(None),
385 Err(e) => Err(e.into()),
386 }
387 }
388
389 pub fn read_segment_length(&mut self) -> Result<u16> {
391 let length = self.reader.read_u16::<BigEndian>()?;
392 if length < 2 {
394 return Err(Jpeg2000Error::CodestreamError(format!(
395 "Invalid segment length: {}",
396 length
397 )));
398 }
399 Ok(length - 2)
400 }
401
402 pub fn skip_segment(&mut self, length: u16) -> Result<()> {
404 let mut buffer = vec![0u8; length as usize];
405 self.reader.read_exact(&mut buffer)?;
406 Ok(())
407 }
408
409 pub fn parse_siz(&mut self) -> Result<ImageSize> {
411 let length = self.read_segment_length()?;
412 ImageSize::parse(&mut self.reader, length)
413 }
414
415 pub fn parse_cod(&mut self) -> Result<CodingStyle> {
417 let length = self.read_segment_length()?;
418 CodingStyle::parse(&mut self.reader, length)
419 }
420
421 pub fn parse_qcd(&mut self) -> Result<Quantization> {
423 let length = self.read_segment_length()?;
424 Quantization::parse(&mut self.reader, length)
425 }
426}
427
428#[cfg(test)]
429mod tests {
430 use super::*;
431
432 #[test]
433 fn test_marker_conversion() {
434 assert_eq!(Marker::from_u16(0xFF4F).ok(), Some(Marker::Soc));
435 assert_eq!(Marker::from_u16(0xFFD9).ok(), Some(Marker::Eoc));
436 assert!(Marker::from_u16(0x0000).is_err());
437 }
438
439 #[test]
440 fn test_progression_order() {
441 assert_eq!(
442 ProgressionOrder::from_u8(0).ok(),
443 Some(ProgressionOrder::Lrcp)
444 );
445 assert_eq!(
446 ProgressionOrder::from_u8(4).ok(),
447 Some(ProgressionOrder::Cprl)
448 );
449 assert!(ProgressionOrder::from_u8(5).is_err());
450 }
451
452 #[test]
453 fn test_wavelet_transform() {
454 assert_eq!(
455 WaveletTransform::from_u8(0).ok(),
456 Some(WaveletTransform::Irreversible97)
457 );
458 assert_eq!(
459 WaveletTransform::from_u8(1).ok(),
460 Some(WaveletTransform::Reversible53)
461 );
462 assert!(WaveletTransform::from_u8(2).is_err());
463 }
464}