1use log::{debug, trace};
2use std::fmt::Display;
3use std::io::{Read, Seek, Write};
4
5use crate::headers::file_hdr::Segment::*;
6use crate::headers::*;
7use crate::types::NitfSegment;
8use crate::NitfResult;
9
10pub type ImageSegment = NitfSegment<ImageHeader>;
12pub type GraphicSegment = NitfSegment<GraphicHeader>;
13pub type TextSegment = NitfSegment<TextHeader>;
14pub type DataExtensionSegment = NitfSegment<DataExtensionHeader>;
15pub type ReservedExtensionSegment = NitfSegment<ReservedExtensionHeader>;
16
17#[derive(Default, Debug)]
19pub struct Nitf {
20 pub nitf_header: NitfHeader,
22 pub image_segments: Vec<ImageSegment>,
24 pub graphic_segments: Vec<GraphicSegment>,
26 pub text_segments: Vec<TextSegment>,
28 pub data_extension_segments: Vec<DataExtensionSegment>,
30 pub reserved_extension_segments: Vec<ReservedExtensionSegment>,
32}
33
34impl Nitf {
35 pub fn from_reader(reader: &mut (impl Read + Seek)) -> NitfResult<Self> {
37 let mut nitf = Nitf::default();
38
39 debug!("Reading NITF file header");
40 nitf.nitf_header.read(reader)?;
41
42 let mut n_seg = nitf.nitf_header.numi.val as usize;
43 for i_seg in 0..n_seg {
44 let seg_info = &nitf.nitf_header.imheaders[i_seg];
45 let data_size = seg_info.item_size.val;
46 let seg = ImageSegment::read(reader, data_size)?;
47 nitf.image_segments.push(seg);
48 }
49
50 n_seg = nitf.nitf_header.nums.val as usize;
51 for i_seg in 0..n_seg {
52 let seg_info = &nitf.nitf_header.graphheaders[i_seg];
53 let data_size: u64 = seg_info.item_size.val;
54 let seg = GraphicSegment::read(reader, data_size)?;
55 nitf.graphic_segments.push(seg);
56 }
57
58 n_seg = nitf.nitf_header.numt.val as usize;
59 for i_seg in 0..n_seg {
60 let seg_info = &nitf.nitf_header.textheaders[i_seg];
61 let data_size: u64 = seg_info.item_size.val;
62 let seg = TextSegment::read(reader, data_size)?;
63 nitf.text_segments.push(seg);
64 }
65
66 n_seg = nitf.nitf_header.numdes.val as usize;
67 for i_seg in 0..n_seg {
68 let seg_info = &nitf.nitf_header.dextheaders[i_seg];
69 let data_size: u64 = seg_info.item_size.val;
70 let seg = DataExtensionSegment::read(reader, data_size)?;
71 nitf.data_extension_segments.push(seg);
72 }
73
74 n_seg = nitf.nitf_header.numres.val as usize;
75 for i_seg in 0..n_seg {
76 let seg_info = &nitf.nitf_header.resheaders[i_seg];
77 let data_size = seg_info.item_size.val;
78 let seg = ReservedExtensionSegment::read(reader, data_size)?;
79 nitf.reserved_extension_segments.push(seg);
80 }
81 Ok(nitf)
82 }
83
84 pub fn write_headers(&mut self, writer: &mut (impl Write + Seek)) -> NitfResult<usize> {
86 let mut bytes_written = 0;
87
88 let file_length = self.length() as u64;
89 bytes_written += self.nitf_header.write_header(writer, file_length)?;
90 for seg in self.image_segments.iter_mut() {
91 bytes_written += seg.write_header(writer)?;
92 }
93 for seg in self.graphic_segments.iter_mut() {
94 bytes_written += seg.write_header(writer)?;
95 }
96 for seg in self.text_segments.iter_mut() {
97 bytes_written += seg.write_header(writer)?;
98 }
99 for seg in self.data_extension_segments.iter_mut() {
100 bytes_written += seg.write_header(writer)?;
101 }
102 for seg in self.reserved_extension_segments.iter_mut() {
103 bytes_written += seg.write_header(writer)?;
104 }
105 Ok(bytes_written)
106 }
107
108 pub fn length(&self) -> usize {
110 let mut length = 0;
111 length += self.nitf_header.length();
112 length += self
113 .image_segments
114 .iter()
115 .map(|seg| seg.length())
116 .sum::<usize>();
117 length += self
118 .graphic_segments
119 .iter()
120 .map(|seg| seg.length())
121 .sum::<usize>();
122 length += self
123 .text_segments
124 .iter()
125 .map(|seg| seg.length())
126 .sum::<usize>();
127 length += self
128 .data_extension_segments
129 .iter()
130 .map(|seg| seg.length())
131 .sum::<usize>();
132 length += self
133 .reserved_extension_segments
134 .iter()
135 .map(|seg| seg.length())
136 .sum::<usize>();
137 length
138 }
139
140 fn update_offsets(&mut self) {
142 let mut offset = self.nitf_header.length();
143 let mut trace_string = "Updated offsets: \n".to_string();
144 trace_string += &format!("\tFile Header length: {offset}\n");
145 for (i_seg, seg) in self.image_segments.iter_mut().enumerate() {
146 seg.header_offset = offset as u64;
147 offset += seg.header.length();
148 trace_string += &format!(
149 "\tImage segment {i_seg} header offset: {}\n",
150 seg.header_offset
151 );
152 trace_string += &format!(
153 "\tImage segment {i_seg} header length: {}\n",
154 seg.header.length()
155 );
156 seg.data_offset = offset as u64;
157 offset += seg.data_size as usize;
158 trace_string += &format!("\tImage segment {i_seg} data offset: {}\n", seg.data_offset);
159 trace_string += &format!("\tImage segment {i_seg} data length: {}\n", seg.data_size);
160 }
161 for (i_seg, seg) in self.graphic_segments.iter_mut().enumerate() {
162 seg.header_offset = offset as u64;
163 offset += seg.header.length();
164 trace_string += &format!(
165 "\tGraphic segment {i_seg} header offset: {}\n",
166 seg.header_offset
167 );
168 trace_string += &format!(
169 "\tGraphic segment {i_seg} header length: {}\n",
170 seg.header.length()
171 );
172 seg.data_offset = offset as u64;
173 offset += seg.data_size as usize;
174 trace_string += &format!(
175 "\tGraphic segment {i_seg} data offset: {}\n",
176 seg.data_offset
177 );
178 trace_string += &format!("\tGraphic segment {i_seg} data length: {}\n", seg.data_size);
179 }
180 for (i_seg, seg) in self.text_segments.iter_mut().enumerate() {
181 seg.header_offset = offset as u64;
182 offset += seg.header.length();
183 trace_string += &format!(
184 "\tText segment {i_seg} header offset: {}\n",
185 seg.header_offset
186 );
187 trace_string += &format!(
188 "\tText segment {i_seg} header length: {}\n",
189 seg.header.length()
190 );
191 seg.data_offset = offset as u64;
192 offset += seg.data_size as usize;
193 trace_string += &format!("\tText segment {i_seg} data offset: {}\n", seg.data_offset);
194 trace_string += &format!("\tText segment {i_seg} data length: {}\n", seg.data_size);
195 }
196 for (i_seg, seg) in self.data_extension_segments.iter_mut().enumerate() {
197 seg.header_offset = offset as u64;
198 offset += seg.header.length();
199 trace_string += &format!(
200 "\tData Extension segment {i_seg} header offset: {}\n",
201 seg.header_offset
202 );
203 trace_string += &format!(
204 "\tData Extension segment {i_seg} header length: {}\n",
205 seg.header.length()
206 );
207 seg.data_offset = offset as u64;
208 offset += seg.data_size as usize;
209 trace_string += &format!(
210 "\tData Extension segment {i_seg} data offset: {}\n",
211 seg.data_offset
212 );
213 trace_string += &format!(
214 "\tData Extension segment {i_seg} data length: {}\n",
215 seg.data_size
216 );
217 }
218 for (i_seg, seg) in self.reserved_extension_segments.iter_mut().enumerate() {
219 seg.header_offset = offset as u64;
220 offset += seg.header.length();
221 trace_string += &format!(
222 "\tReserved Extension segment {i_seg} header offset: {}\n",
223 seg.header_offset
224 );
225 trace_string += &format!(
226 "\tReserved Extension segment {i_seg} header length: {}\n",
227 seg.header.length()
228 );
229 seg.data_offset = offset as u64;
230 offset += seg.data_size as usize;
231 trace_string += &format!(
232 "\tReserved Extension segment {i_seg} data offset: {}\n",
233 seg.data_offset
234 );
235 trace_string += &format!(
236 "\tReserved Extension segment {i_seg} data length: {}\n",
237 seg.data_size
238 );
239 }
240 trace!("{trace_string}");
241 }
242
243 pub fn add_im(&mut self, seg: ImageSegment) {
249 let segment_type = Image;
250 let subheader_size = seg.header.length() as u32;
251 let item_size = seg.data_size;
252 self.nitf_header
253 .add_subheader(segment_type, subheader_size, item_size);
254 self.image_segments.push(seg);
255 self.update_offsets();
256 debug!("Added Image Segment to NITF");
257 }
258
259 pub fn add_sy(&mut self, seg: GraphicSegment) {
265 let segment_type = Graphic;
266 let subheader_size = seg.header.length() as u32;
267 let item_size = seg.data_size;
268 self.nitf_header
269 .add_subheader(segment_type, subheader_size, item_size);
270 self.graphic_segments.push(seg);
271 self.update_offsets();
272 debug!("Added Graphic Segment to NITF");
273 }
274
275 pub fn add_te(&mut self, seg: TextSegment) {
281 let segment_type = Text;
282 let subheader_size = seg.header.length() as u32;
283 let item_size = seg.data_size;
284 self.nitf_header
285 .add_subheader(segment_type, subheader_size, item_size);
286 self.text_segments.push(seg);
287 self.update_offsets();
288 debug!("Added Text Segment to NITF");
289 }
290
291 pub fn add_de(&mut self, seg: DataExtensionSegment) {
297 let segment_type = DataExtension;
298 let subheader_size = seg.header.length() as u32;
299 let item_size = seg.data_size;
300 self.nitf_header
301 .add_subheader(segment_type, subheader_size, item_size);
302 self.data_extension_segments.push(seg);
303 self.update_offsets();
304 debug!("Added Data Extension Segment to NITF");
305 }
306
307 pub fn add_re(&mut self, seg: ReservedExtensionSegment) {
313 let segment_type = ReservedExtension;
314 let subheader_size = seg.header.length() as u32;
315 let item_size = seg.data_size;
316 self.nitf_header
317 .add_subheader(segment_type, subheader_size, item_size);
318 self.reserved_extension_segments.push(seg);
319 self.update_offsets();
320 debug!("Added Reserved Extension Segment to NITF");
321 }
322}
323
324impl Display for Nitf {
326 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
327 let mut out_str = String::default();
328 out_str += format!("{}", self.nitf_header).as_ref();
329 for segment in &self.image_segments {
330 out_str += format!("{segment}, ").as_ref();
331 }
332 for segment in &self.graphic_segments {
333 out_str += format!("{segment}, ").as_ref();
334 }
335 for segment in &self.text_segments {
336 out_str += format!("{segment}, ").as_ref();
337 }
338 for segment in &self.data_extension_segments {
339 out_str += format!("{segment}, ").as_ref();
340 }
341 for segment in &self.reserved_extension_segments {
342 out_str += format!("{segment}, ").as_ref();
343 }
344 write!(f, "{out_str}",)
345 }
346}
347impl PartialEq for Nitf {
348 fn eq(&self, other: &Self) -> bool {
349 self.nitf_header == other.nitf_header
350 && self.image_segments == other.image_segments
351 && self.graphic_segments == other.graphic_segments
352 && self.text_segments == other.text_segments
353 && self.data_extension_segments == other.data_extension_segments
354 && self.reserved_extension_segments == other.reserved_extension_segments
355 }
356}
357impl Eq for Nitf {}