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

vil_tiff.h

Go to the documentation of this file.
00001 // This is core/vil/file_formats/vil_tiff.h
00002 #ifndef vil_tiff_file_format_h_
00003 #define vil_tiff_file_format_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \author    awf@robots.ox.ac.uk
00010 // \date 16 Feb 00
00011 //
00012 //\verbatim
00013 //  Modifications
00014 //   3 Oct 2001 Peter Vanroose - Implemented get_property and set_property
00015 //   5 Jan 2002 Ian Scott      - Converted to vil
00016 //   9 Dec 2003 Peter Vanroose - Added support for 1-bit pixel (bitmapped) images
00017 //   21 Dec 2005 J.L. Mundy - Substantial rewrite to handle a more
00018 //       complete tiff 6.0 standard. Files with tiles can now be read and
00019 //       written. Only tiled images are considered blocked, i.e. not strips.
00020 //       Block dimensions must be a multiple of 16, for compatibility with
00021 //       compression schemes. Tiff files with separate color bands are not handled
00022 //   24 Mar 2007 J.L. Mundy - added smart pointer on TIFF handle to support
00023 //       multiple resources from a single tiff file; required for pyramid
00024 //   KNOWN BUG - 24bit samples for both nplanes = 1 and nplanes = 3
00025 //\endverbatim
00026 
00027 #include <vcl_vector.h>
00028 #include <vcl_cassert.h>
00029 #include <vcl_iostream.h>
00030 #include <vil/vil_config.h>
00031 #include <vil/vil_file_format.h>
00032 #include <vil/vil_image_resource.h>
00033 #include <vil/vil_memory_chunk.h>
00034 #include <vil/vil_blocked_image_resource.h>
00035 #include <vil/vil_pyramid_image_resource.h>
00036 #include <vil/file_formats/vil_tiff_header.h>
00037 #include <tiffio.h>
00038 #if HAS_GEOTIFF
00039 #include <vil/file_formats/vil_geotiff_header.h>
00040 #endif
00041 
00042 
00043 //: Loader for tiff files
00044 class vil_tiff_file_format : public vil_file_format
00045 {
00046  public:
00047   virtual char const *tag() const;
00048   virtual vil_image_resource_sptr make_input_image(vil_stream *vs);
00049 
00050   virtual vil_pyramid_image_resource_sptr
00051   make_input_pyramid_image(char const* file);
00052 
00053   //: Construct a pyramid image resource from a base image.
00054   //  All levels are stored in the same resource file. Each level has the same
00055   //  scale ratio (0.5) to the preceeding level. Level 0 is the original
00056   //  base image. The resource is returned open for reading.
00057   //  The temporary directory is for storing intermediate image
00058   //  resources during the construction of the pyramid. Files are
00059   //  be removed from the directory after completion.  If temp_dir is 0
00060   //  then the intermediate resources are created in memory.
00061   virtual vil_pyramid_image_resource_sptr
00062   make_pyramid_image_from_base(char const* filename,
00063                                vil_image_resource_sptr const& base_image,
00064                                unsigned nlevels,
00065                                char const* temp_dir);
00066 
00067   virtual vil_image_resource_sptr make_output_image(vil_stream* vs,
00068                                                     unsigned ni,
00069                                                     unsigned nj,
00070                                                     unsigned nplanes,
00071                                                     enum vil_pixel_format);
00072 
00073   virtual vil_blocked_image_resource_sptr
00074   make_blocked_output_image(vil_stream* vs,
00075                             unsigned ni,
00076                             unsigned nj,
00077                             unsigned nplanes,
00078                             unsigned size_block_i,
00079                             unsigned size_block_j,
00080                             enum vil_pixel_format);
00081 
00082 
00083   virtual vil_pyramid_image_resource_sptr
00084   make_pyramid_output_image(char const* file);
00085 };
00086 
00087 struct tif_stream_structures;
00088 class vil_tiff_header;
00089 //Need to create a smartpointer mechanism for the tiff
00090 //file in order to handle multiple images, e.g. for pyramid
00091 //resource
00092 //A reference counting wrapper for the TIFF handle
00093 struct tif_ref_cnt
00094 {
00095   tif_ref_cnt(TIFF* tif):tif_(tif), cnt_(0){}
00096   TIFF* tif(){return tif_;}
00097   void ref(){cnt_++;}
00098   void unref(){
00099     if (--cnt_<=0) 
00100     {
00101       TIFFClose(tif_);
00102       delete this;
00103     }
00104   }
00105  private:
00106   TIFF* tif_;
00107   unsigned cnt_;
00108 };
00109 
00110 //The smart pointer to the tiff handle
00111 struct tif_smart_ptr
00112 {
00113   tif_smart_ptr(): tptr_(0){}
00114 
00115   tif_smart_ptr(tif_ref_cnt* tptr):tptr_(tptr)
00116   { if (tptr_) tptr_->ref(); }
00117 
00118   tif_smart_ptr(tif_smart_ptr const& tp)
00119   {tptr_ = tp.tptr_; if (tptr_) tptr_->ref();}
00120 
00121   ~tif_smart_ptr()
00122   {
00123     // the strange order of events in this function is to avoid
00124     // heap corruption if unref() causes *this to be deleted.
00125     tif_ref_cnt* old_ptr = tptr_;
00126     tptr_ = 0;
00127     if (old_ptr)
00128       old_ptr->unref();
00129   }
00130   //: Inverse bool
00131   bool operator!() const
00132   {
00133     return (tptr_ != (tif_ref_cnt*)0)? false : true; 
00134   }
00135 
00136   //: Convenient get TIFF* for header construction; assumes temporary use
00137   TIFF* tif() const {if (tptr_) return tptr_->tif(); return (TIFF*)0;}
00138  private:
00139   tif_ref_cnt* tptr_;
00140 };
00141 
00142 //: Generic image interface for image TIFF image files (could have multiple images)
00143 class vil_tiff_image : public vil_blocked_image_resource
00144 {
00145   friend class vil_tiff_file_format;
00146  public:
00147 
00148   vil_tiff_image(tif_smart_ptr const& tif,
00149                  vil_tiff_header* th, const unsigned nimages = 1);
00150 
00151   ~vil_tiff_image();
00152 
00153   //: Dimensions:  planes x width x height x components
00154   virtual unsigned nplanes() const;
00155   virtual unsigned ni() const;
00156   virtual unsigned nj() const;
00157 
00158   virtual enum vil_pixel_format pixel_format() const;
00159 
00160   //: returns "tiff"
00161   char const *file_format() const;
00162 
00163 #if HAS_GEOTIFF
00164   //: are there any geotiff tags
00165   bool is_GEOTIFF() { return h_->is_GEOTIFF(); }
00166 #endif
00167 
00168   //Block interface
00169 
00170   //: Block size in columns (must be a multiple of 16)
00171   virtual unsigned size_block_i() const;
00172 
00173   //: Block size in rows (must be a multiple of 16)
00174   virtual unsigned size_block_j() const;
00175 
00176   //: Number of blocks in image width
00177   virtual unsigned n_block_i() const;
00178 
00179   //: Number of blocks in image height
00180   virtual unsigned n_block_j() const;
00181 
00182   virtual vil_image_view_base_sptr get_block( unsigned  block_index_i,
00183                                               unsigned  block_index_j ) const;
00184 
00185   virtual bool put_block( unsigned  block_index_i, unsigned  block_index_j,
00186                           const vil_image_view_base& blk );
00187 
00188   //: Put the data in this view back into the image source.
00189   virtual bool put_view(const vil_image_view_base& im, unsigned i0, unsigned j0);
00190 
00191   //: Return true if the property given in the first argument has been set.
00192   // currently defined:
00193   //  "quantisation_depth" - number of relevant bits per pixel
00194   //  "size_block_i" and "size_block_j" - block dimensions
00195 
00196   virtual bool get_property(char const *tag, void *prop = 0) const;
00197 
00198 #if HAS_GEOTIFF
00199   //* returns null if the tiff file does not include any geotiff tags
00200   vil_geotiff_header* get_geotiff_header();
00201 #endif
00202 
00203   friend class vil_tiff_pyramid_resource;
00204 
00205   //:indicates the number of images in the tiff file
00206   unsigned int nimages() const {return nimages_;}
00207 
00208   //:the image index for multiple image files
00209   unsigned int index() const {return index_;}
00210   //:point to a particular image in the file
00211   void set_index(const unsigned int index)
00212     {assert(index<nimages_); index_=index;}
00213  private:
00214   //: the TIFF handle to the open resource file
00215   tif_smart_ptr t_;
00216 
00217   //: the TIFF header information
00218   vil_tiff_header* h_;
00219   //: the default image header index
00220   unsigned int index_;
00221   //: number of images in the file
00222   unsigned int nimages_;
00223 #if 0
00224   //to keep the tiff file open during reuse of multiple tiff resources
00225   //in a single file otherwise the resource destructor would close the file
00226   void clear_TIFF() { t_ = 0; }
00227 #endif
00228   //: the number of samples in a block
00229   unsigned samples_per_block() const;
00230 
00231   enum vil_pixel_format compute_pixel_format();
00232 
00233   void copy_byte_block(vxl_byte* data, const vxl_uint_32 nbytes,
00234                        vil_memory_chunk_sptr& cnk) const;
00235 
00236   //: convert a packed block to an expanded view
00237   vil_image_view_base_sptr
00238     view_from_buffer(vil_pixel_format& fmt,
00239                      vil_memory_chunk_sptr const& buf,
00240                      unsigned samples_per_block,
00241                      unsigned bits_per_sample) const;
00242 
00243   //: the key methods for decoding the file data
00244   vil_image_view_base_sptr fill_block_from_tile(vil_memory_chunk_sptr const & buf) const;
00245 
00246   vil_image_view_base_sptr fill_block_from_strip(vil_memory_chunk_sptr const & buf) const;
00247 
00248 #if 0
00249   vil_image_view_base_sptr get_block_internal( unsigned block_index_i,
00250                                                unsigned block_index_j ) const;
00251   void
00252     get_blocks_internal( unsigned start_block_i,
00253                          unsigned end_block_i,
00254                          unsigned start_block_j,
00255                          unsigned end_block_j,
00256                          vcl_vector< vcl_vector< vil_image_view_base_sptr > >& blocks ) const;
00257 #endif
00258   bool put_block(unsigned bi, unsigned bj, unsigned i0,
00259                  unsigned j0, const vil_image_view_base& im);
00260 
00261   unsigned block_index(unsigned block_i, unsigned block_j) const;
00262 
00263   //: fill out the block with leading zeros or trailing zeros if necessary
00264   void pad_block_with_zeros(unsigned ioff, unsigned joff,
00265                             unsigned iclip, unsigned jclip,
00266                             unsigned bytes_per_pixel,
00267                             vxl_byte* block_buf);
00268 
00269   //: fill the block with view data
00270   void fill_block_from_view(unsigned bi, unsigned bj,
00271                             unsigned i0, unsigned j0,
00272                             unsigned ioff, unsigned joff,
00273                             unsigned iclip, unsigned jclip,
00274                             const vil_image_view_base& im,
00275                             vxl_byte*& block_buf);
00276 
00277   void bitpack_block(unsigned bytes_per_block,
00278                      vxl_byte* in_block_buf,
00279                      vxl_byte* out_block_buf);
00280 
00281   bool write_block_to_file(unsigned bi, unsigned bj,
00282                            unsigned block_size_bytes,
00283                            vxl_byte* block_buf);
00284 };//End of single image TIFF resource
00285 
00286 
00287 ///--------- Representation of Pyramid Images by multi-image TIFF -------
00288 //
00289 //
00290 // It is assumed that image scales are not necessarily ordered with
00291 // respect to tiff header index. This data structure maintains essential
00292 // information about each pyramid level. The struct can be sorted on scale
00293 // to form an ordered pyramid.
00294 struct tiff_pyramid_level
00295 {
00296  public:
00297   tiff_pyramid_level(unsigned header_index, unsigned ni,
00298                      unsigned nj, unsigned nplanes, vil_pixel_format fmt)
00299    : header_index_(header_index), scale_(1.0f), ni_(ni), nj_(nj),
00300      nplanes_(nplanes), pix_fmt_(fmt), cur_level_(0)
00301   {}
00302 
00303   ~tiff_pyramid_level() {}
00304 
00305   //:the tiff header index
00306   unsigned header_index_;
00307 
00308   //:scale associated with level
00309   float scale_;
00310 
00311   //:the image width
00312   unsigned ni_;
00313 
00314   //: the image length
00315   unsigned nj_;
00316 
00317   //:the nubmer of planes
00318   unsigned nplanes_;
00319 
00320   //: the pixel format
00321   vil_pixel_format pix_fmt_;
00322 
00323   //: temporary variable for current level
00324   unsigned cur_level_;
00325 
00326   void print(const unsigned l)
00327   { vcl_cout << "level[" << l <<  "] hindex " << header_index_ << " scale: " << scale_ << "  width: " << ni_ << vcl_endl; }
00328 };
00329 
00330 //:Pyramid resource built on the multi-image capability of the TIFF format
00331 // If read is true then the resource is open for reading else it is open for writing
00332 class vil_tiff_pyramid_resource : public vil_pyramid_image_resource
00333 {
00334  public:
00335   vil_tiff_pyramid_resource(tif_smart_ptr const& t, bool read = true);
00336 
00337   virtual ~vil_tiff_pyramid_resource();
00338 
00339   //: The number of planes (or components) of the image.
00340   // This method refers to the base (max resolution) image
00341   // Dimensions:  Planes x ni x nj.
00342   // This concept is treated as a synonym to components.
00343   inline virtual unsigned nplanes() const
00344   { if (levels_[0]) return levels_[0]->nplanes_; return 1; }
00345 
00346   //: The number of pixels in each row.
00347   // Dimensions:  Planes x ni x nj.
00348   inline virtual unsigned ni() const
00349   { if (levels_[0]) return levels_[0]->ni_; return 0; }
00350 
00351   //: The number of pixels in each column.
00352   // Dimensions:  Planes x ni x nj.
00353   inline virtual unsigned nj() const
00354   { if (levels_[0]) return levels_[0]->nj_; return 0; }
00355 
00356   //: Pixel Format.
00357   inline virtual enum vil_pixel_format pixel_format() const
00358   { if (levels_[0]) return levels_[0]->pix_fmt_; return VIL_PIXEL_FORMAT_UNKNOWN; }
00359 
00360   //: Return a string describing the file format.
00361   // Only file images have a format, others return 0
00362   virtual char const* file_format() const { return "ptif"; }
00363 
00364   //:Methods particular to pyramid resource
00365 
00366   //: number of pyramid levels
00367   virtual unsigned nlevels() const { return levels_.size(); }
00368 
00369   //:Get a partial view from the image from a specified pyramid level
00370   virtual vil_image_view_base_sptr get_copy_view(unsigned i0, unsigned n_i,
00371                                                  unsigned j0, unsigned n_j,
00372                                                  unsigned level) const;
00373 
00374   //:Get a partial view from the image in the pyramid closest to scale.
00375   // The origin and size parameters are in the coordinate system of the base image.
00376   // The scale factor is with respect to the base image (base scale = 1.0).
00377   virtual vil_image_view_base_sptr get_copy_view(unsigned i0, unsigned n_i,
00378                                                  unsigned j0, unsigned n_j,
00379                                                  const float scale,
00380                                                  float& actual_scale) const;
00381 
00382   //:
00383   // Caution! The resource is assigned a header and the data is permanently
00384   // written into the file. Be sure you want to commit to the file.
00385   bool put_resource(vil_image_resource_sptr const& resc);
00386 
00387   //: returns the image resource at the specified pyramid level
00388   vil_image_resource_sptr get_resource(const unsigned level) const;
00389 
00390   //: for debug purposes
00391   void print(const unsigned level)
00392   { if (level<levels_.size()) levels_[level]->print(level); }
00393  protected:
00394   //:default constructor
00395   vil_tiff_pyramid_resource();
00396   //utility methods
00397   //:normalize the scale factors so that the base image scale = 1.0
00398   void normalize_scales();
00399 
00400   //:find the image resource with scale closest to specified scale
00401   tiff_pyramid_level* closest(const float scale) const;
00402 
00403   //: If true resource is open for read, else open for write
00404   bool read_;
00405 
00406   //: the tiff handle
00407   tif_smart_ptr t_;
00408 
00409   //The set of images in the pyramid. levels_[0] is the base image
00410   vcl_vector<tiff_pyramid_level*> levels_;
00411 };//End of pyramid image
00412 
00413 
00414 //------------------------ Lifted from vil_nitf2_image ------------------------
00415 //            If this happens again then maybe should elevate to a
00416 //            utility class -- JLM
00417 //
00418 
00419 //:
00420 // This function does a lot of work for \sa byte_align_data().  It will strip one value
00421 // of ni bits and return it as a value of type T (with zero padding on the MSBs).
00422 // Both io and ni are lengths (in bits - not bytes).
00423 //
00424 // \param i0: Offset (in bits - not bytes) from in_val[0].  This will be the start
00425 //            of the bits extracted from in_val.
00426 // \param ni: number of bits (starting from i0) that will be extracted from in_val.
00427 template< class T >
00428 T tiff_get_bits( const T* in_val, unsigned i0, unsigned ni )
00429 {
00430   unsigned sample_offset = i0 / ( sizeof(T)*8 );
00431   unsigned bit_offset = i0 % ( sizeof(T)*8 );
00432 
00433   unsigned strip_left = bit_offset;
00434   int strip_right = ( sizeof( T ) * 8 ) - ( bit_offset + ni );
00435   T temp = in_val[sample_offset];
00436   if ( strip_left > 0 ){
00437     //strip off the appropriate bits from the vcl_left (replacing them with zeros)
00438     temp = temp << strip_left;
00439     temp = temp >> strip_left;
00440   }
00441   if ( strip_right > 0 ){
00442     //strip off the appropriate bits from the vcl_right
00443     //the bit shift operator wasn't having the correct effect, so that'w
00444     //why the for loop
00445     for ( int i = 0 ; i < strip_right ; i++ ) temp /= 2;
00446     //temp = temp >> strip_right;
00447   }
00448   else if ( strip_right < 0 ){
00449     //we didn't have enough bits in the first element of the in_val array
00450     //need to get some from the next element
00451 
00452     for ( int i = 0 ; i < (-strip_right) ; i++ ) temp *= 2;
00453     temp += tiff_get_bits<T>( in_val+sample_offset+1, 0, -strip_right );
00454 
00455 #if 0
00456     T next = in_val[sample_offset+1];
00457     //shift right a bigger amount
00458     int new_strip_right = strip_right + (sizeof(T)*8);
00459     for ( int i = 0 ; i < new_strip_right ; i++ ) next /= 2;
00460     // next is the LSB part
00461     unsigned new_strip_left = 1- strip_right;
00462     temp = temp << new_strip_left;
00463     temp += next;
00464 #endif
00465   }
00466 #ifdef DEBUG
00467   vcl_cout << "Out val = " << vcl_hex << temp << vcl_dec << '\n';
00468 #endif
00469   return temp;
00470 }
00471 
00472 //:
00473 // This function will byte align the data in in_data and store the result in out_data.  For example, let's
00474 // say that you had in_data is of type unsigned char and contains the following data: 110010111001111010000110.
00475 // In other words:
00476 // in_data[0] = 203 (11001011)
00477 // in_data[1] = 158 (10011110)
00478 // in_data[2] = 134 (10000110)
00479 // Let's further say you called this function like this: byte_align_data( in_data, 8, 3, out_data ).
00480 // Then, when the function finished, out_data would look like this:
00481 // out_data[0] = 6 (00000110)
00482 // out_data[1] = 2 (00000010)
00483 // out_data[2] = 7 (00000111)
00484 // out_data[3] = 1 (00000001)
00485 // out_data[4] = 7 (00000111)
00486 // out_data[5] = 2 (00000010)
00487 // out_data[6] = 0 (00000000)
00488 // out_data[7] = 6 (00000110)
00489 //
00490 // Basically, what the function did was group the bitstream into groups of three and then store all of the
00491 // values into out_data.  It had to zero pad all the values (on the MSB side) to get them into out_data.  That's
00492 // why out_data is bigger.
00493 //
00494 // This function works with other unsigned types of data too.  For example, let's say in_data was of type unsigned int
00495 // and contained the following bits: 0100110010111000 0111101100000000 1111000011110000 (note that this bitstream is shown
00496 // in big endian notation, that will not be the case if you are on a little endian machine -- this is just for illustration)
00497 // in other words:
00498 // in_data[0] = 19640 (0100110010111000) [shown in big endian for illustrative purposes only]
00499 // in_data[1] = 31488 (0111101100000000) [shown in big endian for illustrative purposes only]
00500 // in_data[2] = 61680 (1111000011110000) [shown in big endian for illustrative purposes only]
00501 // Let's further say, you called this function like this byte_align_data( in_data, 4, 12, out_data ).
00502 // Then out_data would be aligned along two byte (sixteen bit) boundaries and would look like this:
00503 // out_data[0] = 1227 (0000010011001011) [shown in big endian for illustrative purposes only]
00504 // out_data[1] = 2171 (0000100001111011) [shown in big endian for illustrative purposes only]
00505 // out_data[2] = 15   (0000000000001111) [shown in big endian for illustrative purposes only]
00506 // out_data[3] = 240  (0000000011110000) [shown in big endian for illustrative purposes only]
00507 //
00508 // Because of the fact that this function uses bit shifting operators, and the behavior of the vcl_right
00509 // shift operator is implementation specific when applied to a negative number, you should probably
00510 // only use this function on unsigned data.
00511 //
00512 // @param in_data: The input data.  It must be at least (num_samples*in_bits_per_sample\8) bytes long.
00513 //                The values should have the endianness of your platform.
00514 // @param num_samples: The number of actual samples in in_data.
00515 // @param in_bits_per_sample: The bits per sample in in_data
00516 // @param out_data: I'll store the output data here.  It must be at least (num_samples*sizeof(T)) bytes long
00517 //                 The values will have the endianness of your platform.
00518 //
00519 // Note that inBitsPerSampe must not be >= sizeof(T).  If they were to be equal, then this function
00520 // would have nothing to do (in_data is already byte aligned).  If in_bits_per_sample were less than sizeof(T),
00521 // then each element of out_data would be too small to store the corresponding elements in in_data.
00522 //
00523 // Note that there is a specialization for the bool case which just casts it to an 8 bit quantity then calls
00524 // this same function.  This is because the logic in get_bits<> doesn't work for the bool case.
00525 template< class T >
00526 T* tiff_byte_align_data( T* in_data, unsigned num_samples, unsigned in_bits_per_sample, T* out_data )
00527 {
00528   assert( in_bits_per_sample < sizeof(T)*8 );
00529 
00530   //grab each value from the bitstream (in_data) that we need... one
00531   //at a time
00532   unsigned bit_offset = 0;
00533   for ( unsigned o = 0 ; o < num_samples ; o++ ){
00534     out_data[o] = tiff_get_bits<T>( in_data, bit_offset, in_bits_per_sample );
00535     //printf("bo = %i, in = %x, out =  %x\n", bit_offset, in_data[o], out_data[o]);
00536     bit_offset+=in_bits_per_sample;
00537   }
00538 
00539   return out_data;
00540 }
00541 
00542 template<> bool* tiff_byte_align_data<bool>( bool* in_data, unsigned num_samples, unsigned in_bits_per_sample, bool* out_data );
00543 
00544 #endif // vil_tiff_file_format_h_

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