Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

vil_nitf2_image_subheader.cxx

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

Generated on Thu Jan 10 14:40:00 2008 for core/vil by  doxygen 1.4.4