1use std::fmt::Display;
7use std::io::{Read, Seek, Write};
8use std::str::FromStr;
9
10use crate::headers::NitfSegmentHeader;
11use crate::types::{ExtendedSubheader, NitfField, Security};
12use crate::{NitfError, NitfResult};
13
14#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
16pub struct ImageHeader {
17 pub im: NitfField<IM>,
19 pub iid1: NitfField<String>,
21 pub idatim: NitfField<String>,
23 pub tgtid: NitfField<String>,
25 pub iid2: NitfField<String>,
27 pub security: Security,
29 pub encryp: NitfField<String>,
31 pub isorce: NitfField<String>,
33 pub nrows: NitfField<u32>,
35 pub ncols: NitfField<u32>,
37 pub pvtype: NitfField<PixelValueType>,
39 pub irep: NitfField<ImageRepresentation>,
41 pub icat: NitfField<String>,
43 pub abpp: NitfField<u8>,
45 pub pjust: NitfField<PixelJustification>,
47 pub icords: NitfField<CoordinateRepresentation>,
49 pub igeolo: NitfField<String>,
51 pub nicom: NitfField<u8>,
53 pub icoms: Vec<NitfField<String>>,
55 pub ic: NitfField<Compression>,
57 pub comrat: NitfField<String>,
59 pub nbands: NitfField<u8>,
61 pub xbands: NitfField<u32>,
63 pub bands: Vec<Band>,
65 pub isync: NitfField<u8>,
67 pub imode: NitfField<Mode>,
69 pub nbpr: NitfField<u16>,
71 pub nbpc: NitfField<u16>,
73 pub nppbh: NitfField<u16>,
75 pub nppbv: NitfField<u16>,
77 pub nbpp: NitfField<u8>,
79 pub idlvl: NitfField<u16>,
81 pub ialvl: NitfField<u16>,
83 pub iloc: NitfField<String>,
85 pub imag: NitfField<String>,
87 pub udidl: NitfField<u32>,
89 pub udofl: NitfField<u16>,
91 pub udid: ExtendedSubheader,
93 pub ixshdl: NitfField<u32>,
95 pub ixsofl: NitfField<u16>,
97 pub ixshd: ExtendedSubheader,
99}
100impl Default for ImageHeader {
101 fn default() -> Self {
102 Self {
103 im: NitfField::init(2u8, "IM"),
104 iid1: NitfField::init(10u8, "IID1"),
105 idatim: NitfField::init(14u8, "IDATIM"),
106 tgtid: NitfField::init(17u8, "TGTID"),
107 iid2: NitfField::init(80u8, "IID2"),
108 security: Security::default(),
109 encryp: NitfField::init(1u8, "ENCRYP"),
110 isorce: NitfField::init(42u8, "ISORCE"),
111 nrows: NitfField::init(8u8, "NROWS"),
112 ncols: NitfField::init(8u8, "NCOLS"),
113 pvtype: NitfField::init(3u8, "PVTYPE"),
114 irep: NitfField::init(8u8, "IREP"),
115 icat: NitfField::init(8u8, "ICAT"),
116 abpp: NitfField::init(2u8, "ABPP"),
117 pjust: NitfField::init(1u8, "PJUST"),
118 icords: NitfField::init(1u8, "ICORDS"),
119 igeolo: NitfField::init(60u8, "IGEOLO"),
120 nicom: NitfField::init(1u8, "NICOM"),
121 icoms: vec![],
122 ic: NitfField::init(2u8, "IC"),
123 comrat: NitfField::init(4u8, "COMRAT"),
124 nbands: NitfField::init(1u8, "NBANDS"),
125 xbands: NitfField::init(5u8, "XBANDS"),
126 bands: vec![],
127 isync: NitfField::init(1u8, "ISYNC"),
128 imode: NitfField::init(1u8, "IMODE"),
129 nbpr: NitfField::init(4u8, "NBPR"),
130 nbpc: NitfField::init(4u8, "NBPC"),
131 nppbh: NitfField::init(4u8, "NPPBH"),
132 nppbv: NitfField::init(4u8, "NPPBV"),
133 nbpp: NitfField::init(2u8, "NBPP"),
134 idlvl: NitfField::init(3u8, "IDLVL"),
135 ialvl: NitfField::init(3u8, "IALVL"),
136 iloc: NitfField::init(10u8, "ILOC"),
137 imag: NitfField::init(4u8, "IMAG"),
138 udidl: NitfField::init(5u8, "UDIDL"),
139 udofl: NitfField::init(3u8, "UDOFL"),
140 udid: ExtendedSubheader::init("UDID"),
141 ixshdl: NitfField::init(5u8, "IXSHDL"),
142 ixsofl: NitfField::init(3u8, "IXSOFL"),
143 ixshd: ExtendedSubheader::init("IXSHD"),
144 }
145 }
146}
147
148#[derive(Default, Clone, Debug, Eq, PartialEq, Copy, Ord, PartialOrd)]
149pub enum IM {
150 #[default]
151 IM,
152}
153impl FromStr for IM {
154 type Err = NitfError;
155 fn from_str(s: &str) -> Result<Self, Self::Err> {
156 match s {
157 "IM" => Ok(Self::default()),
158 _ => Err(NitfError::ParseError("IM".to_string())),
159 }
160 }
161}
162impl Display for IM {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 write!(f, "IM")
165 }
166}
167
168#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
172pub struct Band {
173 pub irepband: NitfField<ImageRepresentationBand>,
175 pub isubcat: NitfField<String>, pub ifc: NitfField<ImageFilterCondition>, pub imflt: NitfField<String>, pub nluts: NitfField<u8>, pub nelut: NitfField<u16>,
185 pub lutd: Vec<Vec<u8>>,
187}
188impl Default for Band {
189 fn default() -> Self {
190 Self {
191 irepband: NitfField::init(2u8, "IREPBAND"),
192 isubcat: NitfField::init(6u8, "ISUBCAT"),
193 ifc: NitfField::init(1u8, "IFC"),
194 imflt: NitfField::init(3u8, "IMFLT"),
195 nluts: NitfField::init(1u8, "NLUTS"),
196 nelut: NitfField::init(5u8, "NELUT"),
197 lutd: vec![],
198 }
199 }
200}
201impl Band {
202 pub fn length(&self) -> usize {
203 let mut length = 0;
204 length += self.irepband.length;
205 length += self.isubcat.length;
206 length += self.ifc.length;
207 length += self.imflt.length;
208 length += self.nluts.length;
209 if self.nluts.val != 0 {
210 length += self.nelut.length;
211 length += (self.nelut.val * self.nluts.val as u16) as usize;
213 }
214 length
215 }
216}
217
218#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
220pub enum PixelValueType {
221 #[default]
222 C,
224 R,
226 B,
228 SI,
230 INT,
232}
233
234#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
236pub enum ImageRepresentation {
237 #[default]
238 MONO,
240 RGB,
242 RGBLUT,
244 MULTI,
246 NODISPLY,
248 NVECTOR,
250 POLAR,
252 VPH,
254 YCbCr601,
256}
257#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
259pub enum ImageRepresentationBand {
260 #[default]
261 DEFAULT,
263 M,
265 R,
267 G,
268 B,
269 LU,
271 Y,
273 Cb,
275 Cr,
277}
278#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
279pub enum ImageFilterCondition {
280 #[default]
281 N,
283}
284
285#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
287pub enum PixelJustification {
288 #[default]
289 R,
291 L,
293}
294
295#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
297pub enum CoordinateRepresentation {
298 #[default]
299 DEFAULT,
301 U,
303 N,
305 S,
307 P,
309 G,
311 D,
313}
314
315#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
317pub enum Compression {
318 #[default]
319 NC,
321 NM,
323 C1,
325 C3,
327 C4,
329 C5,
331 C6,
333 C7,
335 C8,
337 I1,
339 M1,
341 M3,
343 M4,
345 M5,
347 M6,
349 M7,
351 M8,
353}
354
355#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
357pub enum Mode {
358 #[default]
359 B,
361 P,
363 R,
365 S,
367}
368
369fn read_bands(reader: &mut (impl Read + Seek), n_band: u32) -> NitfResult<Vec<Band>> {
372 let mut bands: Vec<Band> = vec![Band::default(); n_band as usize];
373 for band in &mut bands {
374 band.irepband.read(reader)?;
375 band.isubcat.read(reader)?;
376 band.ifc.read(reader)?;
377 band.imflt.read(reader)?;
378 band.nluts.read(reader)?;
379 if band.nluts.val != 0 {
380 band.nelut.read(reader)?;
381 band.lutd = vec![vec![0; band.nelut.val as usize]; band.nluts.val as usize];
383 for lut in band.lutd.iter_mut() {
384 reader
387 .read_exact(lut)
388 .or(Err(NitfError::ReadFatal("LUTD".to_string())))?;
389 }
390 }
391 }
392 Ok(bands)
393}
394fn write_bands(writer: &mut (impl Write + Seek), bands: &Vec<Band>) -> NitfResult<usize> {
396 let mut bytes_written = 0;
397 for band in bands {
398 bytes_written += band.irepband.write(writer)?;
399 bytes_written += band.isubcat.write(writer)?;
400 bytes_written += band.ifc.write(writer)?;
401 bytes_written += band.imflt.write(writer)?;
402 bytes_written += band.nluts.write(writer)?;
403 if band.nluts.val != 0 {
404 band.nelut.write(writer)?;
405 for lut in band.lutd.iter() {
406 bytes_written += writer.write(lut).map_err(NitfError::IOError)?
407 }
408 }
409 }
410 Ok(bytes_written)
411}
412fn is_comrat(compression: &Compression) -> bool {
413 matches!(
414 compression,
415 Compression::C1
416 | Compression::C3
417 | Compression::C4
418 | Compression::C5
419 | Compression::C8
420 | Compression::M1
421 | Compression::M3
422 | Compression::M4
423 | Compression::M5
424 | Compression::M8
425 | Compression::I1
426 )
427}
428
429impl NitfSegmentHeader for ImageHeader {
431 fn read(&mut self, reader: &mut (impl Read + Seek)) -> NitfResult<()> {
432 self.im.read(reader)?;
433 self.iid1.read(reader)?;
434 self.idatim.read(reader)?;
435 self.tgtid.read(reader)?;
436 self.iid2.read(reader)?;
437 self.security.read(reader)?;
438 self.encryp.read(reader)?;
439 self.isorce.read(reader)?;
440 self.nrows.read(reader)?;
441 self.ncols.read(reader)?;
442 self.pvtype.read(reader)?;
443 self.irep.read(reader)?;
444 self.icat.read(reader)?;
445 self.abpp.read(reader)?;
446 self.pjust.read(reader)?;
447 self.icords.read(reader)?;
448 if self.icords.val != CoordinateRepresentation::DEFAULT {
449 self.igeolo.read(reader)?;
450 }
451 self.nicom.read(reader)?;
452 self.icoms = vec![NitfField::init(80u8, "ICOM"); self.nicom.val.into()];
453 self.icoms.iter_mut().try_for_each(|com| com.read(reader))?;
454
455 self.ic.read(reader)?;
456 if is_comrat(&self.ic.val) {
457 self.comrat.read(reader)?;
458 }
459 self.nbands.read(reader)?;
460 if self.nbands.val != 0 {
462 self.bands = read_bands(reader, self.nbands.val as u32)?;
463 } else {
464 self.xbands.read(reader)?;
465 self.bands = read_bands(reader, self.xbands.val)?;
466 }
467 self.isync.read(reader)?;
468 self.imode.read(reader)?;
469 self.nbpr.read(reader)?;
470 self.nbpc.read(reader)?;
471 self.nppbh.read(reader)?;
472 self.nppbv.read(reader)?;
473 self.nbpp.read(reader)?;
474 self.idlvl.read(reader)?;
475 self.ialvl.read(reader)?;
476 self.iloc.read(reader)?;
477 self.imag.read(reader)?;
478 self.udidl.read(reader)?;
479 if self.udidl.val != 0 {
480 self.udofl.read(reader)?;
481 self.udid.read(reader, (self.udidl.val - 3) as usize)?;
482 }
483 self.ixshdl.read(reader)?;
484 if self.ixshdl.val != 0 {
485 self.ixsofl.read(reader)?;
486 self.ixshd.read(reader, (self.ixshdl.val - 3) as usize)?;
487 }
488 Ok(())
489 }
490 fn write(&self, writer: &mut (impl Write + Seek)) -> NitfResult<usize> {
491 let mut bytes_written = 0;
492 bytes_written += self.im.write(writer)?;
493 bytes_written += self.iid1.write(writer)?;
494 bytes_written += self.idatim.write(writer)?;
495 bytes_written += self.tgtid.write(writer)?;
496 bytes_written += self.iid2.write(writer)?;
497 bytes_written += self.security.write(writer)?;
498 bytes_written += self.encryp.write(writer)?;
499 bytes_written += self.isorce.write(writer)?;
500 bytes_written += self.nrows.write(writer)?;
501 bytes_written += self.ncols.write(writer)?;
502 bytes_written += self.pvtype.write(writer)?;
503 bytes_written += self.irep.write(writer)?;
504 bytes_written += self.icat.write(writer)?;
505 bytes_written += self.abpp.write(writer)?;
506 bytes_written += self.pjust.write(writer)?;
507 bytes_written += self.icords.write(writer)?;
508 if self.icords.val != CoordinateRepresentation::DEFAULT {
509 bytes_written += self.igeolo.write(writer)?;
510 }
511 self.nicom.write(writer)?;
512 for comment in &self.icoms {
513 bytes_written += comment.write(writer)?;
514 }
515
516 bytes_written += self.ic.write(writer)?;
517 if is_comrat(&self.ic.val) {
518 bytes_written += self.comrat.write(writer)?;
519 }
520 bytes_written += self.nbands.write(writer)?;
521 if self.nbands.val == 0 {
523 bytes_written += self.xbands.write(writer)?;
524 }
525 bytes_written += write_bands(writer, &self.bands)?;
526 bytes_written += self.isync.write(writer)?;
527 bytes_written += self.imode.write(writer)?;
528 bytes_written += self.nbpr.write(writer)?;
529 bytes_written += self.nbpc.write(writer)?;
530 bytes_written += self.nppbh.write(writer)?;
531 bytes_written += self.nppbv.write(writer)?;
532 bytes_written += self.nbpp.write(writer)?;
533 bytes_written += self.idlvl.write(writer)?;
534 bytes_written += self.ialvl.write(writer)?;
535 bytes_written += self.iloc.write(writer)?;
536 bytes_written += self.imag.write(writer)?;
537 bytes_written += self.udidl.write(writer)?;
538 if self.udidl.val != 0 {
539 bytes_written += self.udofl.write(writer)?;
540 bytes_written += self.udid.write(writer)?;
541 }
542 bytes_written += self.ixshdl.write(writer)?;
543 if self.ixshdl.val != 0 {
544 bytes_written += self.ixsofl.write(writer)?;
545 bytes_written += self.ixshd.write(writer)?;
546 }
547 Ok(bytes_written)
548 }
549 fn length(&self) -> usize {
550 let mut length = 0;
551 length += self.im.length;
552 length += self.iid1.length;
553 length += self.idatim.length;
554 length += self.tgtid.length;
555 length += self.iid2.length;
556 length += self.security.length();
557 length += self.encryp.length;
558 length += self.isorce.length;
559 length += self.nrows.length;
560 length += self.ncols.length;
561 length += self.pvtype.length;
562 length += self.irep.length;
563 length += self.icat.length;
564 length += self.abpp.length;
565 length += self.pjust.length;
566 length += self.icords.length;
567 if self.icords.val != CoordinateRepresentation::DEFAULT {
568 length += self.igeolo.length;
569 }
570 length += self.nicom.length;
571 for comment in &self.icoms {
572 length += comment.length;
573 }
574
575 length += self.ic.length;
576 if is_comrat(&self.ic.val) {
577 length += self.comrat.length;
578 }
579 length += self.nbands.length;
580 if self.nbands.val == 0 {
582 length += self.xbands.length;
583 }
584 length += &self.bands.iter().map(|b| b.length()).sum();
585 length += self.isync.length;
586 length += self.imode.length;
587 length += self.nbpr.length;
588 length += self.nbpc.length;
589 length += self.nppbh.length;
590 length += self.nppbv.length;
591 length += self.nbpp.length;
592 length += self.idlvl.length;
593 length += self.ialvl.length;
594 length += self.iloc.length;
595 length += self.imag.length;
596 length += self.udidl.length;
597 length += self.udidl.val as usize;
598 length += self.ixshdl.length;
599 length += self.ixshdl.val as usize;
600 length
601 }
602}
603impl Display for ImageHeader {
604 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
605 let mut out_str = String::default();
606 out_str += format!("{}, ", self.im).as_ref();
607 out_str += format!("{}, ", self.iid1).as_ref();
608 out_str += format!("{}, ", self.idatim).as_ref();
609 out_str += format!("{}, ", self.tgtid).as_ref();
610 out_str += format!("{}, ", self.iid2).as_ref();
611 out_str += format!("SECURITY: [{}], ", self.security).as_ref();
612 out_str += format!("{}, ", self.encryp).as_ref();
613 out_str += format!("{}, ", self.isorce).as_ref();
614 out_str += format!("{}, ", self.nrows).as_ref();
615 out_str += format!("{}, ", self.ncols).as_ref();
616 out_str += format!("{}, ", self.pvtype).as_ref();
617 out_str += format!("{}, ", self.irep).as_ref();
618 out_str += format!("{}, ", self.icat).as_ref();
619 out_str += format!("{}, ", self.abpp).as_ref();
620 out_str += format!("{}, ", self.pjust).as_ref();
621 out_str += format!("{}, ", self.icords).as_ref();
622 if self.icords.val != CoordinateRepresentation::DEFAULT {
623 out_str += format!("{}, ", self.igeolo).as_ref();
624 }
625 out_str += format!("{}, ", self.nicom).as_ref();
626 for (i_com, com) in self.icoms.iter().enumerate() {
627 out_str += format!("ICOM {i_com}: {com},",).as_ref();
628 }
629 out_str += format!("{}, ", self.ic).as_ref();
630 if is_comrat(&self.ic.val) {
631 out_str += format!("{}, ", self.comrat).as_ref();
632 }
633 out_str += format!("{}, ", self.nbands).as_ref();
634 for (i_band, band) in self.bands.iter().enumerate() {
635 out_str += format!("BAND {i_band}: [{band}], ").as_ref();
636 }
637 out_str += format!("{}, ", self.isync).as_ref();
638 out_str += format!("{}, ", self.imode).as_ref();
639 out_str += format!("{}, ", self.nbpr).as_ref();
640 out_str += format!("{}, ", self.nbpc).as_ref();
641 out_str += format!("{}, ", self.nppbh).as_ref();
642 out_str += format!("{}, ", self.nppbv).as_ref();
643 out_str += format!("{}, ", self.nbpp).as_ref();
644 out_str += format!("{}, ", self.idlvl).as_ref();
645 out_str += format!("{}, ", self.ialvl).as_ref();
646 out_str += format!("{}, ", self.iloc).as_ref();
647 out_str += format!("{}, ", self.imag).as_ref();
648 out_str += format!("{}, ", self.udidl).as_ref();
649 if self.udidl.val != 0 {
650 out_str += format!("{}, ", self.udofl).as_ref();
651 out_str += format!("{}, ", self.udid).as_ref();
652 }
653 out_str += format!("{}, ", self.ixshdl).as_ref();
654 if self.ixshdl.val != 0 {
655 out_str += format!("{}, ", self.ixsofl).as_ref();
656 out_str += format!("{}", self.ixshd).as_ref();
657 }
658 write!(f, "Image Header: {out_str}")
659 }
660}
661impl Display for Band {
662 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
663 let mut out_str = String::default();
664 out_str += format!("{}, ", self.irepband).as_ref();
665 out_str += format!("{}, ", self.isubcat).as_ref();
666 out_str += format!("{}, ", self.ifc).as_ref();
667 out_str += format!("{}, ", self.imflt).as_ref();
668 out_str += format!("{}, ", self.nluts).as_ref();
669 if self.nluts.val != 0 {
670 out_str += format!("{}, ", self.nelut).as_ref();
671 for (i_lut, lut) in self.lutd.iter().enumerate() {
672 for (i_elem, elem) in lut.iter().enumerate() {
673 out_str += format!("LUT{i_lut}{i_elem}: {elem:<3X}, ").as_ref();
674 }
675 }
676 }
677 write!(f, "{out_str}")
678 }
679}
680impl FromStr for PixelValueType {
681 type Err = NitfError;
682 fn from_str(s: &str) -> Result<Self, Self::Err> {
683 match s {
684 "INT" => Ok(Self::INT),
685 "B" => Ok(Self::B),
686 "SI" => Ok(Self::SI),
687 "R" => Ok(Self::R),
688 "C" => Ok(Self::C),
689 _ => Err(NitfError::ParseError("PixelValueType".to_string())),
690 }
691 }
692}
693impl Display for PixelValueType {
694 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
695 match self {
696 Self::INT => write!(f, "INT"),
697 Self::B => write!(f, "B"),
698 Self::SI => write!(f, "SI"),
699 Self::R => write!(f, "R"),
700 Self::C => write!(f, "C"),
701 }
702 }
703}
704impl FromStr for ImageRepresentation {
705 type Err = NitfError;
706 fn from_str(s: &str) -> Result<Self, Self::Err> {
707 match s {
708 "MONO" => Ok(Self::MONO),
709 "RGB" => Ok(Self::RGB),
710 "RGB/LUT" => Ok(Self::RGBLUT),
711 "MULTI" => Ok(Self::MULTI),
712 "NODISPLY" => Ok(Self::NODISPLY),
713 "" => Ok(Self::NVECTOR),
714 "POLAR" => Ok(Self::POLAR),
715 "VPH" => Ok(Self::VPH),
716 "YCbCr601" => Ok(Self::YCbCr601),
717 _ => Err(NitfError::ParseError("ImageRepresentation".to_string())),
718 }
719 }
720}
721impl Display for ImageRepresentation {
722 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
723 match self {
724 Self::MONO => write!(f, "MONO"),
725 Self::RGB => write!(f, "RGB"),
726 Self::RGBLUT => write!(f, "RGB/LUT"),
727 Self::MULTI => write!(f, "MULTI"),
728 Self::NODISPLY => write!(f, "NODISPLY"),
729 Self::NVECTOR => write!(f, "NVECTOR"),
730 Self::POLAR => write!(f, "POLAR"),
731 Self::VPH => write!(f, "VPH"),
732 Self::YCbCr601 => write!(f, "YCbCr601"),
733 }
734 }
735}
736impl FromStr for ImageRepresentationBand {
737 type Err = NitfError;
738 fn from_str(s: &str) -> Result<Self, Self::Err> {
739 match s {
740 "" => Ok(Self::DEFAULT),
741 "M" => Ok(Self::M),
742 "R" => Ok(Self::R),
743 "G" => Ok(Self::G),
744 "B" => Ok(Self::B),
745 "LU" => Ok(Self::LU),
746 "Y" => Ok(Self::Y),
747 "Cb" => Ok(Self::Cb),
748 "Cr" => Ok(Self::Cr),
749 _ => Err(NitfError::ParseError("ImageRepresentationBand".to_string())),
750 }
751 }
752}
753impl Display for ImageRepresentationBand {
754 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
755 match self {
756 Self::DEFAULT => write!(f, ""),
757 Self::M => write!(f, "M"),
758 Self::R => write!(f, "R"),
759 Self::G => write!(f, "G"),
760 Self::B => write!(f, "B"),
761 Self::LU => write!(f, "LU"),
762 Self::Y => write!(f, "Y"),
763 Self::Cb => write!(f, "Cb"),
764 Self::Cr => write!(f, "Cr"),
765 }
766 }
767}
768impl FromStr for ImageFilterCondition {
769 type Err = NitfError;
770 fn from_str(s: &str) -> Result<Self, Self::Err> {
771 match s {
772 "N" => Ok(Self::N),
773 _ => Err(NitfError::ParseError("PixelJustification".to_string())),
774 }
775 }
776}
777impl Display for ImageFilterCondition {
778 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
779 match self {
780 Self::N => write!(f, "N"),
781 }
782 }
783}
784impl FromStr for PixelJustification {
785 type Err = NitfError;
786 fn from_str(s: &str) -> Result<Self, Self::Err> {
787 match s {
788 "R" => Ok(Self::R),
789 "L" => Ok(Self::L),
790 _ => Err(NitfError::ParseError("PixelJustification".to_string())),
791 }
792 }
793}
794impl Display for PixelJustification {
795 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
796 match self {
797 Self::R => write!(f, "R"),
798 Self::L => write!(f, "L"),
799 }
800 }
801}
802impl FromStr for CoordinateRepresentation {
803 type Err = NitfError;
804 fn from_str(s: &str) -> Result<Self, Self::Err> {
805 match s {
806 "" => Ok(Self::DEFAULT),
807 "U" => Ok(Self::U),
808 "N" => Ok(Self::N),
809 "S" => Ok(Self::S),
810 "P" => Ok(Self::P),
811 "G" => Ok(Self::G),
812 "D" => Ok(Self::D),
813 _ => Err(NitfError::ParseError(
814 "CoordinateRepresentation".to_string(),
815 )),
816 }
817 }
818}
819impl Display for CoordinateRepresentation {
820 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
821 match self {
822 Self::DEFAULT => write!(f, ""),
823 Self::U => write!(f, "U"),
824 Self::N => write!(f, "N"),
825 Self::S => write!(f, "S"),
826 Self::P => write!(f, "P"),
827 Self::G => write!(f, "G"),
828 Self::D => write!(f, "D"),
829 }
830 }
831}
832impl FromStr for Compression {
833 type Err = NitfError;
834 fn from_str(s: &str) -> Result<Self, Self::Err> {
835 match s {
836 "NC" => Ok(Self::NC),
837 "NM" => Ok(Self::NM),
838 "C1" => Ok(Self::C1),
839 "C3" => Ok(Self::C3),
840 "C4" => Ok(Self::C4),
841 "C5" => Ok(Self::C5),
842 "C6" => Ok(Self::C6),
843 "C7" => Ok(Self::C7),
844 "C8" => Ok(Self::C8),
845 "I1" => Ok(Self::I1),
846 "M1" => Ok(Self::M1),
847 "M3" => Ok(Self::M3),
848 "M4" => Ok(Self::M4),
849 "M5" => Ok(Self::M5),
850 "M6" => Ok(Self::M6),
851 "M7" => Ok(Self::M7),
852 "M8" => Ok(Self::M8),
853 _ => Err(NitfError::ParseError("Compression".to_string())),
854 }
855 }
856}
857impl Display for Compression {
858 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
859 match self {
860 Self::NC => write!(f, "NC"),
861 Self::NM => write!(f, "NM"),
862 Self::C1 => write!(f, "C1"),
863 Self::C3 => write!(f, "C3"),
864 Self::C4 => write!(f, "C4"),
865 Self::C5 => write!(f, "C5"),
866 Self::C6 => write!(f, "C6"),
867 Self::C7 => write!(f, "C7"),
868 Self::C8 => write!(f, "C8"),
869 Self::I1 => write!(f, "I1"),
870 Self::M1 => write!(f, "M1"),
871 Self::M3 => write!(f, "M3"),
872 Self::M4 => write!(f, "M4"),
873 Self::M5 => write!(f, "M5"),
874 Self::M6 => write!(f, "M6"),
875 Self::M7 => write!(f, "M7"),
876 Self::M8 => write!(f, "M8"),
877 }
878 }
879}
880impl FromStr for Mode {
881 type Err = NitfError;
882 fn from_str(s: &str) -> Result<Self, Self::Err> {
883 match s {
884 "B" => Ok(Self::B),
885 "P" => Ok(Self::P),
886 "R" => Ok(Self::R),
887 "S" => Ok(Self::S),
888 _ => Err(NitfError::ParseError("Mode".to_string())),
889 }
890 }
891}
892impl Display for Mode {
893 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
894 match self {
895 Self::B => write!(f, "B"),
896 Self::P => write!(f, "P"),
897 Self::R => write!(f, "R"),
898 Self::S => write!(f, "S"),
899 }
900 }
901}