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 #if 0 // get_date_time() commented out
00352 bool vil_nitf2_image_subheader::
00353 get_date_time(int& year, int& month, int& day, int& hour, int& min)
00354 {
00355   vcl_cout  << "In vil_nitf2_image_subheader::get_date_time!\n";
00356   vcl_string date_time = "";
00357   bool success = this->get_property("IDATIM", date_time);
00358   if (!success) {
00359     vcl_cout << "IDATIM Property failed in vil_nitf2_image_subheader\n";
00360     return false;
00361   }
00362   vcl_cout  << "In vil_nitf2_image_subheader::get_date_time!\n";
00363   //d==day,h==hour,n==min,ss==sec,Z==zulu,m==month, y==year suffix
00364   // format is ddhhnnssZmmmyy
00365   vcl_string s_day, s_hour, s_min, s_month, s_year_suff;
00366   s_day       = date_time.substr(0,2);
00367   s_hour      = date_time.substr(2,2);
00368   s_min       = date_time.substr(4,2);
00369   s_month     = date_time.substr(9,3);
00370   s_year_suff = date_time.substr(12,2);
00371   vcl_string months[]={"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG",
00372                         "SEP", "OCT", "NOV", "DEC"};
00373   bool found = false;
00374   vcl_cout << date_time << '\n'
00375            << s_day << ' ' << s_hour << ' ' << s_min
00376            << ' ' << s_month << ' ' << s_year_suff << vcl_endl;
00377   for (int i = 0; (i<12)&&(!found); ++i)
00378     if (s_month==months[i]){
00379       found = true;
00380       month = i+1;
00381     }
00382   if (!found)
00383     return false;
00384   day  = vcl_atoi(s_day.c_str());
00385   hour = vcl_atoi(s_hour.c_str());
00386   min =  vcl_atoi(s_min.c_str());
00387   year = vcl_atoi(s_year_suff.c_str());
00388   year += 2000;//good until the next millenium
00389   return true;
00390 }
00391 #endif // 0
00392 
00393 bool vil_nitf2_image_subheader::
00394 get_date_time(int& year, int& month, int& day, int& hour, int& min)
00395 {
00396   vcl_string date_time = "";
00397   bool success = this->get_property("IDATIM", date_time);
00398   if (!success) {
00399     vcl_cout << "IDATIM Property failed in vil_nitf2_image_subheader\n";
00400     return false;
00401   }
00402   //d==day,h==hour,n==min,ss==sec,Z==zulu,m==month, y==year
00403   // format is ddhhnnssZmmmyy OR yyyymmddhhnnss (the NITF 2.1 Commercial format)
00404   vcl_string s_day, s_hour, s_min, s_month, s_year;
00405   // try ddhhnnssZmmmyy first
00406   vcl_string s_zulu = date_time.substr(8,1);
00407   if (s_zulu=="Z") {
00408     s_day   = date_time.substr(0,2);
00409     s_hour  = date_time.substr(2,2);
00410     s_min   = date_time.substr(4,2);
00411     s_month = date_time.substr(9,3);
00412     s_year  = date_time.substr(12,2);
00413     vcl_string months[]={"JAN", "FEB", "MAR", "APR",
00414                          "MAY", "JUN", "JUL", "AUG",
00415                          "SEP", "OCT", "NOV", "DEC"};
00416     bool found = false;
00417     for (int i = 0; (i<12)&&(!found); ++i) {
00418       if (s_month==months[i]){
00419         found = true;
00420         month = i+1;
00421       }
00422     }
00423     if (!found) {
00424       return false;
00425     }
00426   }
00427   else {  // try yyyymmddhhnnss
00428     s_year  = date_time.substr(0,4);
00429     s_month = date_time.substr(4,2);
00430     s_day   = date_time.substr(6,2);
00431     s_hour  = date_time.substr(8,2);
00432     s_min   = date_time.substr(10,2);
00433     month   = vcl_atoi(s_month.c_str());
00434   }
00435   day  = vcl_atoi(s_day.c_str());
00436   hour = vcl_atoi(s_hour.c_str());
00437   min =  vcl_atoi(s_min.c_str());
00438   year = vcl_atoi(s_year.c_str());
00439   if (year < 100)
00440     year += 2000;//good until the next millenium
00441   return true;
00442 }
00443 
00444 unsigned vil_nitf2_image_subheader::nplanes() const
00445 {
00446   //the number of image bands is stored in NBANDS unless NBANDS=0.
00447   //in that case, then it's stored under XBANDS.  That's why we have
00448   //to potentially try both
00449   int numBands;
00450   if (get_property("NBANDS", numBands))
00451   {
00452     if (numBands > 0 ||
00453         get_property("XBANDS", numBands))
00454     {
00455       return numBands;
00456     }
00457   }
00458   return 0;
00459 }
00460 
00461 unsigned int vil_nitf2_image_subheader::get_pixels_per_block_x() const
00462 {
00463   int pixels_per_block;
00464   if (get_property("NPPBH", pixels_per_block)) {
00465     return pixels_per_block;
00466   }
00467   return 0;
00468 }
00469 
00470 unsigned int vil_nitf2_image_subheader::get_pixels_per_block_y() const
00471 {
00472   int pixels_per_block;
00473   if (get_property("NPPBV", pixels_per_block)) {
00474     return pixels_per_block;
00475   }
00476   return 0;
00477 }
00478 
00479 unsigned int vil_nitf2_image_subheader::get_num_blocks_x() const
00480 {
00481   int blocks_per_row;
00482   if (get_property("NBPR", blocks_per_row)) {
00483     return blocks_per_row;
00484   }
00485   return 0;
00486 }
00487 
00488 unsigned int vil_nitf2_image_subheader::get_num_blocks_y() const
00489 {
00490   int blocks_per_col;
00491   if (get_property("NBPC", blocks_per_col)) {
00492     return blocks_per_col;
00493   }
00494   return 0;
00495 }
00496 
00497 unsigned int vil_nitf2_image_subheader::get_number_of_bits_per_pixel() const
00498 {
00499   int bits_per_pixel;
00500   if (get_property("ABPP", bits_per_pixel)) {
00501     return bits_per_pixel;
00502   }
00503   return 0;
00504 }
00505 
00506 vcl_string vil_nitf2_image_subheader::get_image_source() const
00507 {
00508   vcl_string source;
00509   if (get_property("ISORCE", source)) {
00510     return source;
00511   }
00512   return "";
00513 }
00514 
00515 vcl_string vil_nitf2_image_subheader::get_image_type() const
00516 {
00517   vcl_string id;
00518   if (get_property("IREP", id)) {
00519     return id;
00520   }
00521   return "";
00522 }
00523 
00524 bool vil_nitf2_image_subheader::get_lut_info(unsigned int band,
00525                                              int& n_luts, int& ne_lut,
00526                                              vcl_vector< vcl_vector< unsigned char > >& lut_d) const
00527 {
00528   if (!m_field_sequence.get_value("NLUTS", vil_nitf2_index_vector(band), n_luts) ||
00529       !m_field_sequence.get_value("NELUT", vil_nitf2_index_vector(band), ne_lut)) {
00530     return false;
00531   }
00532   lut_d.clear();
00533   lut_d.resize(n_luts);
00534   void* raw_lut_data;
00535   for (int lut_index = 0 ; lut_index < n_luts ; lut_index++) {
00536     lut_d[lut_index].resize(ne_lut);
00537     //get the lut_index'th lut for the given image band
00538     vil_nitf2_index_vector index( band, lut_index );
00539     if (m_field_sequence.get_value("LUTDnm", index, raw_lut_data )) {
00540       for ( int el_index = 0 ; el_index < ne_lut ; el_index++ ) {
00541         lut_d[lut_index][el_index] = static_cast<unsigned char*>(raw_lut_data)[el_index];
00542       }
00543     }
00544     else {
00545       break;
00546     }
00547   }
00548   return true;
00549 }
00550 
00551 vil_nitf2_field::field_tree* vil_nitf2_image_subheader::get_tree( int i ) const
00552 {
00553   vil_nitf2_field::field_tree* t = new vil_nitf2_field::field_tree;
00554   vcl_stringstream name_stream;
00555   name_stream << "Image Subheader";
00556   if ( i > 0 ) name_stream << " #" << i;
00557   t->columns.push_back( name_stream.str() );
00558   m_field_sequence.get_tree( t );
00559   return t;
00560 }
00561 
00562 // Add definitions for rational polynomial coefficients
00563 void vil_nitf2_image_subheader::add_rpc_definitions()
00564 {
00565   vil_nitf2_tagged_record_definition* tr =
00566     vil_nitf2_tagged_record_definition::find("RPC00B");
00567   if (!tr)
00568   {
00569     vil_nitf2_tagged_record_definition::define("RPC00B", "Rational Polynomial Coefficients Type B" )
00570 
00571     // These are the "offset and scale" fields that precede the polynomial coefficients
00572     .field("SUCCESS",     "Success parameter",  NITF_INT(1))                 // not used, but must read
00573     .field("ERR_BIAS",    "ERR_BIAS",           NITF_DBL(7, 2, false), true) // not used, but must read
00574     .field("ERR_RAND",    "ERR_RAND",           NITF_DBL(7, 2, false), true) // not used
00575     .field("LINE_OFF",    "Line Offset",        NITF_INT(6))
00576     .field("SAMP_OFF",    "Sample Offset",      NITF_INT(5))
00577     .field("LAT_OFF",     "Latitude Offset",    NITF_DBL(8, 4, true), false)
00578     .field("LON_OFF",     "Longitude offset",   NITF_DBL(9, 4, true), false)
00579     .field("HEIGHT_OFF",  "Height Offset",      NITF_INT(5, true))
00580     .field("LINE_SCALE",  "Line Scale",         NITF_INT(6))
00581     .field("SAMP_SCALE",  "Sample Scale",       NITF_INT(5))
00582     .field("LAT_SCALE",   "Latitude Scale",     NITF_DBL(8, 4, true), false)
00583     .field("LON_SCALE",   "Longitude Scale",    NITF_DBL(9, 4, true), false)
00584     .field("HEIGHT_SCALE", "Height Scale",      NITF_INT(5, true))
00585 
00586     // Now come the 4 sequential groups of (20 each) polynomial coefficients
00587     //   for line number, line density, sample number and sample density.
00588     // As these values are in <+/->n.nnnnnnE<+/->n (exponential) format,
00589     //   let's just read as strings now and convert into doubles later.
00590 
00591     .repeat(20, vil_nitf2_field_definitions()
00592             .field("LNC",        "Line Number Coefficient",    NITF_EXP(6,1))
00593            )
00594     .repeat(20, vil_nitf2_field_definitions()
00595             .field("LDC",        "Line Density Coefficient",   NITF_EXP(6,1))
00596            )
00597     .repeat(20, vil_nitf2_field_definitions()
00598             .field("SNC",        "Sample Number Coefficient",  NITF_EXP(6,1))
00599            )
00600     .repeat(20, vil_nitf2_field_definitions()
00601             .field("SDC",        "Sample Density Coefficient", NITF_EXP(6,1))
00602            )
00603     .end();  // of RPC TRE
00604   }
00605   tr =vil_nitf2_tagged_record_definition::find("RPC00A");
00606   if (!tr)
00607   {
00608     vil_nitf2_tagged_record_definition::define("RPC00A", "Rational Polynomial Coefficients Type A" )
00609 
00610     // These are the "offset and scale" fields that precede the polynomial coefficients
00611     .field("SUCCESS",     "Success parameter",  NITF_INT(1))                 // not used, but must read
00612     .field("ERR_BIAS",    "ERR_BIAS",           NITF_DBL(7, 2, false), true) // not used, but must read
00613     .field("ERR_RAND",    "ERR_RAND",           NITF_DBL(7, 2, false), true) // not used
00614     .field("LINE_OFF",    "Line Offset",        NITF_INT(6))
00615     .field("SAMP_OFF",    "Sample Offset",      NITF_INT(5))
00616     .field("LAT_OFF",     "Latitude Offset",    NITF_DBL(8, 4, true), false)
00617     .field("LON_OFF",     "Longitude offset",   NITF_DBL(9, 4, true), false)
00618     .field("HEIGHT_OFF",  "Height Offset",      NITF_INT(5, true))
00619     .field("LINE_SCALE",  "Line Scale",         NITF_INT(6))
00620     .field("SAMP_SCALE",  "Sample Scale",       NITF_INT(5))
00621     .field("LAT_SCALE",   "Latitude Scale",     NITF_DBL(8, 4, true), false)
00622     .field("LON_SCALE",   "Longitude Scale",    NITF_DBL(9, 4, true), false)
00623     .field("HEIGHT_SCALE", "Height Scale",      NITF_INT(5, true))
00624 
00625     // Now come the 4 sequential groups of (20 each) polynomial coefficients
00626     //   for line number, line density, sample number and sample density.
00627     // As these values are in <+/->n.nnnnnnE<+/->n (exponential) format,
00628     //   let's just read as strings now and convert into doubles later.
00629 
00630     .repeat(20, vil_nitf2_field_definitions()
00631             .field("LNC",        "Line Number Coefficient",    NITF_EXP(6,1))
00632            )
00633     .repeat(20, vil_nitf2_field_definitions()
00634             .field("LDC",        "Line Density Coefficient",   NITF_EXP(6,1))
00635            )
00636     .repeat(20, vil_nitf2_field_definitions()
00637             .field("SNC",        "Sample Number Coefficient",  NITF_EXP(6,1))
00638            )
00639     .repeat(20, vil_nitf2_field_definitions()
00640             .field("SDC",        "Sample Density Coefficient", NITF_EXP(6,1))
00641            )
00642     .end();  // of RPCA TRE
00643   }
00644 }
00645 
00646 void vil_nitf2_image_subheader::add_USE_definitions()
00647 {
00648   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("USE00A");
00649   if (!tr)
00650   {
00651     vil_nitf2_tagged_record_definition::define("USE00A", "EXPLOITATION USABILITY EXTENSION FORMAT" )
00652 
00653     .field("ANGLE_TO_NORTH","Angle to North",  NITF_INT(3))                 // not used, but must read
00654     .field("MEAN_GSD",      "Mean Ground Sample Distance",NITF_DBL(5, 1, false), false) // not used, but must read
00655     .field("Reserved1", "",NITF_STR(1), false)
00656     .field("DYNAMIC_RANGE", "Dynamic Range",NITF_LONG(5,  false), true) // not used
00657     .field("Reserved2", "",NITF_STR(7), false)
00658     .field("OBL_ANG",       "Obliquity Angle",        NITF_DBL(5,2,false), true)
00659     .field("ROLL_ANG",      "Roll Angle",     NITF_DBL(6,2,true), true)
00660     .field("Reserved3", "",NITF_STR(37), false)
00661     .field("N_REF",         "Number of Reference Lines.",      NITF_INT(2, false), false)
00662     .field("REV_NUM",       "Revolution Number",    NITF_LONG(5, false), false)
00663     .field("N_SEG",         "Number of Segments",   NITF_INT(3,  false), false)
00664     .field("MAX_LP_SEG",    "Maximum Lines Per Segment",         NITF_LONG(6,false), true)
00665     .field("Reserved4", "",NITF_STR(12), false)
00666     .field("SUN_EL",        "Sun Elevation",       NITF_DBL(5,1,true),false)
00667     .field("SUN_AZ",        "Sun Azimuth",     NITF_DBL(5,1,false),false)
00668 
00669 
00670     .end();  // of USE00A TRE
00671   }
00672 }
00673 
00674 // Collect the Sun angles
00675 bool vil_nitf2_image_subheader::
00676 get_sun_params( double& sun_el, double& sun_az)
00677 {
00678   // Now get the sub-header TRE parameters
00679   vil_nitf2_tagged_record_sequence isxhd_tres;
00680   vil_nitf2_tagged_record_sequence::iterator tres_itr;
00681   this->get_property("IXSHD", isxhd_tres);
00682 
00683 
00684   bool success=false;
00685   // Check through the TREs to find "RPC"
00686   for (tres_itr = isxhd_tres.begin(); tres_itr != isxhd_tres.end(); ++tres_itr)
00687   {
00688     vcl_string type = (*tres_itr)->name();
00689     if ( type == "USE00A")
00690     {
00691       success = (*tres_itr)->get_value("SUN_EL", sun_el);
00692       success = success && (*tres_itr)->get_value("SUN_AZ", sun_az);
00693       if (!success)
00694         vcl_cout<<"\n Error reading USE00A\n";
00695       else
00696         return success;
00697     }
00698     else if ( type == "MPD26A")
00699     {
00700       success = (*tres_itr)->get_value("SUN_EL", sun_el);
00701       success = success && (*tres_itr)->get_value("SUN_AZ", sun_az);
00702       if (!success)
00703         vcl_cout<<"\n Error reading MPD26A\n";
00704       else
00705         return success;
00706     }
00707   }
00708   return success;
00709 }
00710 
00711 void vil_nitf2_image_subheader::add_ICHIPB_definitions()
00712 {
00713   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("ICHIPB");
00714   if (!tr)
00715   {
00716     vil_nitf2_tagged_record_definition::define("ICHIPB", "ICHIPB SUPPORT DATA EXTENSION" )
00717 
00718     .field("XFRM_FLAG",    "Non-linear Transformation Flag",  NITF_INT(2),false)                 // not used, but must read
00719     .field("SCALE_FACTOR", "Scale Factor Relative to R0",NITF_DBL(10, 5, false), false) // not used, but must read
00720     .field("ANAMRPH_CORR", "Anamorphic Correction Indicator", NITF_INT(2),false)
00721     .field("SCANBLK_NUM",  "Scan Block Number",NITF_INT(2,  false), true) // not used
00722     //: intelligent data
00723     .field("OP_ROW_11", "Output product row number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00724     .field("OP_COL_11", "Output product column number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00725 
00726     .field("OP_ROW_12", "Output product row number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00727     .field("OP_COL_12", "Output product column number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00728 
00729     .field("OP_ROW_21", "Output product row number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00730     .field("OP_COL_21", "Output product column number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00731 
00732     .field("OP_ROW_22", "Output product row number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00733     .field("OP_COL_22", "Output product column number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00734 
00735     //: full image coordinate system
00736     .field("FI_ROW_11", "Output product row number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00737     .field("FI_COL_11", "Output product column number component of grid point index (1,1)",NITF_DBL(12,3,false), false)
00738 
00739     .field("FI_ROW_12", "Output product row number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00740     .field("FI_COL_12", "Output product column number component of grid point index (1,2)",NITF_DBL(12,3,false), false)
00741 
00742     .field("FI_ROW_21", "Output product row number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00743     .field("FI_COL_21", "Output product column number component of grid point index (2,1)",NITF_DBL(12,3,false), false)
00744 
00745     .field("FI_ROW_22", "Output product row number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00746     .field("FI_COL_22", "Output product column number component of grid point index (2,2)",NITF_DBL(12,3,false), false)
00747 
00748     .field("FI_ROW",      "Full Image Number of Rows",     NITF_LONG(8,false), false)
00749     .field("FI_COL",      "Full Image Number of COlumns",     NITF_LONG(8,false), false)
00750 
00751     .end();  // of ICHIPB TRE
00752   }
00753 }
00754 
00755 
00756 void vil_nitf2_image_subheader::add_STDIDC_definitions()
00757 {
00758   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("STDIDC");
00759   if (!tr)
00760   {
00761     vil_nitf2_tagged_record_definition::define("STDIDC", "STDIDC SUPPORT DATA EXTENSION" )
00762 
00763     .field("ACQUISITION_DATE",    "",  NITF_STR(14),false)                 // not used, but must read
00764     .field("MISSION", "",NITF_STR(14), false) // not used, but must read
00765     .field("PASS", "", NITF_STR(2),false)
00766     .field("OP_NUM",  "",NITF_INT(3,  false), false) // not used
00767     .field("START_SEGMENT", "",NITF_STR(2), false)
00768     .field("REPRO_NUM", "",NITF_INT(2,false), false)
00769     .field("REPLAY_REGEN", "",NITF_STR(3), false)
00770     .field("BLANK_FILL", "",NITF_STR(1), true)
00771     .field("START_COLUMN", "",NITF_INT(3,false), false)
00772     .field("START_ROW", "",NITF_INT(5,false), false)
00773     .field("END_SEGMENT", "",NITF_STR(2), false)
00774     .field("END_COLUMN", "",NITF_INT(3,false), false)
00775     .field("END_ROW", "",NITF_INT(5,false), false)
00776     .field("COUNTRY", "",NITF_STR(2), true)
00777     .field("WAC", "",NITF_INT(4,false), true)
00778     .field("LOCATION", "",NITF_STR(11), false)
00779     .field("RESERVED1", "",NITF_STR(5), true)
00780     .field("RESERVED2", "",NITF_STR(8), true)
00781 
00782     .end();  // of STDIDC TRE
00783   }
00784 }
00785 
00786 
00787 void vil_nitf2_image_subheader::add_STDIDB_definitions()
00788 {
00789   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("STDIDB");
00790   if (!tr)
00791   {
00792     vil_nitf2_tagged_record_definition::define("STDIDB", "STDIDB SUPPORT DATA EXTENSION" )
00793 
00794     .field("unk1",    "",  NITF_INT(2,false),false)                 // not used, but must read
00795     .field("unk2",    "",  NITF_STR(3),false)                 // not used, but must read
00796     .field("unk3",    "",  NITF_INT(2,false),false)                 // not used, but must read
00797     .field("unk4",    "",  NITF_INT(4,false),false)                 // not used, but must read
00798     .field("unk5",    "",  NITF_STR(2),false)                 // not used, but must read
00799     .field("unk6",    "",  NITF_INT(3,false),false)                 // not used, but must read
00800     .field("unk7",    "",  NITF_STR(2),false)                 // not used, but must read
00801     .field("unk8",    "",  NITF_INT(2,false),false)
00802     .field("unk9",    "",  NITF_STR(3),false)    // not used, but must read
00803     .field("unk10",    "",  NITF_STR(1),false)
00804     .field("START_COLUMN",    "",  NITF_STR(2),false)
00805     .field("START_ROW",    "",  NITF_INT(5,false),false)
00806     .field("unk11",    "",  NITF_STR(2),false)                 // not used, but must read
00807     .field("unk12",    "",  NITF_STR(2),false)                 // not used, but must read
00808     .field("unk13",    "",  NITF_INT(5,false),false)                 // not used, but must read
00809     .field("unk14",    "",  NITF_STR(2),false)                 // not used, but must read
00810     .field("unk15",    "",  NITF_INT(4,false),false)                 // not used, but must read
00811     .field("unk16",    "",  NITF_STR(4),false)                 // not used, but must read
00812     .field("unk17",    "",  NITF_STR(1),false)                 // not used, but must read
00813     .field("unk18",    "",  NITF_STR(5),false)
00814     .field("unk19",    "",  NITF_STR(1),false)    // not used, but must read
00815     .field("unk20",    "",  NITF_STR(5),false)
00816     .field("unk21",    "",  NITF_STR(7),false)
00817 
00818     .end();  // of STDIDC TRE
00819   }
00820 }
00821 
00822 
00823 void vil_nitf2_image_subheader::add_MPD26A_definitions()
00824 {
00825   vil_nitf2_tagged_record_definition* tr =vil_nitf2_tagged_record_definition::find("MPD26A");
00826   if (!tr)
00827   {
00828     vil_nitf2_tagged_record_definition::define("MPD26A", "MPD26A SUPPORT DATA EXTENSION" )
00829 
00830     .field("UNK1",    "Unknown ",  NITF_DBL(11,1,false), false) // not used, but must read
00831     .field("UNK2",    "Unknown ",  NITF_STR(2), false) // not used, but must read
00832     .field("UNK3",    "Unknown ",  NITF_INT(7,false),false)                 // not used, but must read
00833     .field("UNK31",    "Unknown ", NITF_STR(10),false)                 // not used, but must read
00834     .field("UNK4",    "Unknown ",  NITF_DBL(6,1,false), true) // not used, but must read
00835     .field("UNK5",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00836     .field("UNK6",    "Unknown ",  NITF_STR(3), false) // not used, but must read
00837     .field("UNK7",    "Unknown ",  NITF_STR(1), false) // not used, but must read
00838     .field("UNK8",    "Unknown ",  NITF_STR(1), false) // not used, but must read
00839     .field("SUN_EL", "Sun Elevation angle", NITF_DBL(5,1,true),false)
00840     .field("SUN_AZ", "Sun Azimuthal angle", NITF_DBL(5,1,false),false)
00841     .field("UNK9",    "Unknown ",  NITF_INT(1,false), false) // not used, but must read
00842     .field("UNK10",    "Unknown ",  NITF_INT(1,false), false) // not used, but must read
00843     .field("UNK11",    "Unknown ",  NITF_INT(4,false), false) // not used, but must read
00844     .field("UNK12",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00845     .field("UNK13",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00846     .field("UNK14",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00847     .field("UNK15",    "Unknown ",  NITF_STR(10), false) // not used, but must read
00848     .field("UNK16",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00849     .field("UNK17",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00850     .field("UNK18",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00851     .field("UNK19",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00852     .field("UNK20",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00853     .field("UNK21",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00854     .field("UNK22",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00855     .field("UNK23",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00856     .field("UNK24",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00857     .field("UNK16",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00858     .field("UNK17",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00859     .field("UNK18",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00860     .field("UNK19",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00861     .field("UNK20",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00862     .field("UNK21",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00863     .field("UNK22",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00864     .field("UNK23",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00865     .field("UNK24",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00866     .field("UNK16",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00867     .field("UNK17",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00868     .field("UNK18",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00869     .field("UNK19",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00870     .field("UNK20",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00871     .field("UNK21",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00872     .field("UNK22",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00873     .field("UNK23",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00874     .field("UNK24",    "Unknown ",  NITF_DBL(9,1,false), false) // not used, but must read
00875 
00876     .end();  // of MPD26A TRE
00877   }
00878 }
00879 
00880 
00881 // obtain column and row offset from STDIDB /SDTDIDC
00882 bool vil_nitf2_image_subheader::
00883 get_correction_offset(double & u_off, double & v_off)
00884 {
00885   // Now get the sub-header TRE parameters
00886   vil_nitf2_tagged_record_sequence isxhd_tres;
00887   vil_nitf2_tagged_record_sequence::iterator tres_itr;
00888   this->get_property("IXSHD", isxhd_tres);
00889 
00890   double ulr=0;
00891   double ulc=0;
00892   // Check through the TREs to find "RPC"
00893   for (tres_itr = isxhd_tres.begin(); tres_itr != isxhd_tres.end(); ++tres_itr)
00894   {
00895     vcl_string type = (*tres_itr)->name();
00896     if ( type == "ICHIPB" )
00897     {
00898       double r_off=1.0; // dummy initialisation
00899       double c_off=1.0; // to silence a compiler warning
00900       if ( (*tres_itr)->get_value("FI_ROW_11", r_off) &&
00901            (*tres_itr)->get_value("FI_COL_11", c_off) )
00902       {
00903         ulr+=r_off;
00904         ulc+=c_off;
00905       }
00906       else
00907         return false;
00908     }
00909     else if ( type == "STDIDC" )
00910     {
00911       int r_off=1;
00912       int c_off=1;
00913       if ( (*tres_itr)->get_value("START_ROW",    r_off) &&
00914            (*tres_itr)->get_value("START_COLUMN", c_off) )
00915       {
00916         ulr+=(double)((r_off-1)*get_pixels_per_block_y());
00917         ulc+=(double)((c_off-1)*get_pixels_per_block_x());
00918       }
00919       else
00920         return false;
00921     }
00922     else if ( type == "STDIDB" )
00923     {
00924       int r_off=1;
00925       int c_off=1;
00926       vcl_string temp_off;
00927       if ( (*tres_itr)->get_value("START_ROW",    r_off) &&
00928            (*tres_itr)->get_value("START_COLUMN", temp_off) )
00929       {
00930         if ((int)temp_off[0]>=65)
00931           c_off=((int)temp_off[0]-55)*10;
00932         else
00933           c_off=((int)temp_off[0]-48)*10;
00934         c_off+=(int)temp_off[1]-48;
00935         ulr+=(r_off-1)*get_pixels_per_block_y();
00936         ulc+=(c_off-1)*get_pixels_per_block_x();
00937       }
00938       else
00939         return false;
00940     }
00941   }
00942   u_off=ulc;
00943   v_off=ulr;
00944   return true;
00945 }
00946 
00947 // Collect the RPC parameters for the current image. Image corners are reported
00948 // as a string of geographic coordinates,one for each image corner.
00949   bool vil_nitf2_image_subheader::
00950 get_rpc_params( vcl_string& rpc_type, vcl_string& image_id,
00951                 vcl_string& image_corner_geo_locations,
00952                 double* rpc_data )
00953 {
00954   // Get image ID and location from main header values
00955   vcl_string iid2 = "";
00956   bool success = this->get_property("IID2", iid2);
00957   if (!success) {
00958     vcl_cout << "IID2 Property failed in vil_nitf2_image_subheader\n";
00959     return false;
00960   }
00961   image_id = iid2.substr(0,39);// trim length to NN characters to match file ID
00962   vcl_string igeolo = "";
00963   success = this->get_property("IGEOLO", igeolo);
00964   if (!success) {
00965     vcl_cout << "IGEOLO Property failed in vil_nitf2_image_subheader\n";
00966     return false;
00967   }
00968   image_corner_geo_locations = igeolo;
00969 
00970   // Now get the sub-header TRE parameters
00971   vil_nitf2_tagged_record_sequence isxhd_tres;
00972   vil_nitf2_tagged_record_sequence::iterator tres_itr;
00973   this->get_property("IXSHD", isxhd_tres);
00974 
00975 
00976   // Check through the TREs to find "RPC"
00977   for (tres_itr = isxhd_tres.begin(); tres_itr != isxhd_tres.end(); ++tres_itr)
00978   {
00979     vcl_string type = (*tres_itr)->name();
00980 
00981     if ( type == "RPC00B" || type == "RPC00A") // looking for "RPC..."
00982     {
00983       // set type in return value
00984       rpc_type = type;
00985 
00986       // get offsets and scales, print a couple to make sure values are correct
00987       int line_off;
00988       success = (*tres_itr)->get_value("LINE_OFF", line_off);
00989       if (!success) {
00990         vcl_cout << "LINE_OFF Property failed in vil_nitf2_image_subheader\n";
00991         return false;
00992       }
00993       rpc_data[80] = line_off;
00994 
00995       int samp_off;
00996       success = (*tres_itr)->get_value("SAMP_OFF", samp_off);
00997       if (!success) {
00998         vcl_cout << "SAMP_OFF Property failed in vil_nitf2_image_subheader\n";
00999         return false;
01000       }
01001       rpc_data[81]  = samp_off;
01002 
01003       double lat_off;
01004       success = (*tres_itr)->get_value("LAT_OFF", lat_off);
01005       if (!success) {
01006         vcl_cout << "LAT_OFF Property failed in vil_nitf2_image_subheader\n";
01007         return false;
01008       }
01009       rpc_data[82] = lat_off;
01010 
01011       double lon_off;
01012       success = (*tres_itr)->get_value("LON_OFF", lon_off);
01013       if (!success) {
01014         vcl_cout << "LON_OFF Property failed in vil_nitf2_image_subheader\n";
01015         return false;
01016       }
01017       rpc_data[83] = lon_off;
01018 
01019       int height_off;
01020       success = (*tres_itr)->get_value("HEIGHT_OFF", height_off);
01021       if (!success) {
01022         vcl_cout << "HEIGHT_OFF Property failed in vil_nitf2_image_subheader\n";
01023         return false;
01024       }
01025       rpc_data[84] = height_off;
01026 
01027       int line_scale;
01028       success = (*tres_itr)->get_value("LINE_SCALE", line_scale);
01029       if (!success) {
01030         vcl_cout << "LINE_SCALE Property failed in vil_nitf2_image_subheader\n";
01031         return false;
01032       }
01033       rpc_data[85] = line_scale;
01034 
01035       int samp_scale;
01036       success = (*tres_itr)->get_value("SAMP_SCALE", samp_scale);
01037       if (!success) {
01038         vcl_cout << "SAMP_SCALE Property failed in vil_nitf2_image_subheader\n";
01039         return false;
01040       }
01041       rpc_data[86] = samp_scale;
01042 
01043       double lat_scale;
01044       success = (*tres_itr)->get_value("LAT_SCALE", lat_scale);
01045       if (!success) {
01046         vcl_cout << "LAT_SCALE Property failed in vil_nitf2_image_subheader\n";
01047         return false;
01048       }
01049       rpc_data[87] = lat_scale;
01050 
01051       double lon_scale;
01052       success = (*tres_itr)->get_value("LON_SCALE", lon_scale);
01053       if (!success) {
01054         vcl_cout << "LON_SCALE Property failed in vil_nitf2_image_subheader\n";
01055         return false;
01056       }
01057       rpc_data[88] = lon_scale;
01058 
01059       int height_scale;
01060       success = (*tres_itr)->get_value("HEIGHT_SCALE", height_scale);
01061       if (!success) {
01062         vcl_cout << "HEIGHT_SCALE Property failed in vil_nitf2_image_subheader\n";
01063         return false;
01064       }
01065       rpc_data[89] = height_scale;
01066 
01067       // finally get the 80 polynomial coefficients  ##################
01068       vcl_vector<double> LNC;
01069       success = (*tres_itr)->get_values("LNC", LNC);
01070       if (!success) {
01071         vcl_cout << "LNC Property failed in vil_nitf2_image_subheader\n";
01072         return false;
01073       }
01074       for (int i = 0; i < 20; i++) {
01075         rpc_data[i] = LNC[i];      // copy from vector to regular array.
01076       }
01077 
01078       vcl_vector<double> LDC;
01079       success = (*tres_itr)->get_values("LDC", LDC);
01080       if (!success) {
01081         vcl_cout << "LDC Property failed in vil_nitf2_image_subheader\n";
01082         return false;
01083       }
01084       for (int i = 0; i < 20; i++) {
01085         rpc_data[i+20] = LDC[i];   // copy from vector to regular array.
01086       }
01087 
01088       vcl_vector<double> SNC;
01089       success = (*tres_itr)->get_values("SNC", SNC);
01090       if (!success) {
01091         vcl_cout << "SNC Property failed in vil_nitf2_image_subheader\n";
01092         return false;
01093       }
01094       for (int i = 0; i < 20; i++) {
01095         rpc_data[i+40] = SNC[i];   // copy from vector to regular array.
01096       }
01097 
01098       vcl_vector<double> SDC;
01099       success = (*tres_itr)->get_values("SDC", SDC);
01100       if (!success) {
01101         vcl_cout << "SDC Property failed in vil_nitf2_image_subheader\n";
01102         return false;
01103       }
01104       for (int i = 0; i < 20; i++) {
01105         rpc_data[i+60] = SDC[i];   // copy from vector to regular array.
01106       }
01107     }
01108   }
01109 
01110   return true;
01111 }