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 #include <vcl_cstdlib.h>
00018 
00019 vil_nitf2_field_definitions* vil_nitf2_image_subheader::s_field_definitions_21 = 0;
00020 vil_nitf2_field_definitions* vil_nitf2_image_subheader::s_field_definitions_20 = 0;
00021 
00022 vil_nitf2_image_subheader::vil_nitf2_image_subheader(vil_nitf2_classification::file_version version)
00023   : m_field_sequence(version == vil_nitf2_classification::V_NITF_20 ?
00024                      *get_field_definitions_20() :
00025                      *get_field_definitions_21()),
00026     m_data_mask_table(0),
00027     m_version(version)
00028 {
00029   add_rpc_definitions();
00030   add_USE_definitions();
00031   add_ICHIPB_definitions();
00032   add_MPD26A_definitions();
00033   add_STDIDB_definitions();
00034   add_STDIDC_definitions();
00035 }
00036 
00037 vil_nitf2_image_subheader::~vil_nitf2_image_subheader()
00038 {
00039   if (m_data_mask_table) delete m_data_mask_table;//jlm
00040   if (vil_nitf2_tagged_record_definition::all_definitions().size()) {
00041     vil_nitf2_tagged_record_definition::undefine("RPC00A");
00042     vil_nitf2_tagged_record_definition::undefine("RPC00B");
00043   }
00044 }
00045 
00046 bool vil_nitf2_image_subheader::read(vil_stream* stream)
00047 {
00048   bool success = m_field_sequence.read(*stream);
00049 
00050   if (success)
00051   {
00052     // If this image has a data mask, we need to parse that too
00053     vcl_string compression_code;
00054     get_property("IC", compression_code);
00055     if (compression_code.find_first_of("M") != vcl_string::npos) {
00056       vcl_string imode;
00057       get_property("IMODE", imode);
00058       m_data_mask_table = new vil_nitf2_data_mask_table(
00059                                                         get_num_blocks_x(), get_num_blocks_y(), nplanes(), imode);
00060       if (!m_data_mask_table->parse(stream)) return false;
00061     }
00062   }
00063   return success;
00064 }
00065 
00066 const vil_nitf2_field_definitions* vil_nitf2_image_subheader::get_field_definitions_21()
00067 {
00068   if (!s_field_definitions_21) {
00069     s_field_definitions_21 = new vil_nitf2_field_definitions();
00070     add_shared_field_defs_1(s_field_definitions_21);
00071     vil_nitf2_classification::add_field_defs(s_field_definitions_21, vil_nitf2_classification::V_NITF_21, "I", "Image");
00072     add_shared_field_defs_2(s_field_definitions_21);
00073     add_geo_field_defs(s_field_definitions_21, vil_nitf2_classification::V_NITF_21);
00074     add_shared_field_defs_3(s_field_definitions_21);
00075   }
00076   return s_field_definitions_21;
00077 }
00078 
00079 const vil_nitf2_field_definitions* vil_nitf2_image_subheader::get_field_definitions_20()
00080 {
00081   if (!s_field_definitions_20) {
00082     s_field_definitions_20 = new vil_nitf2_field_definitions();
00083     add_shared_field_defs_1(s_field_definitions_20);
00084     vil_nitf2_classification::add_field_defs(s_field_definitions_20, vil_nitf2_classification::V_NITF_20, "I", "Image");
00085     add_shared_field_defs_2(s_field_definitions_20);
00086     add_geo_field_defs(s_field_definitions_20, vil_nitf2_classification::V_NITF_20);
00087     add_shared_field_defs_3(s_field_definitions_20);
00088   }
00089   return s_field_definitions_20;
00090 }
00091 
00092 void vil_nitf2_image_subheader::
00093 add_shared_field_defs_3(vil_nitf2_field_definitions* defs)
00094 {
00095   (*defs)
00096     .field("NICOM", "Number of Image Comments", NITF_INT(1), false, 0, 0)
00097 
00098     //TODO: does it make any sense for a vcl_vector to have blank entries????  For now, I'm saying no (false parameter)
00099     .repeat("NICOM", vil_nitf2_field_definitions()
00100 
00101             .field("ICOMn", "Image Comment n", NITF_STR_ECSA(80), false, 0, 0))
00102 
00103     .field("IC", "Image Compression",
00104            NITF_ENUM(2, vil_nitf2_enum_values()
00105                      .value("NC", "Not compressed")
00106                      .value("NM", "Uncompressed - contains block mask and/or pad pixel mask")
00107                      .value("C1", "Bi-level")
00108                      .value("C3", "JPEG")
00109                      .value("C4", "Vector Quantization")
00110                      .value("C5", "Lossless JPEG")
00111                      .value("C6", "Reserved - future correlated multicomponent compression")
00112                      .value("C7", "Reserved - future SAR compression")
00113                      .value("C8", "JPEG2000")
00114                      .value("I1", "Downsampled JPEG")
00115                      .value("M1", "Compressed - contains block mask and/or pad pixel mask")
00116                      .value("M3", "Compressed - contains block mask and/or pad pixel mask")
00117                      .value("M4", "Compressed - contains block mask and/or pad pixel mask")
00118                      .value("M5", "Compressed - contains block mask and/or pad pixel mask")
00119                      .value("M6", "Reserved - future correlated multicomponent compression")
00120                      .value("M7", "Reserved - future SAR compression")
00121                      .value("M8", "JPEG2000 - contains block mask and/or pad pixel mask")),
00122            false, 0, 0);
00123 
00124   vcl_vector<vcl_string> comp_ic_values;
00125   comp_ic_values.push_back("C1");
00126   comp_ic_values.push_back("C3");
00127   comp_ic_values.push_back("C4");
00128   comp_ic_values.push_back("C5");
00129   comp_ic_values.push_back("C8");
00130   comp_ic_values.push_back("M1");
00131   comp_ic_values.push_back("M3");
00132   comp_ic_values.push_back("M4");
00133   comp_ic_values.push_back("M5");
00134   comp_ic_values.push_back("M8");
00135   comp_ic_values.push_back("I1");
00136 
00137   // Using string because the valid enum values are different based on the content of IC
00138   (*defs)
00139     .field("COMRAT", "Compression Rate Code",         NITF_STR_BCSA(4),true, 0,
00140            new vil_nitf2_field_value_one_of<vcl_string>("IC", comp_ic_values))
00141 
00142     // The value of IREP determines which values are acceptable here
00143     // (e.g., if IREP=MONO, then this must equal 1)
00144     .field("NBANDS", "Number of Bands",               NITF_INT(1), false, 0, 0)
00145 
00146     // Acceptable range [00010-99999]... only used if NBANDS=0
00147     .field("XBANDS", "Number of multispectral bands", NITF_INT(5), true, 0,
00148            new vil_nitf2_field_value_one_of<int>("NBANDS",0))
00149 
00150     .repeat(new vil_nitf2_choose_field_value<int>(
00151                                                   "NBANDS", "XBANDS", new vil_nitf2_field_value_greater_than<int>("NBANDS", 0)),
00152             vil_nitf2_field_definitions()
00153 
00154             .field("IREPBAND", "nth Band Representation",             NITF_STR_BCSA(2), true, 0, 0)
00155             .field("ISUBCAT",  "nth Band Subcategory",                NITF_STR_BCSA(6), true, 0, 0)
00156             .field("IFC",      "nth Image Filter Condition",          NITF_STR_BCSA(1), false, 0, 0)
00157             .field("IMFLT",    "nth Band Standard Image Filter Code", NITF_STR_BCSA(3), true, 0, 0)
00158             .field("NLUTS",    "Number of LUTS for the nth Image Band",        NITF_INT(1, false),  false, 0, 0)
00159             .field("NELUT",    "Number of LUT Entries for the nth Image Band", NITF_INT(5, false),  false, 0,
00160                    new vil_nitf2_field_value_greater_than<int>("NLUTS", 0) /*condition*/ )
00161 
00162             .repeat(new vil_nitf2_field_value<int>("NLUTS"), vil_nitf2_field_definitions()
00163 
00164                     .field("LUTDnm", "nth Image Band, mth LUT",             NITF_BIN(1), false,
00165                            new vil_nitf2_field_value<int>("NELUT"), 0))
00166             )
00167 
00168     .field("ISYNC", "Image Sync Code", NITF_INT(1),  false, 0, 0)
00169     .field("IMODE", "Image Mode",
00170            NITF_ENUM(1, vil_nitf2_enum_values()
00171                      .value("B", "Band interleaved by block")
00172                      .value("P", "Band interleaved by pixel")
00173                      .value("R", "Band interleaved by row")
00174                      .value("S", "Band sequential")),
00175            false, 0, 0)
00176 
00177     .field("NBPR",  "Number of Blocks per Row",              NITF_INT(4), false, 0, 0)
00178     .field("NBPC",  "Number of Blocks per Column",           NITF_INT(4), false, 0, 0)
00179     .field("NPPBH", "Number of Pixels per Block Horizontal", NITF_INT(4), false, 0, 0) //[0000-8192]
00180     .field("NPPBV", "Number of Pixels per Block Vertical",   NITF_INT(4), false, 0, 0) //[0000-8192]
00181     .field("NBPP",  "Number of Bits per Pixel per Band",     NITF_INT(2), false, 0, 0) //[01-96]
00182     .field("IDLVL", "Image Display Level",                   NITF_INT(3), false, 0, 0)
00183     .field("IALVL", "Attachment Level",                      NITF_INT(3), false, 0, 0) //[000-998]
00184 
00185     // TODO: Enter these two values as ints with optional sign (once supported)
00186     // Actually, since they are both in one field, maybe we'd want to make it one
00187     // compound field (in the new tree format)
00188     .field("ILOC_ROW", "Image Location Row",            NITF_STR_BCSA(5), false, 0, 0)
00189     .field("ILOC_COL", "Image Location Column",         NITF_STR_BCSA(5), false, 0, 0)
00190 
00191     // TODO: THis should be a decimal field that supports non-negative power of two
00192     // fractions (eg '/2  ' means 1/2, '/16 'means 1/16
00193     .field("IMAG",  "Image Magnification",              NITF_STR_BCSA(4), false, 0, 0)
00194     .field("UDIDL", "User Defined Image Data Length",        NITF_INT(5), false, 0, 0) //[00000,00003-99999]
00195 
00196     .field("UDOFL", "User Defined Overflow",                 NITF_INT(3), false, 0,
00197            new vil_nitf2_field_value_greater_than<int>("UDIDL", 0))
00198 
00199     .field("UDID", "User Defined Image Data",                NITF_TRES(), false,
00200            new vil_nitf2_max_field_value_plus_offset_and_threshold("UDIDL", -3), 0)
00201 
00202     .field("IXSHDL", "Image Extended Subheader Data Length", NITF_INT(5), false, 0, 0)
00203 
00204     .field("IXSOFL", "Image Extended Subheader Overflow",    NITF_INT(3), false, 0,
00205            new vil_nitf2_field_value_greater_than<int>("IXSHDL", 0))
00206 
00207     .field("IXSHD", "Image Extended Subheader Data",         NITF_TRES(), false,
00208            new vil_nitf2_max_field_value_plus_offset_and_threshold("IXSHDL", -3), 0);
00209 }
00210 
00211 void vil_nitf2_image_subheader::add_geo_field_defs(vil_nitf2_field_definitions* defs,
00212                                                    const vil_nitf2_classification::file_version& version)
00213 {
00214   switch (version)
00215   {
00216     case vil_nitf2_classification::V_NITF_20:
00217     {
00218       (*defs)
00219         .field("ICORDS", "Image Coordinate Representation",
00220                NITF_ENUM(1, vil_nitf2_enum_values()
00221                          .value("U", "UTM")
00222                          .value("G", "Geodetic/Geographic")
00223                          .value("N", "None")
00224                          .value("C", "Geocentric")),
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                NITF_ENUM(1, vil_nitf2_enum_values()
00242                          .value("U", "UTM expressed in MGRS form")
00243                          .value("G", "Geographic")
00244                          .value("N", "UTM/UPS (Northern hemisphere)") // actually means None for Nitf 2.0
00245                          .value("S", "UTM/UPS (Southern hemisphere)") // NITF 2.1 only
00246                          .value("D", "Decimal degrees")),             // NITF 2.1 only
00247                true, 0, 0)
00248 
00249         .field("IGEOLO", "Image Geographic Location", NITF_STR_BCSA(60), false, 0,
00250                new vil_nitf2_field_specified("ICORDS"));
00251       break;
00252     }
00253     default:
00254       assert(!"unsupported case");
00255   } // end switch
00256 }
00257 
00258 void vil_nitf2_image_subheader::add_shared_field_defs_2(vil_nitf2_field_definitions* defs)
00259 {
00260   (*defs)
00261     .field("ENCRYP", "Encryption",
00262            NITF_ENUM(1, vil_nitf2_enum_values()
00263                      // Only one valid value, until the spec gets updated
00264                      .value("0", "Not Encrypted")),
00265            false, 0, 0)
00266     .field("ISORCE", "Image Source", NITF_STR_ECSA(42),  true, 0, 0)
00267     //TODO: only allow range [00000001-99999999]
00268     .field("NROWS", "Number of Significant Rows in Image", NITF_INT(8, false), false, 0, 0)
00269     //TODO: only allow range [00000001-99999999]
00270     .field("NCOLS", "Number of Significant Columns in Image", NITF_INT(8, false), false, 0, 0)
00271     .field("PVTYPE", "Pixel Value Type",
00272            NITF_ENUM(3, vil_nitf2_enum_values()
00273                      .value("INT", "Integer")
00274                      .value("B",   "Bi-level")
00275                      .value("SI",  "2's complement signed integer")
00276                      .value("R",   "Real")
00277                      .value("C",   "Complex")),
00278            false, 0, 0)
00279     .field("IREP", "Image Representation",
00280            NITF_ENUM(8, vil_nitf2_enum_values()
00281                      .value("MONO",     "Monochrome")
00282                      .value("RGB",      "Red, green, blue true color")
00283                      .value("RGB/LUT",  "Red, green, blue mapped Color")
00284                      .value("MULTI",    "Multiband imagery")
00285                      .value("NODISPLY", "Not intended for display")
00286                      .value("NVECTOR",  "Cartesian coordinates")
00287                      .value("POLAR",    "Polar coordinates")
00288                      .value("VPH",      "SAR video phase history")
00289                      .value("YCbCr601", "BT.601-5 color space")),
00290            false, 0, 0)
00291 #ifdef UNCLASS_ONLY
00292     .field("ICAT", "Image Category",
00293            NITF_ENUM(8, vil_nitf2_enum_values()
00294                      .value("VIS",    "Visible imagery")
00295                      .value("SL",     "Side-looking radar")
00296                      .value("TI",     "Thermal infrared")
00297                      .value("FL",     "Forward-looking radar")
00298                      .value("RD",     "Radar")
00299                      .value("EO",     "Electro-optical")
00300                      .value("OP",     "Optical")
00301                      .value("HR",     "High-resolution radar")
00302                      .value("HS",     "Hyperspectral")
00303                      .value("CP",     "Color frame photography")
00304                      .value("BP",     "Black/white frame photography")
00305                      .value("SARIQ",  "SAR radio hologram")
00306                      .value("SAR",    "Synthetic aperture radar")
00307                      .value("IR",     "Infrared")
00308                      .value("MS",     "Multispectral")
00309                      .value("FP",     "Fingerprints")
00310                      .value("MRI",    "Magnetic resonance imagery")
00311                      .value("XRAY",   "X-ray")
00312                      .value("CAT",    "CAT scan")
00313                      .value("VD",     "Video")
00314                      .value("BARO",   "Barometric pressure")
00315                      .value("CURRENT","Water current")
00316                      .value("DEPTH",  "Water depth")
00317                      .value("MAP",    "Raster map")
00318                      .value("PAT",    "Color patch")
00319                      .value("LEG",    "Legends")
00320                      .value("DTEM",   "Elevation models")
00321                      .value("MATR",   "Matrix data (other types)")
00322                      .value("LOCG",   "Location Grids")),
00323            false, 0, 0)
00324 #else
00325     .field("ICAT", "Image Category", NITF_STR_ECSA(8), false, 0, 0)
00326 #endif //UNCLASS_ONLY
00327 
00328     .field("ABPP", "Actual Bits Per Pixel per Band", NITF_INT(2), false, 0, 0) //[1-96]
00329     .field("PJUST", "Pixel Justification",
00330            NITF_ENUM(1, vil_nitf2_enum_values()
00331                      .value("L", "Left-justified")
00332                      .value("R", "Right-justified")),
00333            false, 0, 0);
00334 }
00335 
00336 void vil_nitf2_image_subheader::add_shared_field_defs_1(vil_nitf2_field_definitions* defs)
00337 {
00338   (*defs)
00339     .field("IM", "File Part Type",
00340            NITF_ENUM(2, vil_nitf2_enum_values()
00341                      .value("IM", "Image Header")))
00342     .field("IID1", "Image Identifier 1", NITF_STR_BCSA(10))
00343 
00344     // order of data/time depends on NITF2.1 or NITF2.0, so just read in as string for now
00345     //.field("IDATIM", "Image Date and Time", NITF_DAT(14)));
00346     .field("IDATIM", "Image Date and Time", NITF_STR_BCSA(14))
00347     .field("TGTID",  "Target Identifier",   NITF_STR_BCSA(17), true)
00348     .field("IID2",   "Image Identifier 2",  NITF_STR_ECSA(80), true);
00349 }
00350 /*
00351 bool vil_nitf2_image_subheader::
00352 get_date_time(int& year, int& month, int& day, int& hour, int& min)
00353 {
00354   vcl_cout  << "In vil_nitf2_image_subheader::get_date_time!\n";
00355   vcl_string date_time = "";
00356   bool success = this->get_property("IDATIM", date_time);
00357   if (!success) {
00358     vcl_cout << "IDATIM Property failed in vil_nitf2_image_subheader\n";
00359     return false;
00360   }
00361   vcl_cout  << "In vil_nitf2_image_subheader::get_date_time!\n";
00362   //d==day,h==hour,n==min,ss==sec,Z==zulu,m==month, y==year suffix
00363   // format is ddhhnnssZmmmyy
00364   vcl_string s_day, s_hour, s_min, s_month, s_year_suff;
00365   s_day       = date_time.substr(0,2);
00366   s_hour      = date_time.substr(2,2);
00367   s_min       = date_time.substr(4,2);
00368   s_month     = date_time.substr(9,3);
00369   s_year_suff = date_time.substr(12,2);
00370   vcl_string months[]={"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG",
00371                         "SEP", "OCT", "NOV", "DEC"};
00372   bool found = false;
00373   vcl_cout << date_time << "\n";
00374   vcl_cout << s_day << " " << s_hour << " " << s_min << " " << s_month << " " << s_year_suff << vcl_endl;
00375   for(int i = 0; (i<12)&&(!found); ++i)
00376     if(s_month==months[i]){
00377       found = true;
00378       month = i+1;
00379     }
00380   if(!found)
00381     return false;
00382   day  = vcl_atoi(s_day.c_str());
00383   hour = vcl_atoi(s_hour.c_str());
00384   min =  vcl_atoi(s_min.c_str());
00385   year = vcl_atoi(s_year_suff.c_str());
00386   year += 2000;//good until the next millenium
00387   return true;
00388 }
00389 */
00390 bool vil_nitf2_image_subheader::
00391 get_date_time(int& year, int& month, int& day, int& hour, int& min)
00392 {
00393   vcl_string date_time = "";
00394   bool success = this->get_property("IDATIM", date_time);
00395   if (!success) {
00396     vcl_cout << "IDATIM Property failed in vil_nitf2_image_subheader\n";
00397     return false;
00398   }
00399   //d==day,h==hour,n==min,ss==sec,Z==zulu,m==month, y==year
00400   // format is ddhhnnssZmmmyy OR yyyymmddhhnnss (the NITF 2.1 Commercial format)
00401   vcl_string s_day, s_hour, s_min, s_month, s_year;
00402   // try ddhhnnssZmmmyy first
00403   vcl_string s_zulu = date_time.substr(8,1);
00404   if (s_zulu=="Z") {
00405     s_day   = date_time.substr(0,2);
00406     s_hour  = date_time.substr(2,2);
00407     s_min   = date_time.substr(4,2);
00408     s_month = date_time.substr(9,3);
00409     s_year  = date_time.substr(12,2);
00410     vcl_string months[]={"JAN", "FEB", "MAR", "APR",
00411                          "MAY", "JUN", "JUL", "AUG",
00412                          "SEP", "OCT", "NOV", "DEC"};
00413     bool found = false;
00414     for(int i = 0; (i<12)&&(!found); ++i) {
00415       if(s_month==months[i]){
00416         found = true;
00417         month = i+1;
00418       }
00419     }
00420     if(!found) {
00421       return false;
00422     }
00423   } else {  // try yyyymmddhhnnss
00424     s_year  = date_time.substr(0,4);
00425     s_month = date_time.substr(4,2);
00426     s_day   = date_time.substr(6,2);
00427     s_hour  = date_time.substr(8,2);
00428     s_min   = date_time.substr(10,2);
00429     month   = vcl_atoi(s_month.c_str());
00430   }
00431   day  = vcl_atoi(s_day.c_str());
00432   hour = vcl_atoi(s_hour.c_str());
00433   min =  vcl_atoi(s_min.c_str());
00434   year = vcl_atoi(s_year.c_str());
00435   if (year < 100)
00436     year += 2000;//good until the next millenium
00437   return true;
00438 }
00439 unsigned vil_nitf2_image_subheader::nplanes() const
00440 {
00441   //the number of image bands is stored in NBANDS unless NBANDS=0.
00442   //in that case, then it's stored under XBANDS.  That's why we have
00443   //to potentially try both
00444   int numBands;
00445   if (get_property("NBANDS", numBands))
00446   {
00447     if (numBands > 0 ||
00448         get_property("XBANDS", numBands))
00449     {
00450       return numBands;
00451     }
00452   }
00453   return 0;
00454 }
00455 
00456 unsigned int vil_nitf2_image_subheader::get_pixels_per_block_x() const
00457 {
00458   int pixels_per_block;
00459   if (get_property("NPPBH", pixels_per_block)) {
00460     return pixels_per_block;
00461   }
00462   return 0;
00463 }
00464 
00465 unsigned int vil_nitf2_image_subheader::get_pixels_per_block_y() const
00466 {
00467   int pixels_per_block;
00468   if (get_property("NPPBV", pixels_per_block)) {
00469     return pixels_per_block;
00470   }
00471   return 0;
00472 }
00473 
00474 unsigned int vil_nitf2_image_subheader::get_num_blocks_x() const
00475 {
00476   int blocks_per_row;
00477   if (get_property("NBPR", blocks_per_row)) {
00478     return blocks_per_row;
00479   }
00480   return 0;
00481 }
00482 
00483 unsigned int vil_nitf2_image_subheader::get_num_blocks_y() const
00484 {
00485   int blocks_per_col;
00486   if (get_property("NBPC", blocks_per_col)) {
00487     return blocks_per_col;
00488   }
00489   return 0;
00490 }
00491 unsigned int vil_nitf2_image_subheader::get_number_of_bits_per_pixel() const
00492 {
00493   int bits_per_pixel;
00494   if (get_property("ABPP", bits_per_pixel)) {
00495     return bits_per_pixel;
00496   }
00497   return 0;
00498 }
00499 vcl_string vil_nitf2_image_subheader::get_image_source() const
00500 {
00501   vcl_string source;
00502   if (get_property("ISORCE", source)) {
00503     return source;
00504   }
00505   return "";
00506 }
00507 vcl_string vil_nitf2_image_subheader::get_image_type() const
00508 {
00509   vcl_string id;
00510   if (get_property("IREP", id)) {
00511     return id;
00512   }
00513   return "";
00514 }
00515 
00516 bool vil_nitf2_image_subheader::get_lut_info(unsigned int band,
00517                                              int& n_luts, int& ne_lut,
00518                                              vcl_vector< vcl_vector< unsigned char > >& lut_d) const
00519 {
00520   if (!m_field_sequence.get_value("NLUTS", vil_nitf2_index_vector(band), n_luts) ||
00521       !m_field_sequence.get_value("NELUT", vil_nitf2_index_vector(band), ne_lut)) {
00522     return false;
00523   }
00524   lut_d.clear();
00525   lut_d.resize(n_luts);
00526   void* raw_lut_data;
00527   for (int lut_index = 0 ; lut_index < n_luts ; lut_index++) {
00528     lut_d[lut_index].resize(ne_lut);
00529     //get the lut_index'th lut for the given image band
00530     vil_nitf2_index_vector index( band, lut_index );
00531     if (m_field_sequence.get_value("LUTDnm", index, raw_lut_data )) {
00532       for ( int el_index = 0 ; el_index < ne_lut ; el_index++ ) {
00533         lut_d[lut_index][el_index] = static_cast<unsigned char*>(raw_lut_data)[el_index];
00534       }
00535     }
00536     else {
00537       break;
00538     }
00539   }
00540   return true;
00541 }
00542 
00543 vil_nitf2_field::field_tree* vil_nitf2_image_subheader::get_tree( int i ) const
00544 {
00545   vil_nitf2_field::field_tree* t = new vil_nitf2_field::field_tree;
00546   vcl_stringstream name_stream;
00547   name_stream << "Image Subheader";
00548   if ( i > 0 ) name_stream << " #" << i;
00549   t->columns.push_back( name_stream.str() );
00550   m_field_sequence.get_tree( t );
00551   return t;
00552 }
00553 
00554 // Add definitions for rational polynomial coefficients
00555 void vil_nitf2_image_subheader::add_rpc_definitions()
00556 {
00557   vil_nitf2_tagged_record_definition* tr =
00558     vil_nitf2_tagged_record_definition::find("RPC00B");
00559   if (!tr)
00560   {
00561     vil_nitf2_tagged_record_definition::define("RPC00B", "Rational Polynomial Coefficients Type B" )
00562 
00563     // These are the "offset and scale" fields that precede the polynomial coefficients
00564     .field("SUCCESS",     "Success parameter",  NITF_INT(1))                 // not used, but must read
00565     .field("ERR_BIAS",    "ERR_BIAS",           NITF_DBL(7, 2, false), true) // not used, but must read
00566     .field("ERR_RAND",    "ERR_RAND",           NITF_DBL(7, 2, false), true) // not used
00567     .field("LINE_OFF",    "Line Offset",        NITF_INT(6))
00568     .field("SAMP_OFF",    "Sample Offset",      NITF_INT(5))
00569     .field("LAT_OFF",     "Latitude Offset",    NITF_DBL(8, 4, true), false)
00570     .field("LON_OFF",     "Longitude offset",   NITF_DBL(9, 4, true), false)
00571     .field("HEIGHT_OFF",  "Height Offset",      NITF_INT(5, true))
00572     .field("LINE_SCALE",  "Line Scale",         NITF_INT(6))
00573     .field("SAMP_SCALE",  "Sample Scale",       NITF_INT(5))
00574     .field("LAT_SCALE",   "Latitude Scale",     NITF_DBL(8, 4, true), false)
00575     .field("LON_SCALE",   "Longitude Scale",    NITF_DBL(9, 4, true), false)
00576     .field("HEIGHT_SCALE", "Height Scale",      NITF_INT(5, true))
00577 
00578     // Now come the 4 sequential groups of (20 each) polynomial coefficients
00579     //   for line number, line density, sample number and sample density.
00580     // As these values are in <+/->n.nnnnnnE<+/->n (exponential) format,
00581     //   let's just read as strings now and convert into doubles later.
00582 
00583     .repeat(20, vil_nitf2_field_definitions()
00584             .field("LNC",        "Line Number Coefficient",    NITF_EXP(6,1))
00585            )
00586     .repeat(20, vil_nitf2_field_definitions()
00587             .field("LDC",        "Line Density Coefficient",   NITF_EXP(6,1))
00588            )
00589     .repeat(20, vil_nitf2_field_definitions()
00590             .field("SNC",        "Sample Number Coefficient",  NITF_EXP(6,1))
00591            )
00592     .repeat(20, vil_nitf2_field_definitions()
00593             .field("SDC",        "Sample Density Coefficient", NITF_EXP(6,1))
00594            )
00595     .end();  // of RPC TRE
00596   }
00597   tr =vil_nitf2_tagged_record_definition::find("RPC00A");
00598   if (!tr)
00599   {
00600     vil_nitf2_tagged_record_definition::define("RPC00A", "Rational Polynomial Coefficients Type A" )
00601 
00602     // These are the "offset and scale" fields that precede the polynomial coefficients
00603     .field("SUCCESS",     "Success parameter",  NITF_INT(1))                 // not used, but must read
00604     .field("ERR_BIAS",    "ERR_BIAS",           NITF_DBL(7, 2, false), true) // not used, but must read
00605     .field("ERR_RAND",    "ERR_RAND",           NITF_DBL(7, 2, false), true) // not used
00606     .field("LINE_OFF",    "Line Offset",        NITF_INT(6))
00607     .field("SAMP_OFF",    "Sample Offset",      NITF_INT(5))
00608     .field("LAT_OFF",     "Latitude Offset",    NITF_DBL(8, 4, true), false)
00609     .field("LON_OFF",     "Longitude offset",   NITF_DBL(9, 4, true), false)
00610     .field("HEIGHT_OFF",  "Height Offset",      NITF_INT(5, true))
00611     .field("LINE_SCALE",  "Line Scale",         NITF_INT(6))
00612     .field("SAMP_SCALE",  "Sample Scale",       NITF_INT(5))
00613     .field("LAT_SCALE",   "Latitude Scale",     NITF_DBL(8, 4, true), false)
00614     .field("LON_SCALE",   "Longitude Scale",    NITF_DBL(9, 4, true), false)
00615     .field("HEIGHT_SCALE", "Height Scale",      NITF_INT(5, true))
00616 
00617     // Now come the 4 sequential groups of (20 each) polynomial coefficients
00618     //   for line number, line density, sample number and sample density.
00619     // As these values are in <+/->n.nnnnnnE<+/->n (exponential) format,
00620     //   let's just read as strings now and convert into doubles later.
00621 
00622     .repeat(20, vil_nitf2_field_definitions()
00623             .field("LNC",        "Line Number Coefficient",    NITF_EXP(6,1))
00624            )
00625     .repeat(20, vil_nitf2_field_definitions()
00626             .field("LDC",        "Line Density Coefficient",   NITF_EXP(6,1))
00627            )
00628     .repeat(20, vil_nitf2_field_definitions()
00629             .field("SNC",        "Sample Number Coefficient",  NITF_EXP(6,1))
00630            )
00631     .repeat(20, vil_nitf2_field_definitions()
00632             .field("SDC",        "Sample Density Coefficient", NITF_EXP(6,1))
00633            )
00634     .end();  // of RPCA TRE
00635   }
00636 }
00637 
00638 void vil_nitf2_image_subheader::add_USE_definitions()
00639 {
00640   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("USE00A");
00641   if (!tr)
00642   {
00643     vil_nitf2_tagged_record_definition::define("USE00A", "EXPLOITATION USABILITY EXTENSION FORMAT" )
00644 
00645     .field("ANGLE_TO_NORTH","Angle to North",  NITF_INT(3))                 // not used, but must read
00646     .field("MEAN_GSD",      "Mean Ground Sample Distance",NITF_DBL(5, 1, false), false) // not used, but must read
00647     .field("Reserved1", "",NITF_STR(1), false)
00648     .field("DYNAMIC_RANGE", "Dynamic Range",NITF_LONG(5,  false), true) // not used
00649     .field("Reserved2", "",NITF_STR(7), false)
00650     .field("OBL_ANG",       "Obliquity Angle",        NITF_DBL(5,2,false), true)
00651     .field("ROLL_ANG",      "Roll Angle",     NITF_DBL(6,2,true), true)
00652     .field("Reserved3", "",NITF_STR(37), false)
00653     .field("N_REF",         "Number of Reference Lines.",      NITF_INT(2, false), false)
00654     .field("REV_NUM",       "Revolution Number",    NITF_LONG(5, false), false)
00655     .field("N_SEG",         "Number of Segments",   NITF_INT(3,  false), false)
00656     .field("MAX_LP_SEG",    "Maximum Lines Per Segment",         NITF_LONG(6,false), true)
00657     .field("Reserved4", "",NITF_STR(12), false)
00658     .field("SUN_EL",        "Sun Elevation",       NITF_DBL(5,1,true),false)
00659     .field("SUN_AZ",        "Sun Azimuth",     NITF_DBL(5,1,false),false)
00660 
00661 
00662     .end();  // of USE00A TRE
00663   }
00664 }
00665 
00666 // Collect the Sun angles
00667 bool vil_nitf2_image_subheader::
00668 get_sun_params( double& sun_el, double& sun_az)
00669 {
00670   // Now get the sub-header TRE parameters
00671   vil_nitf2_tagged_record_sequence isxhd_tres;
00672   vil_nitf2_tagged_record_sequence::iterator tres_itr;
00673   this->get_property("IXSHD", isxhd_tres);
00674 
00675 
00676   bool success=false;
00677   // Check through the TREs to find "RPC"
00678   for (tres_itr = isxhd_tres.begin(); tres_itr != isxhd_tres.end(); ++tres_itr)
00679   {
00680     vcl_string type = (*tres_itr)->name();
00681     if ( type == "USE00A")
00682     {
00683       success = (*tres_itr)->get_value("SUN_EL", sun_el);
00684       success = success && (*tres_itr)->get_value("SUN_AZ", sun_az);
00685       if (!success)
00686         vcl_cout<<"\n Error reading USE00A\n";
00687       else
00688         return success;
00689     }
00690     else if ( type == "MPD26A")
00691     {
00692       success = (*tres_itr)->get_value("SUN_EL", sun_el);
00693       success = success && (*tres_itr)->get_value("SUN_AZ", sun_az);
00694       if (!success)
00695         vcl_cout<<"\n Error reading MPD26A\n";
00696       else
00697         return success;
00698     }
00699   }
00700   return success;
00701 }
00702 
00703 void vil_nitf2_image_subheader::add_ICHIPB_definitions()
00704 {
00705   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("ICHIPB");
00706   if (!tr)
00707   {
00708     vil_nitf2_tagged_record_definition::define("ICHIPB", "ICHIPB SUPPORT DATA EXTENSION" )
00709 
00710     .field("XFRM_FLAG",    "Non-linear Transformation Flag",  NITF_INT(2),false)                 // not used, but must read
00711     .field("SCALE_FACTOR", "Scale Factor Relative to R0",NITF_DBL(10, 5, false), false) // not used, but must read
00712     .field("ANAMRPH_CORR", "Anamorphic Correction Indicator", NITF_INT(2),false)
00713     .field("SCANBLK_NUM",  "Scan Block Number",NITF_INT(2,  false), true) // not used
00714     //: intelligent data
00715     .field("OP_ROW_11", "Output product row number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00716     .field("OP_COL_11", "Output product column number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00717 
00718     .field("OP_ROW_12", "Output product row number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00719     .field("OP_COL_12", "Output product column number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00720 
00721     .field("OP_ROW_21", "Output product row number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00722     .field("OP_COL_21", "Output product column number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00723 
00724     .field("OP_ROW_22", "Output product row number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00725     .field("OP_COL_22", "Output product column number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00726 
00727     //: full image coordinate system
00728     .field("FI_ROW_11", "Output product row number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00729     .field("FI_COL_11", "Output product column number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00730 
00731     .field("FI_ROW_12", "Output product row number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00732     .field("FI_COL_12", "Output product column number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00733 
00734     .field("FI_ROW_21", "Output product row number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00735     .field("FI_COL_21", "Output product column number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00736 
00737     .field("FI_ROW_22", "Output product row number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00738     .field("FI_COL_22", "Output product column number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00739 
00740     .field("FI_ROW",      "Full Image Number of Rows",     NITF_LONG(8,false), false)
00741     .field("FI_COL",      "Full Image Number of COlumns",     NITF_LONG(8,false), false)
00742 
00743     .end();  // of ICHIPB TRE
00744   }
00745 }
00746 
00747 
00748 void vil_nitf2_image_subheader::add_STDIDC_definitions()
00749 {
00750   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("STDIDC");
00751   if (!tr)
00752   {
00753     vil_nitf2_tagged_record_definition::define("STDIDC", "STDIDC SUPPORT DATA EXTENSION" )
00754 
00755     .field("ACQUISITION_DATE",    "",  NITF_STR(14),false)                 // not used, but must read
00756     .field("MISSION", "",NITF_STR(14), false) // not used, but must read
00757     .field("PASS", "", NITF_STR(2),false)
00758     .field("OP_NUM",  "",NITF_INT(3,  false), false) // not used
00759     .field("START_SEGMENT", "",NITF_STR(2), false)
00760     .field("REPRO_NUM", "",NITF_INT(2,false), false)
00761     .field("REPLAY_REGEN", "",NITF_STR(3), false)
00762     .field("BLANK_FILL", "",NITF_STR(1), true)
00763     .field("START_COLUMN", "",NITF_INT(3,false), false)
00764     .field("START_ROW", "",NITF_INT(5,false), false)
00765     .field("END_SEGMENT", "",NITF_STR(2), false)
00766     .field("END_COLUMN", "",NITF_INT(3,false), false)
00767     .field("END_ROW", "",NITF_INT(5,false), false)
00768     .field("COUNTRY", "",NITF_STR(2), true)
00769     .field("WAC", "",NITF_INT(4,false), true)
00770     .field("LOCATION", "",NITF_STR(11), false)
00771     .field("RESERVED1", "",NITF_STR(5), true)
00772     .field("RESERVED2", "",NITF_STR(8), true)
00773 
00774     .end();  // of STDIDC TRE
00775   }
00776 }
00777 
00778 
00779 void vil_nitf2_image_subheader::add_STDIDB_definitions()
00780 {
00781   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("STDIDB");
00782   if (!tr)
00783   {
00784     vil_nitf2_tagged_record_definition::define("STDIDB", "STDIDB SUPPORT DATA EXTENSION" )
00785 
00786     .field("unk1",    "",  NITF_INT(2,false),false)                 // not used, but must read
00787     .field("unk2",    "",  NITF_STR(3),false)                 // not used, but must read
00788     .field("unk3",    "",  NITF_INT(2,false),false)                 // not used, but must read
00789     .field("unk4",    "",  NITF_INT(4,false),false)                 // not used, but must read
00790     .field("unk5",    "",  NITF_STR(2),false)                 // not used, but must read
00791     .field("unk6",    "",  NITF_INT(3,false),false)                 // not used, but must read
00792     .field("unk7",    "",  NITF_STR(2),false)                 // not used, but must read
00793     .field("unk8",    "",  NITF_INT(2,false),false)
00794     .field("unk9",    "",  NITF_STR(3),false)    // not used, but must read
00795     .field("unk10",    "",  NITF_STR(1),false)
00796     .field("START_COLUMN",    "",  NITF_STR(2),false)
00797     .field("START_ROW",    "",  NITF_INT(5,false),false)
00798     .field("unk11",    "",  NITF_STR(2),false)                 // not used, but must read
00799     .field("unk12",    "",  NITF_STR(2),false)                 // not used, but must read
00800     .field("unk13",    "",  NITF_INT(5,false),false)                 // not used, but must read
00801     .field("unk14",    "",  NITF_STR(2),false)                 // not used, but must read
00802     .field("unk15",    "",  NITF_INT(4,false),false)                 // not used, but must read
00803     .field("unk16",    "",  NITF_STR(4),false)                 // not used, but must read
00804     .field("unk17",    "",  NITF_STR(1),false)                 // not used, but must read
00805     .field("unk18",    "",  NITF_STR(5),false)
00806     .field("unk19",    "",  NITF_STR(1),false)    // not used, but must read
00807     .field("unk20",    "",  NITF_STR(5),false)
00808     .field("unk21",    "",  NITF_STR(7),false)
00809 
00810     .end();  // of STDIDC TRE
00811   }
00812 }
00813 
00814 
00815 void vil_nitf2_image_subheader::add_MPD26A_definitions()
00816 {
00817   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("MPD26A");
00818   if (!tr)
00819   {
00820     vil_nitf2_tagged_record_definition::define("MPD26A", "MPD26A SUPPORT DATA EXTENSION" )
00821 
00822     .field("UNK1",    "Unknown ",  NITF_DBL(11,1,false), false) // not used, but must read
00823     .field("UNK2",    "Unknown ",  NITF_STR(2), false) // not used, but must read
00824     .field("UNK3",    "Unknown ",  NITF_INT(7,false),false)                 // not used, but must read
00825     .field("UNK31",    "Unknown ", NITF_STR(10),false)                 // not used, but must read
00826     .field("UNK4",    "Unknown ",  NITF_DBL(6,1,false), true) // not used, but must read
00827     .field("UNK5",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00828     .field("UNK6",    "Unknown ",  NITF_STR(3), false) // not used, but must read
00829     .field("UNK7",    "Unknown ",  NITF_STR(1), false) // not used, but must read
00830     .field("UNK8",    "Unknown ",  NITF_STR(1), false) // not used, but must read
00831     .field("SUN_EL", "Sun Elevation angle", NITF_DBL(5,1,true),false)
00832     .field("SUN_AZ", "Sun Azimuthal angle", NITF_DBL(5,1,false),false)
00833     .field("UNK9",    "Unknown ",  NITF_INT(1,false), false) // not used, but must read
00834     .field("UNK10",    "Unknown ",  NITF_INT(1,false), false) // not used, but must read
00835     .field("UNK11",    "Unknown ",  NITF_INT(4,false), false) // not used, but must read
00836     .field("UNK12",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00837     .field("UNK13",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00838     .field("UNK14",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00839     .field("UNK15",    "Unknown ",  NITF_STR(10), false) // not used, but must read
00840     .field("UNK16",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00841     .field("UNK17",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00842     .field("UNK18",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00843     .field("UNK19",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00844     .field("UNK20",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00845     .field("UNK21",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00846     .field("UNK22",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00847     .field("UNK23",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00848     .field("UNK24",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00849     .field("UNK16",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00850     .field("UNK17",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00851     .field("UNK18",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00852     .field("UNK19",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00853     .field("UNK20",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00854     .field("UNK21",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00855     .field("UNK22",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00856     .field("UNK23",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00857     .field("UNK24",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00858     .field("UNK16",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00859     .field("UNK17",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00860     .field("UNK18",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00861     .field("UNK19",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00862     .field("UNK20",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00863     .field("UNK21",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00864     .field("UNK22",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00865     .field("UNK23",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00866     .field("UNK24",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00867 
00868     .end();  // of MPD26A TRE
00869   }
00870 }
00871 
00872 
00873 // obtain column and row offset from STDIDB /SDTDIDC
00874 bool vil_nitf2_image_subheader::
00875 get_correction_offset(double & u_off, double & v_off)
00876 {
00877   // Now get the sub-header TRE parameters
00878   vil_nitf2_tagged_record_sequence isxhd_tres;
00879   vil_nitf2_tagged_record_sequence::iterator tres_itr;
00880   this->get_property("IXSHD", isxhd_tres);
00881 
00882   double ulr=0;
00883   double ulc=0;
00884   // Check through the TREs to find "RPC"
00885   for (tres_itr = isxhd_tres.begin(); tres_itr != isxhd_tres.end(); ++tres_itr)
00886   {
00887     vcl_string type = (*tres_itr)->name();
00888     if ( type == "ICHIPB" )
00889     {
00890       double r_off=1.0; // dummy initialisation
00891       double c_off=1.0; // to silence a compiler warning
00892       if ( (*tres_itr)->get_value("FI_ROW_11", r_off) &&
00893            (*tres_itr)->get_value("FI_COL_11", c_off) )
00894       {
00895         ulr+=r_off;
00896         ulc+=c_off;
00897       }
00898       else
00899         return false;
00900     }
00901     else if ( type == "STDIDC" )
00902     {
00903       int r_off=1;
00904       int c_off=1;
00905       if ( (*tres_itr)->get_value("START_ROW",    r_off) &&
00906            (*tres_itr)->get_value("START_COLUMN", c_off) )
00907       {
00908         ulr+=(double)((r_off-1)*get_pixels_per_block_y());
00909         ulc+=(double)((c_off-1)*get_pixels_per_block_x());
00910       }
00911       else
00912         return false;
00913     }
00914     else if ( type == "STDIDB" )
00915     {
00916       int r_off=1;
00917       int c_off=1;
00918       vcl_string temp_off;
00919       if ( (*tres_itr)->get_value("START_ROW",    r_off) &&
00920            (*tres_itr)->get_value("START_COLUMN", temp_off) )
00921       {
00922         if ((int)temp_off[0]>=65)
00923           c_off=((int)temp_off[0]-55)*10;
00924         else
00925           c_off=((int)temp_off[0]-48)*10;
00926         c_off+=(int)temp_off[1]-48;
00927         ulr+=(r_off-1)*get_pixels_per_block_y();
00928         ulc+=(c_off-1)*get_pixels_per_block_x();
00929       }
00930       else
00931         return false;
00932     }
00933   }
00934   u_off=ulc;
00935   v_off=ulr;
00936   return true;
00937 }
00938 
00939 // Collect the RPC parameters for the current image. Image corners are reported
00940 // as a string of geographic coordinates,one for each image corner.
00941   bool vil_nitf2_image_subheader::
00942 get_rpc_params( vcl_string& rpc_type, vcl_string& image_id,
00943                 vcl_string& image_corner_geo_locations,
00944                 double* rpc_data )
00945 {
00946   // Get image ID and location from main header values
00947   vcl_string iid2 = "";
00948   bool success = this->get_property("IID2", iid2);
00949   if (!success) {
00950     vcl_cout << "IID2 Property failed in vil_nitf2_image_subheader\n";
00951     return false;
00952   }
00953   image_id = iid2.substr(0,39);// trim length to NN characters to match file ID
00954   vcl_string igeolo = "";
00955   success = this->get_property("IGEOLO", igeolo);
00956   if (!success) {
00957     vcl_cout << "IGEOLO Property failed in vil_nitf2_image_subheader\n";
00958     return false;
00959   }
00960   image_corner_geo_locations = igeolo;
00961 
00962   // Now get the sub-header TRE parameters
00963   vil_nitf2_tagged_record_sequence isxhd_tres;
00964   vil_nitf2_tagged_record_sequence::iterator tres_itr;
00965   this->get_property("IXSHD", isxhd_tres);
00966 
00967 
00968   // Check through the TREs to find "RPC"
00969   for (tres_itr = isxhd_tres.begin(); tres_itr != isxhd_tres.end(); ++tres_itr)
00970   {
00971     vcl_string type = (*tres_itr)->name();
00972 
00973     if ( type == "RPC00B" || type == "RPC00A") // looking for "RPC..."
00974     {
00975       // set type in return value
00976       rpc_type = type;
00977 
00978       // get offsets and scales, print a couple to make sure values are correct
00979       int line_off;
00980       success = (*tres_itr)->get_value("LINE_OFF", line_off);
00981       if (!success) {
00982         vcl_cout << "LINE_OFF Property failed in vil_nitf2_image_subheader\n";
00983         return false;
00984       }
00985       rpc_data[80] = line_off;
00986 
00987       int samp_off;
00988       success = (*tres_itr)->get_value("SAMP_OFF", samp_off);
00989       if (!success) {
00990         vcl_cout << "SAMP_OFF Property failed in vil_nitf2_image_subheader\n";
00991         return false;
00992       }
00993       rpc_data[81]  = samp_off;
00994 
00995       double lat_off;
00996       success = (*tres_itr)->get_value("LAT_OFF", lat_off);
00997       if (!success) {
00998         vcl_cout << "LAT_OFF Property failed in vil_nitf2_image_subheader\n";
00999         return false;
01000       }
01001       rpc_data[82] = lat_off;
01002 
01003       double lon_off;
01004       success = (*tres_itr)->get_value("LON_OFF", lon_off);
01005       if (!success) {
01006         vcl_cout << "LON_OFF Property failed in vil_nitf2_image_subheader\n";
01007         return false;
01008       }
01009       rpc_data[83] = lon_off;
01010 
01011       int height_off;
01012       success = (*tres_itr)->get_value("HEIGHT_OFF", height_off);
01013       if (!success) {
01014         vcl_cout << "HEIGHT_OFF Property failed in vil_nitf2_image_subheader\n";
01015         return false;
01016       }
01017       rpc_data[84] = height_off;
01018 
01019       int line_scale;
01020       success = (*tres_itr)->get_value("LINE_SCALE", line_scale);
01021       if (!success) {
01022         vcl_cout << "LINE_SCALE Property failed in vil_nitf2_image_subheader\n";
01023         return false;
01024       }
01025       rpc_data[85] = line_scale;
01026 
01027       int samp_scale;
01028       success = (*tres_itr)->get_value("SAMP_SCALE", samp_scale);
01029       if (!success) {
01030         vcl_cout << "SAMP_SCALE Property failed in vil_nitf2_image_subheader\n";
01031         return false;
01032       }
01033       rpc_data[86] = samp_scale;
01034 
01035       double lat_scale;
01036       success = (*tres_itr)->get_value("LAT_SCALE", lat_scale);
01037       if (!success) {
01038         vcl_cout << "LAT_SCALE Property failed in vil_nitf2_image_subheader\n";
01039         return false;
01040       }
01041       rpc_data[87] = lat_scale;
01042 
01043       double lon_scale;
01044       success = (*tres_itr)->get_value("LON_SCALE", lon_scale);
01045       if (!success) {
01046         vcl_cout << "LON_SCALE Property failed in vil_nitf2_image_subheader\n";
01047         return false;
01048       }
01049       rpc_data[88] = lon_scale;
01050 
01051       int height_scale;
01052       success = (*tres_itr)->get_value("HEIGHT_SCALE", height_scale);
01053       if (!success) {
01054         vcl_cout << "HEIGHT_SCALE Property failed in vil_nitf2_image_subheader\n";
01055         return false;
01056       }
01057       rpc_data[89] = height_scale;
01058 
01059       // finally get the 80 polynomial coefficients  ##################
01060       vcl_vector<double> LNC;
01061       success = (*tres_itr)->get_values("LNC", LNC);
01062       if (!success) {
01063         vcl_cout << "LNC Property failed in vil_nitf2_image_subheader\n";
01064         return false;
01065       }
01066       for (int i = 0; i < 20; i++) {
01067         rpc_data[i] = LNC[i];      // copy from vector to regular array.
01068       }
01069 
01070       vcl_vector<double> LDC;
01071       success = (*tres_itr)->get_values("LDC", LDC);
01072       if (!success) {
01073         vcl_cout << "LDC Property failed in vil_nitf2_image_subheader\n";
01074         return false;
01075       }
01076       for (int i = 0; i < 20; i++) {
01077         rpc_data[i+20] = LDC[i];   // copy from vector to regular array.
01078       }
01079 
01080       vcl_vector<double> SNC;
01081       success = (*tres_itr)->get_values("SNC", SNC);
01082       if (!success) {
01083         vcl_cout << "SNC Property failed in vil_nitf2_image_subheader\n";
01084         return false;
01085       }
01086       for (int i = 0; i < 20; i++) {
01087         rpc_data[i+40] = SNC[i];   // copy from vector to regular array.
01088       }
01089 
01090       vcl_vector<double> SDC;
01091       success = (*tres_itr)->get_values("SDC", SDC);
01092       if (!success) {
01093         vcl_cout << "SDC Property failed in vil_nitf2_image_subheader\n";
01094         return false;
01095       }
01096       for (int i = 0; i < 20; i++) {
01097         rpc_data[i+60] = SDC[i];   // copy from vector to regular array.
01098       }
01099     }
01100   }
01101 
01102   return true;
01103 }