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
1.4.4