core/vil/file_formats/vil_nitf2_header.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 
00005 #include "vil_nitf2_header.h"
00006 
00007 #include "vil_nitf2_field_functor.h"
00008 #include "vil_nitf2_field_definition.h"
00009 #include "vil_nitf2_typed_field_formatter.h"
00010 
00011 #include <vcl_cassert.h>
00012 
00013 vil_nitf2_field_definitions* vil_nitf2_header::s_field_definitions_1 = 0;
00014 vil_nitf2_field_definitions* vil_nitf2_header::s_field_definitions_20 = 0;
00015 vil_nitf2_field_definitions* vil_nitf2_header::s_field_definitions_21 = 0;
00016 
00017 vil_nitf2_header::vil_nitf2_header()
00018   : m_field_sequence1(*get_field_definitions_1()),
00019     m_field_sequence2(0),
00020     m_field_sequence_classification(0)
00021 { }
00022 
00023 vil_nitf2_header::~vil_nitf2_header()
00024 {
00025   delete m_field_sequence2;
00026   delete m_field_sequence_classification;
00027 }
00028 
00029 vcl_string vil_nitf2_header::section_num_tag(section_type sec)
00030 {
00031   switch (sec) {
00032    case enum_file_header:                 assert(0); return "";
00033    case enum_image_segments:              return "NUMI";
00034    case enum_graphic_segments:            return "NUMS";
00035    case enum_label_segments:              return "NUML";
00036    case enum_text_segments:               return "NUMT";
00037    case enum_data_extension_segments:     return "NUMDES";
00038    case enum_reserved_extension_segments: return "NUMRES";
00039    default:                               return "";
00040   }
00041 }
00042 
00043 vcl_string vil_nitf2_header::section_len_header_tag(section_type sec)
00044 {
00045   switch (sec) {
00046    case enum_file_header:                 assert(0); return "";
00047    case enum_image_segments:              return "LISH";
00048    case enum_graphic_segments:            return "LSSH";
00049    case enum_label_segments:              return "LLSH";
00050    case enum_text_segments:               return "LTSH";
00051    case enum_data_extension_segments:     return "LDSH";
00052    case enum_reserved_extension_segments: return "LRESH";
00053    default:                               return "";
00054   }
00055 }
00056 
00057 vcl_string vil_nitf2_header::section_len_data_tag(section_type sec)
00058 {
00059   switch (sec) {
00060    case enum_file_header:                 assert(0); return "";
00061    case enum_image_segments:              return "LI";
00062    case enum_graphic_segments:            return "LS";
00063    case enum_label_segments:              return "LL";
00064    case enum_text_segments:               return "LT";
00065    case enum_data_extension_segments:     return "LD";
00066    case enum_reserved_extension_segments: return "LRE";
00067    default:                               return "";
00068   }
00069 }
00070 
00071 bool vil_nitf2_header::read(vil_stream* stream)
00072 {
00073   // Read the first part of the header
00074   bool success = m_field_sequence1.read(*stream) &&
00075     // If the version is not recognized, it may not even be a NITF file
00076     file_version() != vil_nitf2_classification::V_UNKNOWN;
00077 
00078   // Now read the classification stuff whose format depends on the NITF version
00079   if (success) {
00080     if (m_field_sequence_classification) delete m_field_sequence_classification;
00081     m_field_sequence_classification =
00082       new vil_nitf2_field_sequence(*vil_nitf2_classification::get_field_definitions(file_version(), "F", "File"));
00083     success &= m_field_sequence_classification->read(*stream);
00084   }
00085 
00086   // Now read in the rest of the header
00087   if (success) {
00088     if (m_field_sequence2) delete m_field_sequence2;
00089     m_field_sequence2 = new vil_nitf2_field_sequence(*get_field_definitions_2(file_version()));
00090     success &= m_field_sequence2->read(*stream);
00091   }
00092 
00093   return success;
00094 }
00095 
00096 vil_nitf2_field_definitions* vil_nitf2_header::get_field_definitions_2(
00097   vil_nitf2_classification::file_version version)
00098 {
00099   // Check if previously computed
00100   vil_nitf2_field_definitions* field_defs = (version == vil_nitf2_classification::V_NITF_20) ?
00101                                        s_field_definitions_20 :
00102                                        s_field_definitions_21;
00103   if (field_defs) return field_defs;
00104 
00105   // Compute field definitions
00106   field_defs = new vil_nitf2_field_definitions();
00107 
00108   (*field_defs)
00109     .field("FSCOP",  "File Copy Number",      NITF_INT(5), true /*in NITF2.0*/, 0, 0)
00110     .field("FSCPYS", "File Number of Copies", NITF_INT(5), true /*in NITF2.0*/, 0, 0)
00111     .field("ENCRYP", "Encryption",            NITF_INT(1), false, 0, 0);
00112 
00113   if (version == vil_nitf2_classification::V_NITF_20) {
00114     (*field_defs)
00115       .field("ONAME", "Originator's Name",    NITF_STR_ECSA(27), true, 0, 0);
00116   } else {
00117     // TODO: These next three values should actually be read in as a vcl_vector of 3 (8bit) unsigned binary integers
00118     (*field_defs)
00119       .field("FBKGC", "File Background Color 1", NITF_BIN(3),       true, 0, 0)
00120       .field("ONAME", "Originator's Name",       NITF_STR_ECSA(24), true, 0, 0);
00121   }
00122 
00123   (*field_defs)
00124     .field("OPHONE", "Originator's Phone Number", NITF_STR_ECSA(18), true,  0, 0)
00125     .field("FL",     "File Length",               NITF_LONG(12),     false, 0, 0)
00126     .field("HL",     "NITF File Header Length",   NITF_INT(6),       false, 0, 0)
00127 
00128     .field("NUMI",   "Number of Image Segments",  NITF_INT(3),   false, 0, 0)
00129     .repeat("NUMI",   vil_nitf2_field_definitions()
00130 
00131             .field("LISH", "Lengh of Image Subheader",  NITF_INT(6),   false, 0, 0)
00132             .field("LI",   "Length of Image Segment",   NITF_LONG(10), false, 0, 0))
00133 
00134     .field("NUMS",   "Number of Graphic Segments", NITF_INT(3), false, 0, 0)
00135     .repeat("NUMS",   vil_nitf2_field_definitions()
00136 
00137             .field("LSSH", "Length of Graphic Subheader", NITF_INT(4), false, 0, 0)
00138             .field("LS",   "Length of Graphic Segment",   NITF_INT(6), false, 0, 0))
00139 
00140     .field("NUML",   "Number of Label Segments",   NITF_INT(3), false, 0, 0)
00141     .repeat("NUML",   vil_nitf2_field_definitions()
00142 
00143             .field("LLSH", "Length of Label Subheader",  NITF_INT(4), false, 0, 0)
00144             .field("LL",   "Length of Label Segment",    NITF_INT(3), false, 0, 0))
00145 
00146     .field("NUMT",   "Number of Text Segments",    NITF_INT(3), false, 0, 0)
00147     .repeat("NUMT",   vil_nitf2_field_definitions()
00148 
00149             .field("LTSH", "Length of Text Subheader",   NITF_INT(4), false, 0, 0)
00150             .field("LT",   "Length of Text Segment",     NITF_INT(5), false, 0, 0))
00151 
00152     .field("NUMDES", "Number of Data Extension Segments", NITF_INT(3), false, 0, 0)
00153     .repeat("NUMDES", vil_nitf2_field_definitions()
00154 
00155             .field("LDSH", "Length of Data Extension Subheader", NITF_INT(4), false, 0, 0)
00156             .field("LD",   "Length of Data Extension Segment",   NITF_INT(9), false, 0, 0))
00157 
00158     .field("NUMRES", "Number of Reserved Extension Segments", NITF_INT(3), false, 0, 0)
00159     .repeat("NUMRES", vil_nitf2_field_definitions()
00160 
00161             .field("LRESH", "Length of Reserved Extension Subheader", NITF_INT(4), false, 0, 0)
00162             .field("LRE",   "Length of Reserved Extension Segment",   NITF_INT(7), false, 0, 0))
00163 
00164     .field("UDHDL",  "User Defined Header Data Length", NITF_INT(5), false, 0, 0) // range [00000,00003-99999]
00165 
00166     .field("UDHOFL", "User Defined Header Overflow",    NITF_INT(3), false, 0,
00167            new vil_nitf2_field_value_greater_than<int>("UDHDL", 0))
00168 
00169     .field("UDHD", "User Defined Header Data",          NITF_TRES(), false,
00170            new vil_nitf2_max_field_value_plus_offset_and_threshold("UDHDL", -3), 0)
00171 
00172     .field("XHDL",    "Extended Header Data Length",    NITF_INT(5), false, 0, 0)
00173 
00174     .field("XHDLOFL", "Extended Header Data Overflow",  NITF_INT(3), false, 0,
00175            new vil_nitf2_field_value_greater_than<int>("XHDL", 0))
00176 
00177     .field("XHD", "Extended Header Data",               NITF_TRES(), false,
00178            new vil_nitf2_max_field_value_plus_offset_and_threshold("XHDL", -3), 0);
00179 
00180   // Save them for future use
00181   if (version == vil_nitf2_classification::V_NITF_20) {
00182     s_field_definitions_20 = field_defs;
00183   } else {
00184     s_field_definitions_21 = field_defs;
00185   }
00186   return field_defs;
00187 }
00188 
00189 vil_nitf2_field_definitions* vil_nitf2_header::get_field_definitions_1()
00190 {
00191   if (!s_field_definitions_1) {
00192     s_field_definitions_1 = new vil_nitf2_field_definitions();
00193     vil_nitf2_field_definitions& field_defs = *s_field_definitions_1;
00194     field_defs
00195       .field("FHDR", "File Profile Name",
00196              NITF_ENUM(4, vil_nitf2_enum_values()
00197                .value("NITF", "NITF File")
00198                .value("NSIF", "NSIF File")),
00199               false, 0, 0)
00200     .field("FVER", "File Version",           NITF_STR_BCSA(5),  false, 0, 0)
00201     .field("CLEVEL", "Complexity Level",     NITF_INT(2),       false, 0, 0)
00202     // NITF2.1 - BF01, NITF2.0: <blank>
00203     .field("STYPE", "Standard Type",
00204            NITF_ENUM(4, vil_nitf2_enum_values()
00205              .value("BF01", "ISO/IEC IS 12087-5")),
00206             true, 0, 0)
00207     .field("OSTAID", "Operating Station ID", NITF_STR_BCSA(10), false, 0, 0)
00208     // order of data/time depends on NITF2.1 or NITF2.0, so just read in as string for now
00209     //.field("FDT", "File date and time", NITF_DAT(14),  false, 0, 0));
00210     .field("FDT", "File Date and Time",      NITF_STR_BCSA(14), false, 0, 0)
00211     .field("FTITLE", "File Title",           NITF_STR_ECSA(80), true, 0, 0);
00212   }
00213   return s_field_definitions_1;
00214 }
00215 
00216 vil_nitf2_classification::file_version vil_nitf2_header::file_version() const
00217 {
00218   vcl_string file_profile;
00219   vcl_string file_version;
00220   if (get_property("FHDR", file_profile) && get_property("FVER", file_version)) {
00221     if (file_profile == "NSIF" && file_version == "01.00") return vil_nitf2_classification::V_NSIF_10;
00222     if (file_profile == "NITF" && file_version == "01.00") return vil_nitf2_classification::V_NITF_10;
00223     if (file_profile == "NITF" && file_version == "02.00") return vil_nitf2_classification::V_NITF_20;
00224     if (file_profile == "NITF" && file_version == "02.10") return vil_nitf2_classification::V_NITF_21;
00225   }
00226   return vil_nitf2_classification::V_UNKNOWN;
00227 }
00228 
00229 vil_nitf2_field::field_tree* vil_nitf2_header::get_tree() const
00230 {
00231   vil_nitf2_field::field_tree* t = new vil_nitf2_field::field_tree;
00232   t->columns.push_back( "File Header" );
00233   m_field_sequence1.get_tree( t );
00234   if ( m_field_sequence_classification ) m_field_sequence_classification->get_tree( t );
00235   if ( m_field_sequence2 ) m_field_sequence2->get_tree( t );
00236   return t;
00237 }