use std::fmt::Display;
use std::fs::File;
use std::str::FromStr;
use crate::error::NitfError;
use crate::headers::NitfSegmentHeader;
use crate::types::{NitfField, Security, ExtendedSubheader};
#[derive(Default, Clone, Debug, Eq, PartialEq)]
pub struct ImageHeader {
pub im: NitfField<String>,
pub iid1: NitfField<String>,
pub idatim: NitfField<String>,
pub tgtid: NitfField<String>,
pub iid2: NitfField<String>,
pub security: Security,
pub encryp: NitfField<String>,
pub isorce: NitfField<String>,
pub nrows: NitfField<u32>,
pub ncols: NitfField<u32>,
pub pvtype: NitfField<PixelValueType>,
pub irep: NitfField<ImageRepresentation>,
pub icat: NitfField<String>, pub abpp: NitfField<u8>,
pub pjust: NitfField<PixelJustification>,
pub icords: NitfField<CoordinateRepresentation>,
pub igeolo: Vec<NitfField<String>>, pub nicom: NitfField<u8>,
pub icoms: Vec<NitfField<String>>,
pub ic: NitfField<Compression>,
pub comrat: NitfField<String>, pub nbands: NitfField<u8>,
pub xbands: NitfField<u32>,
pub bands: Vec<Band>,
pub isync: NitfField<u8>,
pub imode: NitfField<Mode>,
pub nbpr: NitfField<u16>,
pub nbpc: NitfField<u16>,
pub nppbh: NitfField<u16>,
pub nppbv: NitfField<u16>,
pub nbpp: NitfField<u8>,
pub idlvl: NitfField<u16>,
pub ialvl: NitfField<u16>,
pub iloc: NitfField<String>, pub imag: NitfField<String>,
pub udidl: NitfField<u32>,
pub udofl: NitfField<u16>,
pub udid: NitfField<String>, pub ixshdl: NitfField<u32>,
pub ixsofl: NitfField<u16>,
pub ixshd: ExtendedSubheader
}
#[derive(Default, Clone, Debug, Eq, PartialEq)]
pub struct Band {
pub irepband: NitfField<String>, pub isubcat: NitfField<String>, pub ifc: NitfField<String>, pub imflt: NitfField<String>, pub nluts: NitfField<u8>, pub nelut: NitfField<u16>,
pub lutd: Vec<NitfField<u8>>,
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub enum PixelValueType {
#[default]
C,
R,
B,
SI,
INT,
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub enum ImageRepresentation {
#[default]
MONO,
RGB,
RGBLUT,
MULTI,
NODISPLY,
NVECTOR,
POLAR,
VPH,
YCbCr601,
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub enum PixelJustification {
#[default]
R,
L,
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub enum CoordinateRepresentation {
#[default]
DEFAULT,
U,
N,
S,
P,
G,
D,
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub enum Compression {
#[default]
NC,
NM,
C1,
C3,
C4,
C5,
C6,
C7,
C8,
I1,
M1,
M3,
M4,
M5,
M6,
M7,
M8,
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub enum Mode {
#[default]
B,
P,
R,
S,
}
fn read_bands(reader: &mut File, n_band: u32) -> Vec<Band> {
let mut bands: Vec<Band> = vec![Band::default(); n_band as usize];
for band in &mut bands {
band.irepband.read(reader, 2u8);
band.isubcat.read(reader, 6u8);
band.ifc.read(reader, 1u8);
band.imflt.read(reader, 3u8);
band.nluts.read(reader, 1u8);
if band.nluts.val != 0 {
band.nelut.read(reader, 5u8);
for _ in 0..band.nelut.val {
let mut lut: NitfField<u8> = NitfField::default();
lut.read(reader, 1u8);
band.lutd.push(lut);
}
}
}
bands
}
impl NitfSegmentHeader for ImageHeader {
fn read(&mut self, reader: &mut File) {
self.im.read(reader, 2u8);
self.iid1.read(reader, 10u8);
self.idatim.read(reader, 14u8);
self.tgtid.read(reader, 17u8);
self.iid2.read(reader, 80u8);
self.security.read(reader);
self.encryp.read(reader, 1u8);
self.isorce.read(reader, 42u8);
self.nrows.read(reader, 8u8);
self.ncols.read(reader, 8u8);
self.pvtype.read(reader, 3u8);
self.irep.read(reader, 8u8);
self.icat.read(reader, 8u8);
self.abpp.read(reader, 2u8);
self.pjust.read(reader, 1u8);
self.icords.read(reader, 1u8);
for _ in 0..4 {
let mut geoloc: NitfField<String> = NitfField::default();
geoloc.read(reader, 15u8);
self.igeolo.push(geoloc);
}
self.nicom.read(reader, 1u8);
for _ in 0..self.nicom.val {
let mut comment: NitfField<String> = NitfField::default();
comment.read(reader, 80u8);
self.icoms.push(comment);
}
self.ic.read(reader, 2u8);
self.nbands.read(reader, 1u8);
if self.nbands.val != 0 {
self.bands = read_bands(reader, self.nbands.val as u32)
} else {
self.xbands.read(reader, 5u8);
self.bands = read_bands(reader, self.xbands.val)
}
self.isync.read(reader, 1u8);
self.imode.read(reader, 1u8);
self.nbpr.read(reader, 4u8);
self.nbpc.read(reader, 4u8);
self.nppbh.read(reader, 4u8);
self.nppbv.read(reader, 4u8);
self.nbpp.read(reader, 2u8);
self.idlvl.read(reader, 3u8);
self.ialvl.read(reader, 3u8);
self.iloc.read(reader, 10u8);
self.imag.read(reader, 4u8);
self.udidl.read(reader, 5u8);
let udi_data_length = self.udidl.val;
if udi_data_length != 0 {
self.udofl.read(reader, 3u8);
self.udid.read(reader, udi_data_length - 3);
}
self.ixshdl.read(reader, 5u8);
let ixsh_data_length = self.ixshdl.val;
if ixsh_data_length != 0 {
self.ixsofl.read(reader, 3u8);
self.ixshd.read(reader, (ixsh_data_length - 3) as usize);
}
}
}
impl Display for ImageHeader {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut out_str = String::default();
out_str += format!("IM: {}, ", self.im).as_ref();
out_str += format!("IID1: {}, ", self.iid1).as_ref();
out_str += format!("IDATIM: {}, ", self.idatim).as_ref();
out_str += format!("TGTID: {}, ", self.tgtid).as_ref();
out_str += format!("IID2: {}, ", self.iid2).as_ref();
out_str += format!("SECURITY: [{}], ", self.security).as_ref();
out_str += format!("ENCRYP: {}, ", self.encryp).as_ref();
out_str += format!("ISORCE: {}, ", self.isorce).as_ref();
out_str += format!("NROWS: {}, ", self.nrows).as_ref();
out_str += format!("NCOLS: {}, ", self.ncols).as_ref();
out_str += format!("PVTYPE: {}, ", self.pvtype).as_ref();
out_str += format!("IREP: {}, ", self.irep).as_ref();
out_str += format!("ICAT: {}, ", self.icat).as_ref();
out_str += format!("ABPP: {}, ", self.abpp).as_ref();
out_str += format!("PJUST: {}, ", self.pjust).as_ref();
out_str += format!("ICORDS: {}, ", self.icords).as_ref();
for geolocation in &self.igeolo {
out_str += format!("[GEOLO: {}], ", geolocation).as_ref();
}
out_str += format!("NICOM: {}, ", self.nicom).as_ref();
for comment in &self.icoms {
out_str += format!("[ICOM: {}], ", comment).as_ref();
}
out_str += format!("IC: {}, ", self.ic).as_ref();
out_str += format!("NBANDS: {}, ", self.nbands).as_ref();
for band in &self.bands {
out_str += format!("[BAND: {}], ", band).as_ref();
}
out_str += format!("ISYNC: {}, ", self.isync).as_ref();
out_str += format!("IMODE: {}, ", self.imode).as_ref();
out_str += format!("NBPR: {}, ", self.nbpr).as_ref();
out_str += format!("NBPC: {}, ", self.nbpc).as_ref();
out_str += format!("NPPBH: {}, ", self.nppbh).as_ref();
out_str += format!("NPPBV: {}, ", self.nppbv).as_ref();
out_str += format!("NBPP: {}, ", self.nbpp).as_ref();
out_str += format!("IDLVL: {}, ", self.idlvl).as_ref();
out_str += format!("IALVL: {}, ", self.ialvl).as_ref();
out_str += format!("ILOC: {}, ", self.iloc).as_ref();
out_str += format!("IMAG: {}, ", self.imag).as_ref();
out_str += format!("UDIDL: {}, ", self.udidl).as_ref();
out_str += format!("UDOFL: {}, ", self.udofl).as_ref();
out_str += format!("UDID: {}, ", self.udid).as_ref();
out_str += format!("IXSHDL: {}, ", self.ixshdl).as_ref();
if self.ixshdl.val != 0
{
out_str += format!("IXSOFL: {}, ", self.ixsofl).as_ref();
out_str += format!("IXSHD: {}", self.ixshd).as_ref();
}
write!(f, "[Image Subheader: {out_str}]")
}
}
impl Display for Band {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut out_str = String::default();
out_str += format!("IREPBAND: {}, ", self.irepband).as_ref();
out_str += format!("ISUBCAT: {}, ", self.isubcat).as_ref();
out_str += format!("IFC: {}, ", self.ifc).as_ref();
out_str += format!("IMFLT: {}, ", self.imflt).as_ref();
out_str += format!("NLUTS: {}, ", self.nluts).as_ref();
out_str += format!("NELUT: {}, ", self.nelut).as_ref();
for look_up in &self.lutd {
out_str += format!("LUTD: {look_up}, ").as_ref();
}
write!(f, "{out_str}")
}
}
impl FromStr for PixelValueType {
type Err = NitfError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"INT" => Ok(Self::INT),
"B" => Ok(Self::B),
"SI" => Ok(Self::SI),
"R" => Ok(Self::R),
"C" => Ok(Self::C),
_ => Err(NitfError::FieldError),
}
}
}
impl FromStr for ImageRepresentation {
type Err = NitfError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"MONO" => Ok(Self::MONO),
"RGB" => Ok(Self::RGB),
"RGBLUT" => Ok(Self::RGBLUT),
"MULTI" => Ok(Self::MULTI),
"NODISPLY" => Ok(Self::NODISPLY),
"NVECTOR" => Ok(Self::NVECTOR),
"POLAR" => Ok(Self::POLAR),
"VPH" => Ok(Self::VPH),
"YCbCr601" => Ok(Self::YCbCr601),
_ => Err(NitfError::FieldError),
}
}
}
impl FromStr for PixelJustification {
type Err = NitfError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"R" => Ok(Self::R),
"L" => Ok(Self::L),
_ => Err(NitfError::FieldError),
}
}
}
impl FromStr for CoordinateRepresentation {
type Err = NitfError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"" => Ok(Self::DEFAULT),
"U" => Ok(Self::U),
"N" => Ok(Self::N),
"S" => Ok(Self::S),
"P" => Ok(Self::P),
"G" => Ok(Self::G),
"D" => Ok(Self::D),
_ => Err(NitfError::FieldError),
}
}
}
impl FromStr for Compression {
type Err = NitfError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"NC" => Ok(Self::NC),
"NM" => Ok(Self::NM),
"C1" => Ok(Self::C1),
"C3" => Ok(Self::C3),
"C4" => Ok(Self::C4),
"C5" => Ok(Self::C5),
"C6" => Ok(Self::C6),
"C7" => Ok(Self::C7),
"C8" => Ok(Self::C8),
"I1" => Ok(Self::I1),
"M1" => Ok(Self::M1),
"M3" => Ok(Self::M3),
"M4" => Ok(Self::M4),
"M5" => Ok(Self::M5),
"M6" => Ok(Self::M6),
"M7" => Ok(Self::M7),
"M8" => Ok(Self::M8),
_ => Err(NitfError::FieldError),
}
}
}
impl FromStr for Mode {
type Err = NitfError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"B" => Ok(Self::B),
"P" => Ok(Self::P),
"R" => Ok(Self::R),
"S" => Ok(Self::S),
_ => Err(NitfError::FieldError),
}
}
}