core/vil/file_formats/vil_nitf2_image.h
Go to the documentation of this file.
00001 //:
00002 // \file
00003 // vil_nitf2: Written by Rob Radtke (rob@) and Harry Voorhees (hlv@) of
00004 // Stellar Science Ltd. Co. (stellarscience.com) for
00005 // Air Force Research Laboratory, 2005.
00006 
00007 #ifndef VIL_NITF2_IMAGE_H
00008 #define VIL_NITF2_IMAGE_H
00009 
00010 #include <vil/vil_blocked_image_resource.h>
00011 
00012 #include <vcl_vector.h>
00013 #include <vcl_cassert.h>
00014 
00015 #include <vil/vil_stream.h>
00016 
00017 #include "vil_nitf2_image_subheader.h"
00018 #include "vil_nitf2_header.h"
00019 
00020 #include <vil/vil_file_format.h>
00021 
00022 class vil_nitf2_des;
00023 
00024 class vil_nitf2_file_format : public vil_file_format
00025 {
00026  public:
00027   virtual char const *tag() const;
00028   virtual vil_image_resource_sptr make_input_image(vil_stream *vs);
00029   virtual vil_image_resource_sptr make_output_image(vil_stream* vs,
00030                                                     unsigned nx,
00031                                                     unsigned ny,
00032                                                     unsigned nplanes,
00033                                                     enum vil_pixel_format);
00034 };
00035 
00036 //: Class for reading NITF 2.1 imagery files.
00037 // It works just like any other vil_image_resource class except that it does
00038 // support retrieving multiple images from the same file.
00039 // Call nimages() to find out how many images are in this resource, and then call
00040 // set_current_image() to tell the class which image you want to work with presently.
00041 // All regular vil_image_resource functions will operate on the current image.
00042 //
00043 // You can access image header information through get_image_headers() and file
00044 // header information through get_header().
00045 //
00046 // Known reading limitations:
00047 //  - The only supported compression schemes are uncompressed (all 4 different
00048 //    types of data layouts: band sequential, band interleaved, band interleaved
00049 //    by row, and band interleaved by pixel) and JPEG 2000 compression (via plugin).
00050 //  Other forms of compression do not work (eg. JPEG (regular, non-j2k)
00051 //  - Writing is unsupported at this time
00052 //  - graphic segments are not read in
00053 //  - text segments are not read in
00054 //  - The class was designed to handle images with PVTYPE=C (complex), but images of
00055 //    this type are completely untested.
00056 //
00057 // Things that do work:
00058 //  - Reading uncompressed and image data (ints, shorts, 8 bit int, floats etc)
00059 //  - parsing and validating file headers, and image headers
00060 //  - enum_data masks (and pad pixels) are supported through vil_nitf2_data_mask_table
00061 //  - PJUST = L
00062 //  - Images with LUTS will read in correctly, but you will need to apply the LUT
00063 //    yourself.  You can access the lut information for p-th band of the current image by calling
00064 //    current_image_header()->get_lut_info(p, out_n_luts, out_ne_lut, out_lut_data)
00065 //  - The class does not have built-in support for JPEG2000 compressed NITF files
00066 //    Using cmake though, you can configure VXL to link against Er Mapper's freely
00067 //    available ECW JPEG2000 SDK (http://ermapper.com/downloads/sdks.aspx#16).  If you
00068 //    do that, then this class will automatically be able to read NITF files that are
00069 //    JPEG 2000 compressed.
00070 //
00071 class vil_nitf2_image : public vil_blocked_image_resource
00072 {
00073  public:
00074   //: Instantiate an image resource, but doesn't read anything.
00075   // You'll want to call parse_headers() before you do anything with me
00076   // (eg. before you ask for any image data).
00077   // If that returns false, then I am invalid and useless to you in every way.
00078   vil_nitf2_image( vil_stream* is );
00079   vil_nitf2_image( const vcl_string& filePath, const char* mode );
00080 
00081   virtual ~vil_nitf2_image();
00082 
00083   //:return the image info of the current image
00084   virtual unsigned nplanes() const;
00085   virtual unsigned ni() const;
00086   virtual unsigned nj() const;
00087   virtual enum vil_pixel_format pixel_format () const;
00088 
00089   //: Block size in columns
00090   virtual unsigned size_block_i() const;
00091 
00092   //: Block size in rows
00093   virtual unsigned size_block_j() const;
00094 
00095   //: Number of blocks in image width
00096   virtual unsigned n_block_i() const;
00097 
00098   //: Number of blocks in image height
00099   virtual unsigned n_block_j() const;
00100 
00101   //: returns "nitf vM.N"
00102   char const * file_format() const;
00103 
00104 
00105   // is the current image JPEG 2000 compressed
00106   bool is_jpeg_2000_compressed() const;
00107 
00108   // This function is sort of a hack.  It will return a decimated version
00109   // of the region specified by (i0,j0){i0+ni,j0+nj).  It will be decimated by i_factorXj_factor.
00110   // That is the image returned will have size (ni/i_factor, nj/j_factor).
00111   // The reason this function is a hack is because it only works for jpeg 2000 compressed
00112   // NITF files (that is, is_jpeg_2000_compressed() returns true).  You would normally want to use
00113   // vil_decimate_image_resource to obtain decimated images.  That will work for jpeg2000
00114   // compressed NITF files too, but that class/function doesn't take advantage of the JPEG 2000
00115   // spec's built in optimization for obtaining decimated versions of large images.  This function
00116   // does.  Well, more accurately, it can.  It depends on the implementation of the s_decode_jpeg_2000()
00117   // function you've provided.
00118   virtual vil_image_view_base_sptr get_copy_view_decimated_j2k( unsigned i0, unsigned ni,
00119                                                                 unsigned j0, unsigned nj,
00120                                                                 double i_factor, double j_factor ) const;
00121   virtual vil_image_view_base_sptr get_copy_view_decimated_j2k( double i_factor, double j_factor ) const
00122   { return get_copy_view_decimated_j2k( 0, ni(), 0, nj(), i_factor, j_factor ); }
00123 
00124   virtual vil_image_view_base_sptr get_copy_view(unsigned i0, unsigned ni,
00125                                                  unsigned j0, unsigned nj) const;
00126   virtual vil_image_view_base_sptr get_copy_view( ) const
00127   { return get_copy_view( 0, ni(), 0, nj() ); }
00128 
00129   virtual bool put_view (const vil_image_view_base& /* im */, unsigned /* i0 */, unsigned /* j0 */ )
00130   { return false; }
00131 
00132   virtual bool put_block(unsigned  /*block_index_i*/, unsigned  /*block_index_j*/,
00133                          const vil_image_view_base& /*blk*/ )
00134   { return false; }
00135 
00136   virtual vil_image_view_base_sptr get_block( unsigned int blockIndexX, unsigned int blockIndexY ) const;
00137 
00138   virtual bool get_property (char const *tag, void *property_value=0) const;
00139 
00140   //const vil_nitf2_header& getFileHeader() const;
00141   const vcl_vector< vil_nitf2_image_subheader* >& get_image_headers() const
00142   { return m_image_headers; }
00143   const vil_nitf2_header& get_header() const
00144   { return m_file_header; }
00145   const vcl_vector< vil_nitf2_des* >& get_des() const
00146   { return m_des; }
00147 
00148   //:
00149   //  Since the VIL API (eg. get_view()) for retrieving image data
00150   //  doesn't support files with multiple images, clients will
00151   //  need to call this function to tell get_view() which image to read in.
00152   //
00153   //  Overloaded from vil_image_resource.  The NITF 2.x file format does support
00154   //  multiple images per file and you can use this API to access each and every
00155   //  one of them.
00156   //
00157   //  Note: By default, the first image is always used.  If you don't call this
00158   //  function at all, then you will only see the first image in a given file.
00159   virtual void set_current_image( unsigned int index );
00160   virtual unsigned int current_image() const;
00161   virtual unsigned int nimages() const;
00162 
00163   bool parse_headers();
00164   vil_nitf2_classification::file_version file_version() const;
00165 
00166   //:
00167   // All instances of vil_nitf2_image will use s_decode_jpeg_2000() to decode
00168   // JPEG 2000 streams if you set the function.  If unset, then the library
00169   // will not be able to read JPEG 2000 compressed NITF files.
00170   //
00171   static vil_image_view_base_sptr ( *s_decode_jpeg_2000 )( vil_stream* vs,
00172                                                            unsigned i0, unsigned ni,
00173                                                            unsigned j0, unsigned nj,
00174                                                            double i_factor, double j_factor );
00175 
00176   // I allocate the return value, but you own it after I return it to you
00177   // so you need to delete it.
00178   virtual vil_nitf2_field::field_tree* get_tree() const;
00179 
00180  protected:
00181   virtual vil_image_view_base_sptr get_block_j2k( unsigned int blockIndexX, unsigned int blockIndexY ) const;
00182   virtual vil_image_view_base_sptr get_copy_view_uncompressed(unsigned i0, unsigned ni,
00183                                                               unsigned j0, unsigned nj) const;
00184 
00185 
00186   // Returns the offset (in bytes) from the beginning of the NITF file
00187   // to the beginning of the specified portion of the NITF stream.  For example:
00188   //
00189   // get_offset_to( enum_text_segments, Header, 0) will return the offset from the
00190   // beginning of the NITF stream to the beginning of the first text segment's
00191   // subheader.  You'd better make sure there is at least one text segment before
00192   // you call this.
00193   //
00194   // get_offset_to( enum_image_segments, enum_data, 3) will return the offset from the
00195   // beginning of the NITF stream to the beginning of the fourth image segment's
00196   // data section.  You'd better make sure there is at least four image segments before
00197   // you call this.
00198   vil_streampos get_offset_to( vil_nitf2_header::section_type sec, vil_nitf2_header::portion_type por, unsigned int index = 0 ) const;
00199   // Returns the offset (in bytes) from the beginning of section_type 'sec' and the beginning of the specified portion
00200   // (subheader or data).  If more then one of these segments exist, then use 'index' to select which one you want.
00201   vil_streampos size_to( vil_nitf2_header::section_type sec, vil_nitf2_header::portion_type por, int index ) const;
00202 
00203   // Returns the overall offset to the specified image/block/band combination.
00204   // If this block isn't present in the stream (ie. it's all blank), then
00205   // I'll return 0;
00206   vil_streampos get_offset_to_image_data_block_band( unsigned int imageIndex,
00207                                                      unsigned int blockIndexX,
00208                                                      unsigned int blockIndexY,
00209                                                      int bandIndex ) const;
00210 
00211   //main file header
00212   vil_nitf2_header m_file_header;
00213   //image header(s)
00214   vcl_vector< vil_nitf2_image_subheader* > m_image_headers;
00215   void clear_image_headers();
00216   const vil_nitf2_image_subheader* current_image_header() const;
00217   //DESs (if any)
00218   vcl_vector< vil_nitf2_des* > m_des;
00219   void clear_des();
00220 
00221   vil_stream* m_stream;
00222   unsigned int m_current_image_index;
00223 };
00224 
00225 //: This function does a lot of work for \sa byte_align_data().
00226 // It will strip one value of ni bits and return it as a value of type T
00227 // (with zero padding on the MSBs).
00228 // Both io and ni are lengths (in bits - not bytes).
00229 //
00230 // \param i0: Offset (in bits - not bytes) from in_val[0].  This will be the start
00231 //            of the bits extracted from in_val.
00232 // \param ni: number of bits (starting from i0) that will be extracted from in_val.
00233 template< class T >
00234 T get_bits( const T* in_val, unsigned int i0, unsigned int ni )
00235 {
00236   unsigned int sample_offset = i0 / ( sizeof(T)*8 );
00237   unsigned int bit_offset = i0 % ( sizeof(T)*8 );
00238 
00239   unsigned int strip_left = bit_offset;
00240   int strip_right = ( sizeof( T ) * 8 ) - ( bit_offset + ni );
00241   T temp = in_val[sample_offset];
00242   if ( strip_left > 0 ){
00243     //strip off the appropriate bits from the vcl_left (replacing them with zeros)
00244     temp = temp << strip_left;
00245     temp = temp >> strip_left;
00246   }
00247   if ( strip_right > 0 ){
00248     //strip off the appropriate bits from the vcl_right
00249     //the bit shift operator wasn't having the correct effect, so that'w
00250     //why the for loop
00251     for ( int i = 0 ; i < strip_right ; i++ ) temp /= 2;
00252     //temp = temp >> strip_right;
00253   }
00254   else if ( strip_right < 0 ){
00255     //we didn't have enough bits in the first element of the in_val array
00256     //need to get some from the next element
00257     for ( int i = 0 ; i < (-strip_right) ; i++ ) temp *= 2;
00258     temp += get_bits<T>( in_val+sample_offset+1, 0, -strip_right );
00259   }
00260   return temp;
00261 }
00262 
00263 //: This function will byte align the data in in_data and store the result in out_data.
00264 // For example, let's say that you had in_data is of type unsigned char
00265 // and contains the following data: 110010111001111010000110.
00266 // In other words:
00267 // in_data[0] = 203 (11001011)
00268 // in_data[1] = 158 (10011110)
00269 // in_data[2] = 134 (10000110)
00270 // Let's further say you called this function like this: byte_align_data( in_data, 8, 3, out_data ).
00271 // Then, when the function finished, out_data would look like this:
00272 // out_data[0] = 6 (00000110)
00273 // out_data[1] = 2 (00000010)
00274 // out_data[2] = 7 (00000111)
00275 // out_data[3] = 1 (00000001)
00276 // out_data[4] = 7 (00000111)
00277 // out_data[5] = 2 (00000010)
00278 // out_data[6] = 0 (00000000)
00279 // out_data[7] = 6 (00000110)
00280 //
00281 // Basically, what the function did was group the bitstream into groups of three and then store all of the
00282 // values into out_data.  It had to zero pad all the values (on the MSB side) to get them into out_data.  That's
00283 // why out_data is bigger.
00284 //
00285 // This function works with other unsigned types of data too.  For example, let's say in_data was of type unsigned int
00286 // and contained the following bits: 0100110010111000 0111101100000000 1111000011110000 (note that this bitstream is shown
00287 // in big endian notation, that will not be the case if you are on a little endian machine -- this is just for illustration)
00288 // in other words:
00289 // in_data[0] = 19640 (0100110010111000) [shown in big endian for illustrative purposes only]
00290 // in_data[1] = 31488 (0111101100000000) [shown in big endian for illustrative purposes only]
00291 // in_data[2] = 61680 (1111000011110000) [shown in big endian for illustrative purposes only]
00292 // Let's further say, you called this function like this byte_align_data( in_data, 4, 12, out_data ).
00293 // Then out_data would be aligned along two byte (sixteen bit) boundaries and would look like this:
00294 // out_data[0] = 1227 (0000010011001011) [shown in big endian for illustrative purposes only]
00295 // out_data[1] = 2171 (0000100001111011) [shown in big endian for illustrative purposes only]
00296 // out_data[2] = 15   (0000000000001111) [shown in big endian for illustrative purposes only]
00297 // out_data[3] = 240  (0000000011110000) [shown in big endian for illustrative purposes only]
00298 //
00299 // Because of the fact that this function uses bit shifting operators, and the behavior of the vcl_right
00300 // shift operator is implementation specific when applied to a negative number, you should probably
00301 // only use this function on unsigned data.
00302 //
00303 // \param in_data: The input data.  It must be at least (num_samples*in_bits_per_sample\8) bytes long.
00304 //                The values should have the endianness of your platform.
00305 // \param num_samples: The number of actual samples in in_data.
00306 // \param in_bits_per_sample: The bits per sample in in_data
00307 // \param out_data: I'll store the output data here.  It must be at least (num_samples*sizeof(T)) bytes long
00308 //                 The values will have the endianness of your platform.
00309 //
00310 // Note that inBitsPerSampe must not be >= sizeof(T).  If they were to be equal, then this function
00311 // would have nothing to do (in_data is already byte aligned).  If in_bits_per_sample were less than sizeof(T),
00312 // then each element of out_data would be too small to store the corresponding elements in in_data.
00313 //
00314 // Note that there is a specialization for the bool case which just casts it to an 8 bit quantity then calls
00315 // this same function.  This is because the logic in get_bits<> doesn't work for the bool case.
00316 template< class T >
00317 T* byte_align_data( T* in_data, unsigned int num_samples, unsigned int in_bits_per_sample, T* out_data )
00318 {
00319   assert( in_bits_per_sample < sizeof(T)*8 );
00320 
00321   //grab each value from the bitstream (in_data) that we need... one at a time
00322   unsigned int bit_offset = 0;
00323   for ( unsigned int o = 0 ; o < num_samples ; o++ ){
00324     out_data[o] = get_bits<T>( in_data, bit_offset, in_bits_per_sample );
00325     bit_offset+=in_bits_per_sample;
00326   }
00327 
00328   return out_data;
00329 }
00330 
00331 template<> bool* byte_align_data<bool>( bool* in_data, unsigned int num_samples, unsigned int in_bits_per_sample, bool* out_data );
00332 
00333 #endif // VIL_NITF2_IMAGE_H