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     .field("unk21",    "",  NITF_STR(7),false) 
00702 
00703 
00704 
00705 
00706 
00707 
00708     .end();  // of STDIDC TRE
00709   }
00710 
00711 
00712 
00713 }
00714 
00715 
00716 
00717 void vil_nitf2_image_subheader::add_MPD26A_definitions()
00718 {
00719   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("MPD26A");
00720   if (!tr)
00721   {
00722     vil_nitf2_tagged_record_definition::define("MPD26A", "MPD26A SUPPORT DATA EXTENSION" )
00723 
00724         .field("UNK1",    "Unknown ",  NITF_DBL(11,1,false), false) // not used, but must read
00725         .field("UNK2",    "Unknown ",  NITF_STR(2), false) // not used, but must read
00726         .field("UNK3",    "Unknown ",  NITF_INT(7,false),false)                 // not used, but must read
00727         .field("UNK31",    "Unknown ", NITF_STR(10),false)                 // not used, but must read
00728         .field("UNK4",    "Unknown ",  NITF_DBL(6,1,false), true) // not used, but must read
00729         .field("UNK5",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00730         .field("UNK6",    "Unknown ",  NITF_STR(3), false) // not used, but must read
00731         .field("UNK7",    "Unknown ",  NITF_STR(1), false) // not used, but must read
00732         .field("UNK8",    "Unknown ",  NITF_STR(1), false) // not used, but must read
00733         .field("SUN_EL", "Sun Elevation angle", NITF_DBL(5,1,true),false)
00734         .field("SUN_AZ", "Sun Azimuthal angle", NITF_DBL(5,1,false),false)
00735         .field("UNK9",    "Unknown ",  NITF_INT(1,false), false) // not used, but must read
00736         .field("UNK10",    "Unknown ",  NITF_INT(1,false), false) // not used, but must read
00737         .field("UNK11",    "Unknown ",  NITF_INT(4,false), false) // not used, but must read
00738         .field("UNK12",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00739         .field("UNK13",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00740         .field("UNK14",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00741         .field("UNK15",    "Unknown ",  NITF_STR(10), false) // not used, but must read
00742         .field("UNK16",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00743         .field("UNK17",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00744         .field("UNK18",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00745         .field("UNK19",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00746         .field("UNK20",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00747         .field("UNK21",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00748         .field("UNK22",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00749         .field("UNK23",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00750         .field("UNK24",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00751         .field("UNK16",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00752         .field("UNK17",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00753         .field("UNK18",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00754         .field("UNK19",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00755         .field("UNK20",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00756         .field("UNK21",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00757         .field("UNK22",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00758         .field("UNK23",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00759         .field("UNK24",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00760         .field("UNK16",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00761         .field("UNK17",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00762         .field("UNK18",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00763         .field("UNK19",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00764         .field("UNK20",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00765         .field("UNK21",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00766         .field("UNK22",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00767         .field("UNK23",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00768         .field("UNK24",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00769 
00770     .end();  // of MPD26A TRE
00771   }
00772 }
00773 
00774 
00775 // obtain column and row offset from STDIDB /SDTDIDC
00776 bool vil_nitf2_image_subheader::
00777 get_correction_offset(double & u_off, double & v_off)
00778 {
00779   // Now get the sub-header TRE parameters
00780   vil_nitf2_tagged_record_sequence isxhd_tres;
00781   vil_nitf2_tagged_record_sequence::iterator tres_itr;
00782   this->get_property("IXSHD", isxhd_tres);
00783 
00784   bool success = false;
00785 
00786   double ulr=0;
00787   double ulc=0;
00788   // Check through the TREs to find "RPC"
00789   for (tres_itr = isxhd_tres.begin(); tres_itr != isxhd_tres.end(); ++tres_itr)
00790   {
00791       vcl_string type = (*tres_itr)->name();
00792       if ( type == "ICHIPB" )
00793       {
00794           double r_off;
00795           double c_off;
00796           success = (*tres_itr)->get_value("FI_ROW_11", r_off); 
00797           success = success && (*tres_itr)->get_value("FI_COL_11", c_off); 
00798           if(success)
00799           {
00800               ulr+=r_off;
00801               ulc+=c_off;
00802           }
00803 
00804       }
00805       if ( type == "STDIDC" )
00806       {
00807           int r_off=1;
00808           int c_off=1;
00809           success = (*tres_itr)->get_value("START_ROW", r_off); 
00810           success = success && (*tres_itr)->get_value("START_COLUMN", c_off); 
00811 
00812           if(success)
00813           {
00814               ulr+=(double)((r_off-1)*get_pixels_per_block_y());
00815               ulc+=(double)((c_off-1)*get_pixels_per_block_x());
00816           }
00817       }
00818       else if ( type == "STDIDB" )
00819       {
00820           int r_off=1;
00821           int c_off=1;
00822 
00823           success = (*tres_itr)->get_value("START_ROW", r_off); 
00824           vcl_string temp_off;
00825           success = success && (*tres_itr)->get_value("START_COLUMN", temp_off); 
00826           if((int)temp_off[0]>=65)
00827               c_off=((int)temp_off[0]-55)*10;
00828           else
00829               c_off=((int)temp_off[0]-48)*10;
00830 
00831           c_off+=(int)temp_off[1]-48;
00832           if(success)
00833           {
00834               ulr+=(r_off-1)*get_pixels_per_block_y();
00835               ulc+=(c_off-1)*get_pixels_per_block_x();
00836           }
00837       }
00838 
00839 
00840   }
00841   u_off=ulc;
00842   v_off=ulr;
00843   return success;
00844 }
00845 // Collect the RPC parameters for the current image. Image corners are reported
00846 // as a string of geographic coordinates,one for each image corner.
00847   bool vil_nitf2_image_subheader::
00848 get_rpc_params( vcl_string& rpc_type, vcl_string& image_id,
00849                 vcl_string& image_corner_geo_locations,
00850                 double* rpc_data )
00851 {
00852   // Get image ID and location from main header values
00853   vcl_string iid2 = "";
00854   bool success = this->get_property("IID2", iid2);
00855   if (!success) {
00856     vcl_cout << "IID2 Property failed in vil_nitf2_image_subheader\n";
00857     return false;
00858   }
00859   image_id = iid2.substr(0,39);// trim length to NN characters to match file ID
00860   vcl_string igeolo = "";
00861   success = this->get_property("IGEOLO", igeolo);
00862   if (!success) {
00863     vcl_cout << "IGEOLO Property failed in vil_nitf2_image_subheader\n";
00864     return false;
00865   }
00866   image_corner_geo_locations = igeolo;
00867 
00868   // Now get the sub-header TRE parameters
00869   vil_nitf2_tagged_record_sequence isxhd_tres;
00870   vil_nitf2_tagged_record_sequence::iterator tres_itr;
00871   this->get_property("IXSHD", isxhd_tres);
00872 
00873 
00874   // Check through the TREs to find "RPC"
00875   for (tres_itr = isxhd_tres.begin(); tres_itr != isxhd_tres.end(); ++tres_itr)
00876   {
00877     vcl_string type = (*tres_itr)->name();
00878 
00879     if ( type == "RPC00B" || type == "RPC00A") // looking for "RPC..."
00880     {
00881       // set type in return value
00882       rpc_type = type;
00883 
00884       // get offsets and scales, print a couple to make sure values are correct
00885       int line_off;
00886       success = (*tres_itr)->get_value("LINE_OFF", line_off);
00887       if (!success) {
00888         vcl_cout << "LINE_OFF Property failed in vil_nitf2_image_subheader\n";
00889         return false;
00890       }
00891       rpc_data[80] = line_off;
00892 
00893       int samp_off;
00894       success = (*tres_itr)->get_value("SAMP_OFF", samp_off);
00895       if (!success) {
00896         vcl_cout << "SAMP_OFF Property failed in vil_nitf2_image_subheader\n";
00897         return false;
00898       }
00899       rpc_data[81]  = samp_off;
00900 
00901       double lat_off;
00902       success = (*tres_itr)->get_value("LAT_OFF", lat_off);
00903       if (!success) {
00904         vcl_cout << "LAT_OFF Property failed in vil_nitf2_image_subheader\n";
00905         return false;
00906       }
00907       rpc_data[82] = lat_off;
00908 
00909       double lon_off;
00910       success = (*tres_itr)->get_value("LON_OFF", lon_off);
00911       if (!success) {
00912         vcl_cout << "LON_OFF Property failed in vil_nitf2_image_subheader\n";
00913         return false;
00914       }
00915       rpc_data[83] = lon_off;
00916 
00917       int height_off;
00918       success = (*tres_itr)->get_value("HEIGHT_OFF", height_off);
00919       if (!success) {
00920         vcl_cout << "HEIGHT_OFF Property failed in vil_nitf2_image_subheader\n";
00921         return false;
00922       }
00923       rpc_data[84] = height_off;
00924 
00925       int line_scale;
00926       success = (*tres_itr)->get_value("LINE_SCALE", line_scale);
00927       if (!success) {
00928         vcl_cout << "LINE_SCALE Property failed in vil_nitf2_image_subheader\n";
00929         return false;
00930       }
00931       rpc_data[85] = line_scale;
00932 
00933       int samp_scale;
00934       success = (*tres_itr)->get_value("SAMP_SCALE", samp_scale);
00935       if (!success) {
00936         vcl_cout << "SAMP_SCALE Property failed in vil_nitf2_image_subheader\n";
00937         return false;
00938       }
00939       rpc_data[86] = samp_scale;
00940 
00941       double lat_scale;
00942       success = (*tres_itr)->get_value("LAT_SCALE", lat_scale);
00943       if (!success) {
00944         vcl_cout << "LAT_SCALE Property failed in vil_nitf2_image_subheader\n";
00945         return false;
00946       }
00947       rpc_data[87] = lat_scale;
00948 
00949       double lon_scale;
00950       success = (*tres_itr)->get_value("LON_SCALE", lon_scale);
00951       if (!success) {
00952         vcl_cout << "LON_SCALE Property failed in vil_nitf2_image_subheader\n";
00953         return false;
00954       }
00955       rpc_data[88] = lon_scale;
00956 
00957       int height_scale;
00958       success = (*tres_itr)->get_value("HEIGHT_SCALE", height_scale);
00959       if (!success) {
00960         vcl_cout << "HEIGHT_SCALE Property failed in vil_nitf2_image_subheader\n";
00961         return false;
00962       }
00963       rpc_data[89] = height_scale;
00964 
00965       // finally get the 80 polynomial coefficients  ##################
00966       vcl_vector<double> LNC;
00967       success = (*tres_itr)->get_values("LNC", LNC);
00968       if (!success) {
00969         vcl_cout << "LNC Property failed in vil_nitf2_image_subheader\n";
00970         return false;
00971       }
00972       for (int i = 0; i < 20; i++) {
00973         rpc_data[i] = LNC[i];      // copy from vector to regular array.
00974       }
00975 
00976       vcl_vector<double> LDC;
00977       success = (*tres_itr)->get_values("LDC", LDC);
00978       if (!success) {
00979         vcl_cout << "LDC Property failed in vil_nitf2_image_subheader\n";
00980         return false;
00981       }
00982       for (int i = 0; i < 20; i++) {
00983         rpc_data[i+20] = LDC[i];   // copy from vector to regular array.
00984       }
00985 
00986       vcl_vector<double> SNC;
00987       success = (*tres_itr)->get_values("SNC", SNC);
00988       if (!success) {
00989         vcl_cout << "SNC Property failed in vil_nitf2_image_subheader\n";
00990         return false;
00991       }
00992       for (int i = 0; i < 20; i++) {
00993         rpc_data[i+40] = SNC[i];   // copy from vector to regular array.
00994       }
00995 
00996       vcl_vector<double> SDC;
00997       success = (*tres_itr)->get_values("SDC", SDC);
00998       if (!success) {
00999         vcl_cout << "SDC Property failed in vil_nitf2_image_subheader\n";
01000         return false;
01001       }
01002       for (int i = 0; i < 20; i++) {
01003         rpc_data[i+60] = SDC[i];   // copy from vector to regular array.
01004       }
01005     }
01006   }
01007 
01008   return true;
01009 }