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

vil_nitf2_image.h

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

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