OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimAdrgHeader.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: Ken Melero
6 // Description: This class encapsulates the image parameters and
7 // support data for a ADRG image file(s).
8 //
9 //********************************************************************
10 // $Id: ossimAdrgHeader.cpp 13766 2008-10-22 19:31:32Z gpotts $
11 
12 #include <cstring>
13 #include <iostream>
14 
15 #include <ossim/base/ossimNotify.h>
18 
19 //**************************************************************************
20 // Constructor
21 //**************************************************************************
23  :
24  theErrorStatus(OSSIM_OK),
25  theHeaderFile(img_file),
26  theImageFile(img_file),
27  theValidImageRect(0,0,0,0),
28  thePixelType(OSSIM_UCHAR),
29  theInterleaveType(OSSIM_BSQ),
30  theNumberOfBands(3),
31  theLines(0),
32  theSamples(0),
33  theHeaderSize(0),
34  theTim(0)
35 {
36  // Get the extension.
37  ossimString ext = img_file.ext();
38 
39  if (ext == "IMG")
40  {
42  }
43  else if (ext == "img")
44  {
46  }
47  else
48  {
49  // Required "img" or "IMG" extension.
51  return;
52  }
53 
54  // Check for header file.
55  if(theHeaderFile.exists() == false)
56  {
58  return;
59  }
60 
61  // Parse header for all needed support data.
62  parse();
63 }
64 
65 //**************************************************************************
66 // Destructor
67 //**************************************************************************
69 {
70  if(theTim)
71  {
72  delete [] theTim;
73  theTim = 0;
74  }
75 }
76 
77 //**************************************************************************
78 // Parse header
79 //**************************************************************************
81 {
82  // NOTE: By default, ISO8211 library reports errors to stderr,
83  // so we don't bother doing it ourselves. We simply set
84  // the OSSIM_ERROR flag.
85 
86  ossimDDFModule oModule;
87  ossimDDFRecord* oRecord;
88 
89  // Open header file which is ISO8211 encoded.
90  if(!oModule.Open(theHeaderFile.chars()) )
91  {
93  return;
94  }
95 
96  oRecord = oModule.ReadRecord();
97 
98  ossimDDFField* oField = oRecord->FindField("DRF");
99  int bytesOfData = oField->GetDataSize();
100  int nBytesConsumed = 0;
101  const char* rawFieldData;
102 
103  ossimDDFFieldDefn* fieldDefn = oField->GetFieldDefn();
104  ossimDDFSubfieldDefn* nfile = fieldDefn->FindSubfieldDefn("NOZ");
105  rawFieldData = oField->GetSubfieldData(nfile);
106  ossimString num_img_files = nfile->ExtractStringData(rawFieldData,
107  bytesOfData,
108  &nBytesConsumed);
109 
110  // Number of ZDR images
111  ossim_uint32 num_ifiles = (ossim_uint32)ossimString::toInt(num_img_files);
112 
113  // Skip overview record.
114  oRecord = oModule.ReadRecord();
115 
116  // Validate this is the correct record and it is an ADRG image.
117  ossimString img_file = "";
119  img_base.downcase();
120 
121  // Find the correct geometry record corresponding to the image file.
122  ossim_uint32 count = 0;
123  while(count < num_ifiles)
124  {
125  oField = oRecord->FindField("001");
126  bytesOfData = oField->GetDataSize();
127  nBytesConsumed = 0;
128 
129  fieldDefn = oField->GetFieldDefn();
130  ossimDDFSubfieldDefn* rty = fieldDefn->FindSubfieldDefn("RTY");
131  rawFieldData = oField->GetSubfieldData(rty);
132  ossimString rtype = rty->ExtractStringData(rawFieldData,
133  bytesOfData,
134  &nBytesConsumed);
135 
136  // Found general information record
137  if(rtype == "GIN")
138  {
139  // Validate that this is an ADRG header file.
140  oField = oRecord->FindField("DSI");
141  bytesOfData = oField->GetDataSize();
142  nBytesConsumed = 0;
143 
144  fieldDefn = oField->GetFieldDefn();
145  ossimDDFSubfieldDefn* ptype = fieldDefn->FindSubfieldDefn("PRT");
146  rawFieldData = oField->GetSubfieldData(ptype);
147  ossimString product_type = ptype->ExtractStringData(rawFieldData,
148  bytesOfData,
149  &nBytesConsumed);
150 
151  if(!(strncmp(product_type.c_str(), "ADRG", 4) == 0))
152  {
154  << "File does not appear to be an ADRG header file: "
155  << theHeaderFile.chars() << std::endl;
156 
158  return;
159  }
160 
161  fieldDefn = oField->GetFieldDefn();
162  ossimDDFSubfieldDefn* ifile = fieldDefn->FindSubfieldDefn("NAM");
163  rawFieldData = oField->GetSubfieldData(ifile);
164  img_file = ifile->ExtractStringData(rawFieldData, bytesOfData,
165  &nBytesConsumed);
166  img_file.downcase();
167 
168  count++;
169 
170  if(img_base == img_file)
171  break;
172  else
173  oRecord = oModule.ReadRecord();
174  }
175  else
176  oRecord = oModule.ReadRecord();
177  }
178 
179  // Find Distribution Rectangle name.
180  oField = oRecord->FindField("GEN");
181  bytesOfData = oField->GetDataSize();
182  nBytesConsumed = 0;
183 
184  fieldDefn = oField->GetFieldDefn();
185 
186  // Find Subfield names.
187  ossimDDFSubfieldDefn* min_lon = fieldDefn->FindSubfieldDefn("SWO");
188  ossimDDFSubfieldDefn* min_lat = fieldDefn->FindSubfieldDefn("SWA");
189  ossimDDFSubfieldDefn* max_lon = fieldDefn->FindSubfieldDefn("NEO");
190  ossimDDFSubfieldDefn* max_lat = fieldDefn->FindSubfieldDefn("NEA");
191 
192  // Extract the min/max lon/lat coordinates.
193  rawFieldData = oField->GetSubfieldData(min_lon);
194  theMinLon = min_lon->ExtractStringData(rawFieldData,
195  bytesOfData,
196  &nBytesConsumed);
197  rawFieldData = oField->GetSubfieldData(min_lat);
198  theMinLat = min_lat->ExtractStringData(rawFieldData,
199  bytesOfData,
200  &nBytesConsumed);
201  rawFieldData = oField->GetSubfieldData(max_lon);
202  theMaxLon = max_lon->ExtractStringData(rawFieldData,
203  bytesOfData,
204  &nBytesConsumed);
205  rawFieldData = oField->GetSubfieldData(max_lat);
206  theMaxLat = max_lat->ExtractStringData(rawFieldData,
207  bytesOfData,
208  &nBytesConsumed);
209 
210  // Find the DATA_SET_PARAMETERS_FIELD
211  oField = oRecord->FindField("SPR");
212  bytesOfData = oField->GetDataSize();
213  nBytesConsumed = 0;
214 
215  fieldDefn = oField->GetFieldDefn();
216 
217  // Find subfields.
218  ossimDDFSubfieldDefn* start_row = fieldDefn->FindSubfieldDefn("NUL");
219  ossimDDFSubfieldDefn* stop_col = fieldDefn->FindSubfieldDefn("NUS");
220  ossimDDFSubfieldDefn* stop_row = fieldDefn->FindSubfieldDefn("NLL");
221  ossimDDFSubfieldDefn* start_col = fieldDefn->FindSubfieldDefn("NLS");
222  ossimDDFSubfieldDefn* lines = fieldDefn->FindSubfieldDefn("NFL");
223  ossimDDFSubfieldDefn* samples = fieldDefn->FindSubfieldDefn("NFC");
224  ossimDDFSubfieldDefn* tif = fieldDefn->FindSubfieldDefn("TIF");
225 
226  // Extract the number of lines & samples per tile.
227  rawFieldData = oField->GetSubfieldData(start_row);
228  theStartRow = atoi(start_row->ExtractStringData(rawFieldData,
229  bytesOfData,
230  &nBytesConsumed));
231  rawFieldData = oField->GetSubfieldData(start_col);
232  theStartCol = atoi(start_col->ExtractStringData(rawFieldData,
233  bytesOfData,
234  &nBytesConsumed));
235  rawFieldData = oField->GetSubfieldData(stop_row);
236  theStopRow = atoi(stop_row->ExtractStringData(rawFieldData,
237  bytesOfData,
238  &nBytesConsumed));
239  rawFieldData = oField->GetSubfieldData(stop_col);
240  theStopCol = atoi(stop_col->ExtractStringData(rawFieldData,
241  bytesOfData,
242  &nBytesConsumed));
243  rawFieldData = oField->GetSubfieldData(lines);
244  theLinesInTiles = atoi(lines->ExtractStringData(rawFieldData,
245  bytesOfData,
246  &nBytesConsumed));
247  rawFieldData = oField->GetSubfieldData(samples);
248  theSamplesInTiles = atoi(samples->ExtractStringData(rawFieldData,
249  bytesOfData,
250  &nBytesConsumed));
251  rawFieldData = oField->GetSubfieldData(tif);
252  theTif = tif->ExtractStringData(rawFieldData, bytesOfData,
253  &nBytesConsumed);
254 
257 
259 
260  if(theTim)
261  {
262  delete [] theTim;
263  theTim = 0;
264  }
265  // Initialize the TIM (tile index map).
267 
268  // Read in the tile index map (TIM) if it exists.
269  if(strncmp(theTif.c_str(), "Y", 1) == 0)
270  {
271  // Find the TILE_INDEX_MAP_FIELD
272  oField = oRecord->FindField("TIM");
273  bytesOfData = oField->GetDataSize();
274  fieldDefn = oField->GetFieldDefn();
275  rawFieldData = oField->GetData();
276  nBytesConsumed = 0;
277 
278  for(ossim_uint32 r = 0; r < theLinesInTiles * theSamplesInTiles; r++ )
279  {
280  ossimDDFSubfieldDefn* tim = fieldDefn->FindSubfieldDefn("TSI");
281  theTim[r] = atoi(tim->ExtractStringData(rawFieldData, bytesOfData,
282  &nBytesConsumed));
283  bytesOfData -= nBytesConsumed;
284  rawFieldData += nBytesConsumed;
285  }
286  }
287  else
288  {
289  for(ossim_uint32 m = 0; m < (theLinesInTiles * theSamplesInTiles); m++)
290  theTim[m] = (m+1);
291  }
292 
293  // Close module used for reading encoded header file.
294  oModule.Close();
295 }
296 
297 //*********************************************************************
298 // tim(int32 row, int32 col)
299 //*********************************************************************
301 {
302  return ( theTim[(row * theSamplesInTiles) + col] );
303 }
304 
305 //*********************************************************************
306 // operator <<
307 //*********************************************************************
309 {
310  os << "\nContents of ADRG Header file (.gen):"
311  << "\nImage File = " << adrg.theImageFile
312  << "\nHeader File = " << adrg.theHeaderFile
313  << "\nPixelType = " << adrg.thePixelType
314  << "\nInterleaveType = " << adrg.theInterleaveType
315  << "\nNumberOfBands = " << adrg.theNumberOfBands
316  << "\nLines = " << adrg.theLines
317  << "\nLines (tiles) = " << adrg.theLinesInTiles
318  << "\nSamples = " << adrg.theSamples
319  << "\nSamples (tiles) = " << adrg.theSamplesInTiles
320  << "\nHeaderSize = " << adrg.theHeaderSize
321  << "\nValidImageRect = " << adrg.theValidImageRect
322  << "\nTIF = " << adrg.theTif
323  << "\nMin Lon = " << adrg.theMinLon
324  << "\nMin Lat = " << adrg.theMinLat
325  << "\nMax Lon = " << adrg.theMaxLon
326  << "\nMax Lat = " << adrg.theMaxLat
327  << "\nStart Row = " << adrg.theStartRow
328  << "\nStart Col = " << adrg.theStartCol
329  << "\nStop Row = " << adrg.theStopRow
330  << "\nStop Col = " << adrg.theStopCol
331  << std::endl;
332 
333  for(ossim_uint32 m = 0; m < (adrg.theLinesInTiles * adrg.theSamplesInTiles); m++)
334  os << "\nTIM[" << m << "] = " << adrg.theTim[m];
335 
336  os << std::endl;
337 
338  return(os);
339 }
340 
341 //*********************************************************************
342 // Public method:
343 //*********************************************************************
345 {
347 }
348 
349 //*********************************************************************
350 // Public method:
351 //*********************************************************************
353 {
355 }
356 
357 //*********************************************************************
358 // Public method:
359 //*********************************************************************
361 {
363 }
364 
365 //*********************************************************************
366 // Public method:
367 //*********************************************************************
369 {
371 }
372 
373 //*********************************************************************
374 // Private method:
375 //*********************************************************************
377 {
378  static const char MODULE[] = "ossimAdrgHeader::parseLongitudeString";
379 
380  // Format = +|-dddmmss.ss
381 
382  if (lon.size() != 11)
383  {
385  << MODULE << " Longitude string error!"
386  << "Bad longitude string: " << lon.c_str() << std::endl;
387  }
388 
389  const char* cstr = lon.c_str();
390 
391  double degrees = 0.0;
392  double sign = 1.0;
393  char tmp_str[6];
394 
395  // Get the sign.
396  if (cstr[0] == '-') sign = -1.0;
397 
398  // Get the degrees.
399  tmp_str[3] = '\0';
400  cstr++; // Increment past the sign.
401  strncpy(tmp_str, cstr, 3);
402  degrees = atof(tmp_str);
403 
404  // Get the minutes.
405  tmp_str[2] = '\0';
406  cstr += 3; // Increment to the minutes.
407  strncpy(tmp_str, cstr, 2);
408  degrees += atof(tmp_str) / 60.0;
409 
410  // Get the seconds.
411  tmp_str[5] = '\0';
412  cstr += 2; // Increment to seconds.
413  strncpy(tmp_str, cstr, 5);
414  degrees += atof(tmp_str) / 3600.0;
415 
416  // Set the sign.
417  degrees *= sign;
418 
419  return degrees;
420 }
421 
422 //*********************************************************************
423 // Private method:
424 //*********************************************************************
426 {
427  static const char MODULE[] = "ossimAdrgHeader::parseLatitudeString";
428 
429  // Format = +|-ddmmss.ss
430 
431  if (lat.size() != 10)
432  {
434  << MODULE << " Latitude string error!"
435  << "Bad latitude string: " << lat.c_str() << std::endl;
436  }
437 
438  const char* cstr = lat.c_str();
439 
440  double degrees = 0.0;
441  double sign = 1.0;
442  char tmp_str[6];
443 
444  // Get the sign.
445  if (cstr[0] == '-') sign = -1.0;
446 
447  // Get the degrees.
448  tmp_str[2] = '\0';
449  cstr++; // Increment past the sign.
450  strncpy(tmp_str, cstr, 2);
451  degrees = atof(tmp_str);
452 
453  // Get the minutes.
454  tmp_str[2] = '\0';
455  cstr += 2; // Increment to the minutes.
456  strncpy(tmp_str, cstr, 2);
457  degrees += atof(tmp_str) / 60.0;
458 
459  // Get the seconds.
460  tmp_str[5] = '\0';
461  cstr += 2; // Increment to seconds.
462  strncpy(tmp_str, cstr, 5);
463  degrees += atof(tmp_str) / 3600.0;
464 
465  // Set the sign.
466  degrees *= sign;
467 
468  return degrees;
469 }
ossim_uint32 theSamplesInTiles
const char * ExtractStringData(const char *pachData, int nMaxBytes, int *pnConsumedBytes)
Extract a zero terminated string containing the data for this subfield.
Real sign(Real x, Real y)
Definition: newmatrm.h:108
ossim_uint32 tim(ossim_uint32 row, ossim_uint32 col) const
Information from the DDR defining one field.
Definition: ossimIso8211.h:179
int GetDataSize()
Return the number of bytes in the data block returned by GetData().
Definition: ossimIso8211.h:512
std::ostream & operator<<(std::ostream &os, const ossimAdrgHeader &adrg)
ossimString theMinLon
ossimString theMaxLon
ossimDDFField * FindField(const char *, int=0)
Find the named field within this record.
double minLongitude() const
ossimFilename theImageFile
const char * GetSubfieldData(ossimDDFSubfieldDefn *, int *=NULL, int=0)
Fetch raw data pointer for a particular subfield of this field.
ossimString theTif
This object represents one field in a DDFRecord.
Definition: ossimIso8211.h:492
ossim_uint32 thePixelType
double parseLongitudeString(const ossimString &lon) const
double parseLatitudeString(const ossimString &lat) const
bool exists() const
ossim_uint32 lines() const
std::string::size_type size() const
Definition: ossimString.h:405
unsigned int ossim_uint32
const char * chars() const
For backward compatibility.
Definition: ossimString.h:77
ossimDDFSubfieldDefn * FindSubfieldDefn(const char *)
Find a subfield definition by it&#39;s mnemonic tag.
ErrorStatus theErrorStatus
ossim_uint32 * theTim
ossim_uint32 theStopCol
const char * GetData()
Return the pointer to the entire data block for this record.
Definition: ossimIso8211.h:509
ossim_uint32 theStartCol
ossim_uint32 theLines
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
ossim_uint32 theStartRow
ossim_uint32 theStopRow
ossimDDFFieldDefn * GetFieldDefn()
Fetch the corresponding DDFFieldDefn.
Definition: ossimIso8211.h:517
void Close()
Close an ISO 8211 file.
int Open(const char *pszFilename, int bFailQuietly=false)
Open a ISO 8211 (DDF) file for reading.
ossim_uint32 theInterleaveType
The primary class for reading ISO 8211 files.
Definition: ossimIso8211.h:88
ossimString theMaxLat
ossimFilename fileNoExtension() const
ossimDDFRecord * ReadRecord(void)
Read one record from the file.
ossim_uint32 theHeaderSize
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
ossimString theMinLat
ossim_uint32 theNumberOfBands
ossim_uint32 theLinesInTiles
Contains instance data from one data record (DR).
Definition: ossimIso8211.h:385
double maxLatitude() const
ossimString ext() const
ossim_uint32 theSamples
ossimFilename theHeaderFile
double minLatitude() const
ossimIrect theValidImageRect
ossim_uint32 samples() const
ossimFilename & setExtension(const ossimString &e)
Sets the extension of a file name.
int toInt() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
double maxLongitude() const
8 bit unsigned iteger
Information from the DDR record describing one subfield of a DDFFieldDefn.
Definition: ossimIso8211.h:278