core/vil/file_formats/vil_nitf2_image_subheader.cxx

Go to the documentation of this file.
00001 // vil_nitf2: Written by Rob Radtke (rob@) and Harry Voorhees (hlv@) of
00002 // Stellar Science Ltd. Co. (stellarscience.com) for
00003 // Air Force Research Laboratory, 2005.
00004 #include "vil_nitf2_image_subheader.h"
00005 //:
00006 // \file
00007 #include "vil_nitf2_data_mask_table.h"
00008 #include "vil_nitf2_field_functor.h"
00009 #include "vil_nitf2_field_definition.h"
00010 #include "vil_nitf2_typed_field_formatter.h"
00011 #include "vil_nitf2_index_vector.h"
00012 // for TREs
00013 #include "vil_nitf2_tagged_record_definition.h"
00014 
00015 #include <vcl_sstream.h>
00016 #include <vcl_cassert.h>
00017 
00018 vil_nitf2_field_definitions* vil_nitf2_image_subheader::s_field_definitions_21 = 0;
00019 vil_nitf2_field_definitions* vil_nitf2_image_subheader::s_field_definitions_20 = 0;
00020 
00021 vil_nitf2_image_subheader::vil_nitf2_image_subheader(vil_nitf2_classification::file_version version)
00022   : m_field_sequence(version == vil_nitf2_classification::V_NITF_20 ?
00023                      *get_field_definitions_20() :
00024                      *get_field_definitions_21()),
00025     m_data_mask_table(0),
00026     m_version(version)
00027 { 
00028     add_rpc_definitions(); 
00029     add_USE_definitions();
00030     add_ICHIPB_definitions();
00031     add_MPD26A_definitions();
00032     add_STDIDB_definitions();
00033     add_STDIDC_definitions();              
00034  }
00035 
00036 vil_nitf2_image_subheader::~vil_nitf2_image_subheader()
00037 {
00038   if (m_data_mask_table) delete m_data_mask_table;//jlm
00039   if(vil_nitf2_tagged_record_definition::all_definitions().size()){
00040   vil_nitf2_tagged_record_definition::undefine("RPC00A");
00041   vil_nitf2_tagged_record_definition::undefine("RPC00B");}
00042 }
00043 
00044 bool vil_nitf2_image_subheader::read(vil_stream* stream)
00045 {
00046   bool success = m_field_sequence.read(*stream);
00047 
00048   if (success)
00049   {
00050     // If this image has a data mask, we need to parse that too
00051     vcl_string compression_code;
00052     get_property("IC", compression_code);
00053     if (compression_code.find_first_of("M") != vcl_string::npos) {
00054       vcl_string imode;
00055       get_property("IMODE", imode);
00056       m_data_mask_table = new vil_nitf2_data_mask_table(
00057                                                         get_num_blocks_x(), get_num_blocks_y(), nplanes(), imode);
00058       if (!m_data_mask_table->parse(stream)) return false;
00059     }
00060   }
00061   return success;
00062 }
00063 
00064 const vil_nitf2_field_definitions* vil_nitf2_image_subheader::get_field_definitions_21()
00065 {
00066   if (!s_field_definitions_21) {
00067     s_field_definitions_21 = new vil_nitf2_field_definitions();
00068     add_shared_field_defs_1(s_field_definitions_21);
00069     vil_nitf2_classification::add_field_defs(s_field_definitions_21, vil_nitf2_classification::V_NITF_21, "I", "Image");
00070     add_shared_field_defs_2(s_field_definitions_21);
00071     add_geo_field_defs(s_field_definitions_21, vil_nitf2_classification::V_NITF_21);
00072     add_shared_field_defs_3(s_field_definitions_21);
00073   }
00074   return s_field_definitions_21;
00075 }
00076 
00077 const vil_nitf2_field_definitions* vil_nitf2_image_subheader::get_field_definitions_20()
00078 {
00079   if (!s_field_definitions_20) {
00080     s_field_definitions_20 = new vil_nitf2_field_definitions();
00081     add_shared_field_defs_1(s_field_definitions_20);
00082     vil_nitf2_classification::add_field_defs(s_field_definitions_20, vil_nitf2_classification::V_NITF_20, "I", "Image");
00083     add_shared_field_defs_2(s_field_definitions_20);
00084     add_geo_field_defs(s_field_definitions_20, vil_nitf2_classification::V_NITF_20);
00085     add_shared_field_defs_3(s_field_definitions_20);
00086   }
00087   return s_field_definitions_20;
00088 }
00089 
00090 void vil_nitf2_image_subheader::
00091 add_shared_field_defs_3(vil_nitf2_field_definitions* defs)
00092 {
00093   (*defs)
00094     .field("NICOM", "Number of Image Comments", NITF_INT(1), false, 0, 0)
00095 
00096     //TODO: does it make any sense for a vcl_vector to have blank entries????  For now, I'm saying no (false parameter)
00097     .repeat("NICOM", vil_nitf2_field_definitions()
00098 
00099             .field("ICOMn", "Image Comment n", NITF_STR_ECSA(80), false, 0, 0))
00100 
00101     .field("IC", "Image Compression",
00102            NITF_ENUM(2, vil_nitf2_enum_values()
00103                      .value("NC", "Not compressed")
00104                      .value("NM", "Uncompressed - contains block mask and/or pad pixel mask")
00105                      .value("C1", "Bi-level")
00106                      .value("C3", "JPEG")
00107                      .value("C4", "Vector Quantization")
00108                      .value("C5", "Lossless JPEG")
00109                      .value("C6", "Reserved - future correlated multicomponent compression")
00110                      .value("C7", "Reserved - future SAR compression")
00111                      .value("C8", "JPEG2000")
00112                      .value("I1", "Downsampled JPEG")
00113                      .value("M1", "Compressed - contains block mask and/or pad pixel mask")
00114                      .value("M3", "Compressed - contains block mask and/or pad pixel mask")
00115                      .value("M4", "Compressed - contains block mask and/or pad pixel mask")
00116                      .value("M5", "Compressed - contains block mask and/or pad pixel mask")
00117                      .value("M6", "Reserved - future correlated multicomponent compression")
00118                      .value("M7", "Reserved - future SAR compression")
00119                      .value("M8", "JPEG2000 - contains block mask and/or pad pixel mask")),
00120            false, 0, 0);
00121 
00122   vcl_vector<vcl_string> comp_ic_values;
00123   comp_ic_values.push_back("C1");
00124   comp_ic_values.push_back("C3");
00125   comp_ic_values.push_back("C4");
00126   comp_ic_values.push_back("C5");
00127   comp_ic_values.push_back("C8");
00128   comp_ic_values.push_back("M1");
00129   comp_ic_values.push_back("M3");
00130   comp_ic_values.push_back("M4");
00131   comp_ic_values.push_back("M5");
00132   comp_ic_values.push_back("M8");
00133   comp_ic_values.push_back("I1");
00134 
00135   // Using string because the valid enum values are different based on the content of IC
00136   (*defs)
00137     .field("COMRAT", "Compression Rate Code",         NITF_STR_BCSA(4),true, 0,
00138            new vil_nitf2_field_value_one_of<vcl_string>("IC", comp_ic_values))
00139 
00140     // The value of IREP determines which values are acceptable here
00141     // (e.g., if IREP=MONO, then this must equal 1)
00142     .field("NBANDS", "Number of Bands",               NITF_INT(1), false, 0, 0)
00143 
00144     // Acceptable range [00010-99999]... only used if NBANDS=0
00145     .field("XBANDS", "Number of multispectral bands", NITF_INT(5), true, 0,
00146            new vil_nitf2_field_value_one_of<int>("NBANDS",0))
00147 
00148     .repeat(new vil_nitf2_choose_field_value<int>(
00149                                                   "NBANDS", "XBANDS", new vil_nitf2_field_value_greater_than<int>("NBANDS", 0)),
00150             vil_nitf2_field_definitions()
00151 
00152             .field("IREPBAND", "nth Band Representation",             NITF_STR_BCSA(2), true, 0, 0)
00153             .field("ISUBCAT",  "nth Band Subcategory",                NITF_STR_BCSA(6), true, 0, 0)
00154             .field("IFC",      "nth Image Filter Condition",          NITF_STR_BCSA(1), false, 0, 0)
00155             .field("IMFLT",    "nth Band Standard Image Filter Code", NITF_STR_BCSA(3), true, 0, 0)
00156             .field("NLUTS",    "Number of LUTS for the nth Image Band",        NITF_INT(1, false),  false, 0, 0)
00157             .field("NELUT",    "Number of LUT Entries for the nth Image Band", NITF_INT(5, false),  false, 0,
00158                    new vil_nitf2_field_value_greater_than<int>("NLUTS", 0) /*condition*/ )
00159 
00160             .repeat(new vil_nitf2_field_value<int>("NLUTS"), vil_nitf2_field_definitions()
00161 
00162                     .field("LUTDnm", "nth Image Band, mth LUT",             NITF_BIN(1), false,
00163                            new vil_nitf2_field_value<int>("NELUT"), 0))
00164             )
00165 
00166     .field("ISYNC", "Image Sync Code", NITF_INT(1),  false, 0, 0)
00167     .field("IMODE", "Image Mode",
00168            NITF_ENUM(1, vil_nitf2_enum_values()
00169                      .value("B", "Band interleaved by block")
00170                      .value("P", "Band interleaved by pixel")
00171                      .value("R", "Band interleaved by row")
00172                      .value("S", "Band sequential")),
00173            false, 0, 0)
00174 
00175     .field("NBPR",  "Number of Blocks per Row",              NITF_INT(4), false, 0, 0)
00176     .field("NBPC",  "Number of Blocks per Column",           NITF_INT(4), false, 0, 0)
00177     .field("NPPBH", "Number of Pixels per Block Horizontal", NITF_INT(4), false, 0, 0) //[0000-8192]
00178     .field("NPPBV", "Number of Pixels per Block Vertical",   NITF_INT(4), false, 0, 0) //[0000-8192]
00179     .field("NBPP",  "Number of Bits per Pixel per Band",     NITF_INT(2), false, 0, 0) //[01-96]
00180     .field("IDLVL", "Image Display Level",                   NITF_INT(3), false, 0, 0)
00181     .field("IALVL", "Attachment Level",                      NITF_INT(3), false, 0, 0) //[000-998]
00182 
00183     // TODO: Enter these two values as ints with optional sign (once supported)
00184     // Actually, since they are both in one field, maybe we'd want to make it one
00185     // compound field (in the new tree format)
00186     .field("ILOC_ROW", "Image Location Row",            NITF_STR_BCSA(5), false, 0, 0)
00187     .field("ILOC_COL", "Image Location Column",         NITF_STR_BCSA(5), false, 0, 0)
00188 
00189     // TODO: THis should be a decimal field that supports non-negative power of two
00190     // fractions (eg '/2  ' means 1/2, '/16 'means 1/16
00191     .field("IMAG",  "Image Magnification",              NITF_STR_BCSA(4), false, 0, 0)
00192     .field("UDIDL", "User Defined Image Data Length",        NITF_INT(5), false, 0, 0) //[00000,00003-99999]
00193 
00194     .field("UDOFL", "User Defined Overflow",                 NITF_INT(3), false, 0,
00195            new vil_nitf2_field_value_greater_than<int>("UDIDL", 0))
00196 
00197     .field("UDID", "User Defined Image Data",                NITF_TRES(), false,
00198            new vil_nitf2_max_field_value_plus_offset_and_threshold("UDIDL", -3), 0)
00199 
00200     .field("IXSHDL", "Image Extended Subheader Data Length", NITF_INT(5), false, 0, 0)
00201 
00202     .field("IXSOFL", "Image Extended Subheader Overflow",    NITF_INT(3), false, 0,
00203            new vil_nitf2_field_value_greater_than<int>("IXSHDL", 0))
00204 
00205     .field("IXSHD", "Image Extended Subheader Data",         NITF_TRES(), false,
00206            new vil_nitf2_max_field_value_plus_offset_and_threshold("IXSHDL", -3), 0);
00207 }
00208 
00209 void vil_nitf2_image_subheader::add_geo_field_defs(vil_nitf2_field_definitions* defs,
00210                                                    const vil_nitf2_classification::file_version& version)
00211 {
00212   switch (version)
00213   {
00214     case vil_nitf2_classification::V_NITF_20:
00215     {
00216       (*defs)
00217         .field("ICORDS", "Image Coordinate Representation",
00218 
00219                NITF_ENUM(1, vil_nitf2_enum_values()
00220                          .value("U", "UTM")
00221                          .value("G", "Geodetic/Geographic")
00222                          .value("N", "None")
00223                          .value("C", "Geocentric")),
00224 
00225                false, 0, 0);
00226 
00227       vcl_vector<vcl_string> igeolo_icords;
00228       igeolo_icords.push_back("U");
00229       igeolo_icords.push_back("G");
00230       igeolo_icords.push_back("C");
00231 
00232       (*defs)
00233         .field("IGEOLO", "Image Geographic Location", NITF_STR_BCSA(60), false, 0,
00234                new vil_nitf2_field_value_one_of<vcl_string>("ICORDS", igeolo_icords));
00235       break;
00236     }
00237     case vil_nitf2_classification::V_NITF_21:
00238     {
00239       (*defs)
00240         .field("ICORDS", "Image Coordinate Representation",
00241 
00242                NITF_ENUM(1, vil_nitf2_enum_values()
00243                          .value("U", "UTM expressed in MGRS form")
00244                          .value("G", "Geographic")
00245                          .value("N", "UTM/UPS (Northern hemisphere)") // actually means None for Nitf 2.0
00246                          .value("S", "UTM/UPS (Southern hemisphere)") // NITF 2.1 only
00247                          .value("D", "Decimal degrees")),             // NITF 2.1 only
00248 
00249                true, 0, 0)
00250 
00251         .field("IGEOLO", "Image Geographic Location", NITF_STR_BCSA(60), false, 0,
00252                new vil_nitf2_field_specified("ICORDS"));
00253       break;
00254     }
00255     default:
00256       assert(!"unsupported case");
00257   } // end switch
00258 }
00259 
00260 void vil_nitf2_image_subheader::add_shared_field_defs_2(vil_nitf2_field_definitions* defs)
00261 {
00262   (*defs)
00263     .field("ENCRYP", "Encryption",
00264            NITF_ENUM(1, vil_nitf2_enum_values()
00265                      // Only one valid value, until the spec gets updated
00266                      .value("0", "Not Encrypted")),
00267            false, 0, 0)
00268     .field("ISORCE", "Image Source", NITF_STR_ECSA(42),  true, 0, 0)
00269     //TODO: only allow range [00000001-99999999]
00270     .field("NROWS", "Number of Significant Rows in Image", NITF_INT(8, false), false, 0, 0)
00271     //TODO: only allow range [00000001-99999999]
00272     .field("NCOLS", "Number of Significant Columns in Image", NITF_INT(8, false), false, 0, 0)
00273     .field("PVTYPE", "Pixel Value Type",
00274            NITF_ENUM(3, vil_nitf2_enum_values()
00275                      .value("INT", "Integer")
00276                      .value("B",   "Bi-level")
00277                      .value("SI",  "2's complement signed integer")
00278                      .value("R",   "Real")
00279                      .value("C",   "Complex")),
00280            false, 0, 0)
00281     .field("IREP", "Image Representation",
00282            NITF_ENUM(8, vil_nitf2_enum_values()
00283                      .value("MONO",     "Monochrome")
00284                      .value("RGB",      "Red, green, blue true color")
00285                      .value("RGB/LUT",  "Red, green, blue mapped Color")
00286                      .value("MULTI",    "Multiband imagery")
00287                      .value("NODISPLY", "Not intended for display")
00288                      .value("NVECTOR",  "Cartesian coordinates")
00289                      .value("POLAR",    "Polar coordinates")
00290                      .value("VPH",      "SAR video phase history")
00291                      .value("YCbCr601", "BT.601-5 color space")),
00292            false, 0, 0)
00293 #ifdef UNCLASS_ONLY
00294     .field("ICAT", "Image Category",
00295            NITF_ENUM(8, vil_nitf2_enum_values()
00296                      .value("VIS",    "Visible imagery")
00297                      .value("SL",     "Side-looking radar")
00298                      .value("TI",     "Thermal infrared")
00299                      .value("FL",     "Forward-looking radar")
00300                      .value("RD",     "Radar")
00301                      .value("EO",     "Electro-optical")
00302                      .value("OP",     "Optical")
00303                      .value("HR",     "High-resolution radar")
00304                      .value("HS",     "Hyperspectral")
00305                      .value("CP",     "Color frame photography")
00306                      .value("BP",     "Black/white frame photography")
00307                      .value("SARIQ",  "SAR radio hologram")
00308                      .value("SAR",    "Synthetic aperture radar")
00309                      .value("IR",     "Infrared")
00310                      .value("MS",     "Multispectral")
00311                      .value("FP",     "Fingerprints")
00312                      .value("MRI",    "Magnetic resonance imagery")
00313                      .value("XRAY",   "X-ray")
00314                      .value("CAT",    "CAT scan")
00315                      .value("VD",     "Video")
00316                      .value("BARO",   "Barometric pressure")
00317                      .value("CURRENT","Water current")
00318                      .value("DEPTH",  "Water depth")
00319                      .value("MAP",    "Raster map")
00320                      .value("PAT",    "Color patch")
00321                      .value("LEG",    "Legends")
00322                      .value("DTEM",   "Elevation models")
00323                      .value("MATR",   "Matrix data (other types)")
00324                      .value("LOCG",   "Location Grids")),
00325            false, 0, 0)
00326 #else
00327     .field("ICAT", "Image Category", NITF_STR_ECSA(8), false, 0, 0)
00328 #endif //UNCLASS_ONLY
00329 
00330     .field("ABPP", "Actual Bits Per Pixel per Band", NITF_INT(2), false, 0, 0) //[1-96]
00331     .field("PJUST", "Pixel Justification",
00332            NITF_ENUM(1, vil_nitf2_enum_values()
00333                      .value("L", "Left-justified")
00334                      .value("R", "Right-justified")),
00335            false, 0, 0);
00336 }
00337 
00338 void vil_nitf2_image_subheader::add_shared_field_defs_1(vil_nitf2_field_definitions* defs)
00339 {
00340   (*defs)
00341     .field("IM", "File Part Type",
00342            NITF_ENUM(2, vil_nitf2_enum_values()
00343                      .value("IM", "Image Header")))
00344     .field("IID1", "Image Identifier 1", NITF_STR_BCSA(10))
00345 
00346     // order of data/time depends on NITF2.1 or NITF2.0, so just read in as string for now
00347     //.field("IDATIM", "Image Date and Time", NITF_DAT(14)));
00348     .field("IDATIM", "Image Date and Time", NITF_STR_BCSA(14))
00349     .field("TGTID",  "Target Identifier",   NITF_STR_BCSA(17), true)
00350     .field("IID2",   "Image Identifier 2",  NITF_STR_ECSA(80), true);
00351 }
00352 
00353 unsigned vil_nitf2_image_subheader::nplanes() const
00354 {
00355   //the number of image bands is stored in NBANDS unless NBANDS=0.
00356   //in that case, then it's stored under XBANDS.  That's why we have
00357   //to potentially try both
00358   int numBands;
00359   if (get_property("NBANDS", numBands))
00360   {
00361     if (numBands > 0 ||
00362         get_property("XBANDS", numBands))
00363     {
00364       return numBands;
00365     }
00366   }
00367   return 0;
00368 }
00369 
00370 unsigned int vil_nitf2_image_subheader::get_pixels_per_block_x() const
00371 {
00372   int pixels_per_block;
00373   if (get_property("NPPBH", pixels_per_block)) {
00374     return pixels_per_block;
00375   }
00376   return 0;
00377 }
00378 
00379 unsigned int vil_nitf2_image_subheader::get_pixels_per_block_y() const
00380 {
00381   int pixels_per_block;
00382   if (get_property("NPPBV", pixels_per_block)) {
00383     return pixels_per_block;
00384   }
00385   return 0;
00386 }
00387 
00388 unsigned int vil_nitf2_image_subheader::get_num_blocks_x() const
00389 {
00390   int blocks_per_row;
00391   if (get_property("NBPR", blocks_per_row)) {
00392     return blocks_per_row;
00393   }
00394   return 0;
00395 }
00396 
00397 unsigned int vil_nitf2_image_subheader::get_num_blocks_y() const
00398 {
00399   int blocks_per_col;
00400   if (get_property("NBPC", blocks_per_col)) {
00401     return blocks_per_col;
00402   }
00403   return 0;
00404 }
00405 
00406 bool vil_nitf2_image_subheader::get_lut_info(unsigned int band,
00407                                              int& n_luts, int& ne_lut,
00408                                              vcl_vector< vcl_vector< unsigned char > >& lut_d) const
00409 {
00410   if (!m_field_sequence.get_value("NLUTS", vil_nitf2_index_vector(band), n_luts) ||
00411       !m_field_sequence.get_value("NELUT", vil_nitf2_index_vector(band), ne_lut)) {
00412     return false;
00413   } 
00414   lut_d.clear();
00415   lut_d.resize(n_luts);
00416   void* raw_lut_data; 
00417   for (int lut_index = 0 ; lut_index < n_luts ; lut_index++) {
00418     lut_d[lut_index].resize(ne_lut);
00419     //get the lut_index'th lut for the given image band
00420     vil_nitf2_index_vector index( band, lut_index );
00421     if (m_field_sequence.get_value("LUTDnm", index, raw_lut_data )) {
00422       for( int el_index = 0 ; el_index < ne_lut ; el_index++ ) {
00423         lut_d[lut_index][el_index] = static_cast<unsigned char*>(raw_lut_data)[el_index];
00424       }
00425     } else {
00426       break;
00427     }
00428   }
00429   return true;
00430 }
00431 
00432 vil_nitf2_field::field_tree* vil_nitf2_image_subheader::get_tree( int i ) const
00433 {
00434   vil_nitf2_field::field_tree* t = new vil_nitf2_field::field_tree;
00435   vcl_stringstream name_stream;
00436   name_stream << "Image Subheader";
00437   if ( i > 0 ) name_stream << " #" << i;
00438   t->columns.push_back( name_stream.str() );
00439   m_field_sequence.get_tree( t );
00440   return t;
00441 }
00442 
00443 // Add definitions for rational polynomial coefficients
00444 void vil_nitf2_image_subheader::add_rpc_definitions()
00445 {
00446   vil_nitf2_tagged_record_definition* tr =
00447     vil_nitf2_tagged_record_definition::find("RPC00B");
00448   if (!tr)
00449   {
00450     vil_nitf2_tagged_record_definition::define("RPC00B", "Rational Polynomial Coefficients Type B" )
00451 
00452     // These are the "offset and scale" fields that precede the polynomial coefficients
00453     .field("SUCCESS",     "Success parameter",  NITF_INT(1))                 // not used, but must read
00454     .field("ERR_BIAS",    "ERR_BIAS",           NITF_DBL(7, 2, false), true) // not used, but must read
00455     .field("ERR_RAND",    "ERR_RAND",           NITF_DBL(7, 2, false), true) // not used
00456     .field("LINE_OFF",    "Line Offset",        NITF_INT(6))
00457     .field("SAMP_OFF",    "Sample Offset",      NITF_INT(5))
00458     .field("LAT_OFF",     "Latitude Offset",    NITF_DBL(8, 4, true), false)
00459     .field("LON_OFF",     "Longitude offset",   NITF_DBL(9, 4, true), false)
00460     .field("HEIGHT_OFF",  "Height Offset",      NITF_INT(5, true))
00461     .field("LINE_SCALE",  "Line Scale",         NITF_INT(6))
00462     .field("SAMP_SCALE",  "Sample Scale",       NITF_INT(5))
00463     .field("LAT_SCALE",   "Latitude Scale",     NITF_DBL(8, 4, true), false)
00464     .field("LON_SCALE",   "Longitude Scale",    NITF_DBL(9, 4, true), false)
00465     .field("HEIGHT_SCALE", "Height Scale",      NITF_INT(5, true))
00466 
00467     // Now come the 4 sequential groups of (20 each) polynomial coefficients
00468     //   for line number, line density, sample number and sample density.
00469     // As these values are in <+/->n.nnnnnnE<+/->n (exponential) format,
00470     //   let's just read as strings now and convert into doubles later.
00471 
00472     .repeat(20, vil_nitf2_field_definitions()
00473             .field("LNC",        "Line Number Coefficient",    NITF_EXP(6,1))
00474            )
00475     .repeat(20, vil_nitf2_field_definitions()
00476             .field("LDC",        "Line Density Coefficient",   NITF_EXP(6,1))
00477            )
00478     .repeat(20, vil_nitf2_field_definitions()
00479             .field("SNC",        "Sample Number Coefficient",  NITF_EXP(6,1))
00480            )
00481     .repeat(20, vil_nitf2_field_definitions()
00482             .field("SDC",        "Sample Density Coefficient", NITF_EXP(6,1))
00483            )
00484     .end();  // of RPC TRE
00485   }
00486   tr =vil_nitf2_tagged_record_definition::find("RPC00A");
00487   if (!tr)
00488   {
00489     vil_nitf2_tagged_record_definition::define("RPC00A", "Rational Polynomial Coefficients Type A" )
00490 
00491     // These are the "offset and scale" fields that precede the polynomial coefficients
00492     .field("SUCCESS",     "Success parameter",  NITF_INT(1))                 // not used, but must read
00493     .field("ERR_BIAS",    "ERR_BIAS",           NITF_DBL(7, 2, false), true) // not used, but must read
00494     .field("ERR_RAND",    "ERR_RAND",           NITF_DBL(7, 2, false), true) // not used
00495     .field("LINE_OFF",    "Line Offset",        NITF_INT(6))
00496     .field("SAMP_OFF",    "Sample Offset",      NITF_INT(5))
00497     .field("LAT_OFF",     "Latitude Offset",    NITF_DBL(8, 4, true), false)
00498     .field("LON_OFF",     "Longitude offset",   NITF_DBL(9, 4, true), false)
00499     .field("HEIGHT_OFF",  "Height Offset",      NITF_INT(5, true))
00500     .field("LINE_SCALE",  "Line Scale",         NITF_INT(6))
00501     .field("SAMP_SCALE",  "Sample Scale",       NITF_INT(5))
00502     .field("LAT_SCALE",   "Latitude Scale",     NITF_DBL(8, 4, true), false)
00503     .field("LON_SCALE",   "Longitude Scale",    NITF_DBL(9, 4, true), false)
00504     .field("HEIGHT_SCALE", "Height Scale",      NITF_INT(5, true))
00505 
00506     // Now come the 4 sequential groups of (20 each) polynomial coefficients
00507     //   for line number, line density, sample number and sample density.
00508     // As these values are in <+/->n.nnnnnnE<+/->n (exponential) format,
00509     //   let's just read as strings now and convert into doubles later.
00510 
00511     .repeat(20, vil_nitf2_field_definitions()
00512             .field("LNC",        "Line Number Coefficient",    NITF_EXP(6,1))
00513            )
00514     .repeat(20, vil_nitf2_field_definitions()
00515             .field("LDC",        "Line Density Coefficient",   NITF_EXP(6,1))
00516            )
00517     .repeat(20, vil_nitf2_field_definitions()
00518             .field("SNC",        "Sample Number Coefficient",  NITF_EXP(6,1))
00519            )
00520     .repeat(20, vil_nitf2_field_definitions()
00521             .field("SDC",        "Sample Density Coefficient", NITF_EXP(6,1))
00522            )
00523     .end();  // of RPCA TRE
00524   }
00525 }
00526 void vil_nitf2_image_subheader::add_USE_definitions()
00527 {
00528   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("USE00A");
00529   if (!tr)
00530   {
00531     vil_nitf2_tagged_record_definition::define("USE00A", "EXPLOITATION USABILITY EXTENSION FORMAT" )
00532 
00533     .field("ANGLE_TO_NORTH","Angle to North",  NITF_INT(3))                 // not used, but must read
00534     .field("MEAN_GSD",      "Mean Ground Sample Distance",NITF_DBL(5, 1, false), false) // not used, but must read
00535     .field("Reserved1", "",NITF_STR(1), false)
00536     .field("DYNAMIC_RANGE", "Dynamic Range",NITF_LONG(5,  false), true) // not used
00537     .field("Reserved2", "",NITF_STR(7), false)
00538     .field("OBL_ANG",       "Obliquity Angle",        NITF_DBL(5,2,false), true)
00539     .field("ROLL_ANG",      "Roll Angle",     NITF_DBL(6,2,true), true)
00540     .field("Reserved3", "",NITF_STR(37), false)
00541     .field("N_REF",         "Number of Reference Lines.",      NITF_INT(2, false), false)
00542     .field("REV_NUM",       "Revolution Number",    NITF_LONG(5, false), false)
00543     .field("N_SEG",         "Number of Segments",   NITF_INT(3,  false), false)
00544     .field("MAX_LP_SEG",    "Maximum Lines Per Segment",         NITF_LONG(6,false), true)
00545     .field("Reserved4", "",NITF_STR(12), false)
00546     .field("SUN_EL",        "Sun Elevation",       NITF_DBL(5,1,true),false)
00547     .field("SUN_AZ",        "Sun Azimuth",     NITF_DBL(5,1,false),false)
00548 
00549 
00550     .end();  // of USE00A TRE
00551   }
00552 }
00553 // Collect the Sun angles
00554   bool vil_nitf2_image_subheader::
00555 get_sun_params( double& sun_el, double& sun_az)
00556 {
00557 
00558   // Now get the sub-header TRE parameters
00559   vil_nitf2_tagged_record_sequence isxhd_tres;
00560   vil_nitf2_tagged_record_sequence::iterator tres_itr;
00561   this->get_property("IXSHD", isxhd_tres);
00562 
00563 
00564   bool success=false;
00565   // Check through the TREs to find "RPC"
00566   for (tres_itr = isxhd_tres.begin(); tres_itr != isxhd_tres.end(); ++tres_itr)
00567   {
00568       vcl_string type = (*tres_itr)->name();
00569       if( type == "USE00A")
00570       {
00571           success = (*tres_itr)->get_value("SUN_EL", sun_el);
00572           success = success && (*tres_itr)->get_value("SUN_AZ", sun_az);
00573           if(!success)
00574               vcl_cout<<"\n Error reading USE00A \n";
00575           else
00576               return success;
00577       }
00578       else if( type == "MPD26A")
00579       {
00580           success = (*tres_itr)->get_value("SUN_EL", sun_el);
00581           success = success && (*tres_itr)->get_value("SUN_AZ", sun_az);
00582           if(!success)
00583               vcl_cout<<"\n Error reading MPD26A \n";
00584           else
00585               return success;
00586       }
00587 }
00588   return success;
00589 }
00590 void vil_nitf2_image_subheader::add_ICHIPB_definitions()
00591 {
00592   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("ICHIPB");
00593   if (!tr)
00594   {
00595     vil_nitf2_tagged_record_definition::define("ICHIPB", "ICHIPB SUPPORT DATA EXTENSION" )
00596 
00597     .field("XFRM_FLAG",    "Non-linear Transformation Flag",  NITF_INT(2),false)                 // not used, but must read
00598     .field("SCALE_FACTOR", "Scale Factor Relative to R0",NITF_DBL(10, 5, false), false) // not used, but must read
00599     .field("ANAMRPH_CORR", "Anamorphic Correction Indicator", NITF_INT(2),false)
00600     .field("SCANBLK_NUM",  "Scan Block Number",NITF_INT(2,  false), true) // not used
00601     //: intelligent data
00602     .field("OP_ROW_11", "Output product row number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00603     .field("OP_COL_11", "Output product column number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00604 
00605     .field("OP_ROW_12", "Output product row number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00606     .field("OP_COL_12", "Output product column number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00607 
00608     .field("OP_ROW_21", "Output product row number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00609     .field("OP_COL_21", "Output product column number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00610 
00611     .field("OP_ROW_22", "Output product row number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00612     .field("OP_COL_22", "Output product column number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00613 
00614     //: full image coordinate system
00615     .field("FI_ROW_11", "Output product row number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00616     .field("FI_COL_11", "Output product column number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00617 
00618     .field("FI_ROW_12", "Output product row number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00619     .field("FI_COL_12", "Output product column number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00620 
00621     .field("FI_ROW_21", "Output product row number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00622     .field("FI_COL_21", "Output product column number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00623 
00624     .field("FI_ROW_22", "Output product row number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00625     .field("FI_COL_22", "Output product column number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00626 
00627     .field("FI_ROW",      "Full Image Number of Rows",     NITF_LONG(8,false), false)
00628     .field("FI_COL",      "Full Image Number of COlumns",     NITF_LONG(8,false), false)
00629 
00630 
00631     .end();  // of ICHIPB TRE
00632   }
00633 }
00634 
00635 
00636 void vil_nitf2_image_subheader::add_STDIDC_definitions()
00637 {
00638   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("STDIDC");
00639   if (!tr)
00640   {
00641     vil_nitf2_tagged_record_definition::define("STDIDC", "STDIDC SUPPORT DATA EXTENSION" )
00642 
00643     .field("ACQUISITION_DATE",    "",  NITF_STR(14),false)                 // not used, but must read
00644     .field("MISSION", "",NITF_STR(14), false) // not used, but must read
00645     .field("PASS", "", NITF_STR(2),false)
00646     .field("OP_NUM",  "",NITF_INT(3,  false), false) // not used
00647     .field("START_SEGMENT", "",NITF_STR(2), false)
00648     .field("REPRO_NUM", "",NITF_INT(2,false), false)
00649     .field("REPLAY_REGEN", "",NITF_STR(3), false)
00650     .field("BLANK_FILL", "",NITF_STR(1), true)
00651     .field("START_COLUMN", "",NITF_INT(3,false), false)
00652     .field("START_ROW", "",NITF_INT(5,false), false)
00653     .field("END_SEGMENT", "",NITF_STR(2), false)
00654     .field("END_COLUMN", "",NITF_INT(3,false), false)
00655     .field("END_ROW", "",NITF_INT(5,false), false)
00656     .field("COUNTRY", "",NITF_STR(2), true)
00657     .field("WAC", "",NITF_INT(4,false), true)
00658     .field("LOCATION", "",NITF_STR(11), false)
00659     .field("RESERVED1", "",NITF_STR(5), true)
00660     .field("RESERVED2", "",NITF_STR(8), true)
00661 
00662 
00663 
00664     .end();  // of STDIDC TRE
00665   }
00666 
00667 
00668 
00669 }
00670 
00671 
00672 void vil_nitf2_image_subheader::add_STDIDB_definitions()
00673 {
00674   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("STDIDB");
00675   if (!tr)
00676   {
00677     vil_nitf2_tagged_record_definition::define("STDIDB", "STDIDB SUPPORT DATA EXTENSION" )
00678 
00679     .field("unk1",    "",  NITF_INT(2,false),false)                 // not used, but must read
00680     .field("unk2",    "",  NITF_STR(3),false)                 // not used, but must read
00681     .field("unk3",    "",  NITF_INT(2,false),false)                 // not used, but must read
00682     .field("unk4",    "",  NITF_INT(4,false),false)                 // not used, but must read
00683     .field("unk5",    "",  NITF_STR(2),false)                 // not used, but must read
00684     .field("unk6",    "",  NITF_INT(3,false),false)                 // not used, but must read
00685     .field("unk7",    "",  NITF_STR(2),false)                 // not used, but must read
00686     .field("unk8",    "",  NITF_INT(2,false),false) 
00687     .field("unk9",    "",  NITF_STR(3),false)    // not used, but must read
00688     .field("unk10",    "",  NITF_STR(1),false) 
00689     .field("START_COLUMN",    "",  NITF_STR(2),false) 
00690     .field("START_ROW",    "",  NITF_INT(5,false),false) 
00691     .field("unk11",    "",  NITF_STR(2),false)                 // not used, but must read
00692     .field("unk12",    "",  NITF_STR(2),false)                 // not used, but must read
00693     .field("unk13",    "",  NITF_INT(5,false),false)                 // not used, but must read
00694     .field("unk14",    "",  NITF_STR(2),false)                 // not used, but must read
00695     .field("unk15",    "",  NITF_INT(4,false),false)                 // not used, but must read
00696     .field("unk16",    "",  NITF_STR(4),false)                 // not used, but must read
00697     .field("unk17",    "",  NITF_STR(1),false)                 // not used, but must read
00698     .field("unk18",    "",  NITF_STR(5),false) 
00699     .field("unk19",    "",  NITF_STR(1),false)    // not used, but must read
00700     .field("unk20",    "",  NITF_STR(5),false) 
00701     .