core/vil/file_formats/vil_tiff_header.h
Go to the documentation of this file.
00001 // This is core/vil/file_formats/vil_tiff_header.h
00002 #ifndef vil_tiff_header_h_
00003 #define vil_tiff_header_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \author    J.L. Mundy
00010 // \date 22 Dec 2005
00011 // \brief A header structure for tiff files
00012 //
00013 // This class is responsible for extracting (putting) information
00014 // from (into) the tiff header that is required to specify a vil_image_resource
00015 // There are bool flags that indicate that the item has been successfully
00016 // read (written) to the open tiff file.
00017 //
00018 // Notes:
00019 //   -  The size of each strip can be different and less than the full
00020 //      strip, i.e. bytes_per_line * rows_per_strip, would require.
00021 //      Perhaps this case should be rejected, but
00022 //      it has occurred in images that IrfanView and ImageMagick CAN read.
00023 //      In this case, the buffers are set up with capacity for a full strip.
00024 //   -  The number of rows in a strip can exceed the image length. The actual
00025 //      byte count is equal to the number of bytes in the image. In this
00026 //      case, the block size is truncated to the image_length.
00027 //   -  The width and height of a tile must be a multiple of 16
00028 //   -  The current implementation can't handle Planar Configuration =2,
00029 //      which is RGB in separate color bands.
00030 //   -  If rows_per_strip is missing, it is assumed to be infinity
00031 //      (http://www.awaresystems.be/imaging/tiff/tifftags/rowsperstrip.html)
00032 //
00033 // \verbatim
00034 //  Modifications
00035 //   November 8, 2007 - Added the case of four planes that is necessary to
00036 //                      read and write satellite multispectral image data - JLM
00037 //   January 9, 2012  - Use default value (1) for images that do not have SamplesPerPixel tag - GY
00038 // \endverbatim
00039 
00040 #include <vcl_string.h>
00041 #include <vcl_vector.h>
00042 #include <vxl_config.h>
00043 #include <vcl_cmath.h>
00044 #include <vil/vil_config.h>
00045 #include <vil/vil_pixel_format.h>
00046 #include <tiffio.h>
00047 
00048 struct ushort_tag
00049 {
00050   ushort_tag(): valid(false) {}
00051   vxl_uint_16 val;
00052   bool valid;
00053 };
00054 
00055 struct ulong_tag
00056 {
00057   ulong_tag() : valid(false) {}
00058   vxl_uint_32 val;
00059   bool valid;
00060 };
00061 
00062 // The tiff header elements (tags)
00063 // planar_configuration determines the layout of many of the
00064 // structures
00065 //  1 - pixel samples are contiguous, e.g. RGBRGB...
00066 //  2 - samples are in separate planes (analogous to vil nplanes)
00067 class vil_tiff_header
00068 {
00069  public:
00070   vil_tiff_header(TIFF* tif): tif_(tif) {format_supported = read_header();}
00071 
00072   vil_tiff_header(TIFF* tif, const unsigned ni, const unsigned nj,
00073                   const unsigned nplanes, vil_pixel_format const& fmt,
00074                   const unsigned size_block_i, const unsigned size_block_j);
00075 // the baseline tiff header stucture
00076   vcl_string artist;
00077 
00078   //**Issue** spec says this should be an array[samples_per_pixel] but
00079   //actual multi-sample tiff file headers have this as an
00080   //vxl_uint_16 CHECK (JLM)
00081   ushort_tag bits_per_sample;
00082   vxl_uint_16 bytes_per_sample() const
00083   { return bits_per_sample.valid ? static_cast<vxl_uint_16>((bits_per_sample.val + 7)/8) : 0u; }
00084 
00085   ushort_tag cell_length;
00086 
00087   ushort_tag cell_width;
00088 
00089   // color_map[index][pixel_sample] index ranges from 0->2^bits_per_sample-1
00090   // pixel_sample 0->samples_per_pixel -1
00091   vcl_vector<vcl_vector<vxl_uint_16> >color_map;
00092   bool color_map_valid;
00093 
00094   ushort_tag compression;
00095 
00096   vcl_string copyright;
00097 
00098   vcl_string date_time;
00099 
00100   //Additional samples per pixel, e.g. transparency
00101   ushort_tag extra_samples;
00102 
00103   ushort_tag fill_order;
00104 
00105   //for gray scale data provides a radiometry map, e.g. true reflectance
00106   //index ranges from 0->2^bits_per_sample-1
00107   vcl_vector<vxl_uint_16> gray_response_curve;
00108   bool grey_response_curve_valid;
00109 
00110   //the unit of radiometry
00111   ushort_tag gray_response_unit;
00112 
00113   vcl_string host_computer;
00114   vcl_string image_description;
00115 
00116   ulong_tag image_length;
00117 
00118   //:theoretical from samples per line
00119   vxl_uint_32 bytes_per_line() const;
00120 
00121   //:As returned by the TIFF library
00122   vxl_uint_32 actual_bytes_per_line() const;
00123 
00124   ulong_tag image_width;
00125 
00126   unsigned nplanes;
00127 
00128   vcl_string make;
00129 
00130   ushort_tag max_sample_value;
00131 
00132   ushort_tag min_sample_value;
00133 
00134   vcl_string model;
00135 
00136   ushort_tag orientation;
00137 
00138   ushort_tag photometric;
00139 
00140   ushort_tag planar_config;
00141 
00142   ushort_tag resolution_unit;
00143 
00144   ulong_tag rows_per_strip;
00145 
00146   vxl_uint_32 rows_in_strip() const;
00147 
00148   vxl_uint_32 strips_per_image() const
00149   { return rows_per_strip.valid ?
00150       static_cast<vxl_uint_32>(vcl_floor(1.0+(image_length.val-1)/rows_per_strip.val)) : 1L;
00151   }
00152 
00153   //the actual size of the strip in the file
00154   vxl_uint_32 actual_bytes_per_strip(const vxl_uint_32 strip_index) const;
00155 
00156   //the theoretical size based on rows_per_strip and bytes_per_line
00157   vxl_uint_32 bytes_per_strip() const;
00158 
00159   ushort_tag sample_format;
00160   ushort_tag samples_per_pixel;
00161 
00162   vcl_string software;
00163 
00164   //for planar_config = 1
00165   //[st0|st1|...|strips_per_image-1]
00166   //for planar_config = 2
00167   //[st0|st1|...|strips_per_image-1] ... [st0|st1|...|strips_per_image-1]
00168   //          sample 0               ...         samples_per_pixel-1
00169   vxl_uint_32* strip_byte_counts;
00170   bool strip_byte_counts_valid;
00171   vxl_uint_32* strip_offsets;
00172   bool strip_offsets_valid;
00173 
00174   ushort_tag subfile_type;
00175 
00176   ushort_tag thresholding;
00177 
00178   float x_resolution;
00179   bool x_resolution_valid;
00180 
00181   float y_resolution;
00182   bool y_resolution_valid;
00183 
00184   //tiff extension for blocking
00185   bool is_tiled_flag;
00186 
00187   ulong_tag tile_width;
00188 
00189   ulong_tag tile_length;
00190 
00191   //for planar_config = 1
00192   //[st0|st1|...|tiles_per_image-1]
00193   //for planar_config = 2
00194   //[st0|st1|...|tiles_per_image-1] ... [st0|st1|...|tiles_per_image-1]
00195   //          sample 0               ...         samples_per_pixel-1
00196   vxl_uint_32*  tile_offsets;
00197   bool tile_offsets_valid;
00198   vxl_uint_32* tile_byte_counts;
00199   bool tile_byte_counts_valid;
00200 
00201   vxl_uint_32 tiles_across() const
00202   { return tile_width.valid ?
00203       static_cast<vxl_uint_32>(vcl_floor(1.0+(image_width.val-1)/tile_width.val)) : 0L;
00204   }
00205 
00206   vxl_uint_32 tiles_down() const
00207   { return tile_length.valid ?
00208       static_cast<vxl_uint_32>(vcl_floor(1.0+(image_length.val-1)/tile_length.val)) : 0L;
00209   }
00210 
00211   vxl_uint_32 tiles_per_image() const {return tiles_across()*tiles_down();}
00212 
00213   vxl_uint_32 bytes_per_tile() const;
00214 
00215   //: the actual number of separate image planes in the tiff image
00216   unsigned n_separate_image_planes() const;
00217 
00218   //: the number of encoded bytes in a tile or strip
00219   unsigned encoded_bytes_per_block() const;
00220 
00221   //: the number of samples in a block
00222   unsigned samples_per_line() const;
00223 
00224   //: is the image tiled
00225   bool is_tiled() const;
00226 
00227   //: is the image striped (one of these must be true or read failed)
00228   bool is_striped() const;
00229 
00230 #if HAS_GEOTIFF
00231   bool is_GEOTIFF() const;
00232 #endif
00233 
00234   bool need_byte_swap()
00235   { return file_is_big_endian_!=machine_is_big_endian_ &&
00236            bits_per_sample.val%8 != 0;
00237   }
00238 
00239   vil_pixel_format pix_fmt;
00240 
00241   //: true if the specified format can be read or written.
00242   // check and return a null resource if false
00243   bool format_supported;
00244 
00245   //: the number of images in the file
00246   vxl_uint_16  n_images();
00247  private:
00248   TIFF* tif_;
00249   //: read/write mode true for read.
00250   // returns false if the format cannot be read by current version
00251   bool read_header();
00252   //:returns false if the format cannot be written by current version
00253   bool set_header(unsigned ni, unsigned nj, unsigned nplanes,
00254                   vil_pixel_format const& fmt,
00255                   const unsigned size_block_i,
00256                   const unsigned size_block_j);
00257   //:returns false if the format not handled by this reader
00258   bool compute_pixel_format();
00259   //:returns false if the format not handled by this writer
00260   bool parse_pixel_format(vil_pixel_format const& fmt);
00261   bool file_is_big_endian_;
00262   bool machine_is_big_endian_;
00263 };
00264 
00265 #endif //vil_tiff_header_h_