core/vil/file_formats/vil_tiff_header.cxx
Go to the documentation of this file.
00001 #include "vil_tiff_header.h"
00002 #include <vcl_iostream.h>
00003 #include <vcl_cstdio.h>
00004 #include <vcl_ctime.h>
00005 
00006 #if HAS_GEOTIFF
00007 #include <vil/file_formats/vil_geotiff_header.h>
00008 #endif
00009 
00010 static vcl_string date_and_time()
00011 {
00012   vcl_time_t clock;
00013   struct vcl_tm *t_m;
00014   clock = vcl_time(NULL);
00015   t_m = vcl_localtime(&clock);
00016   char tmp[20];
00017   char datetime[20];
00018   vcl_strftime(tmp,sizeof(datetime),"%Y-%m-%d %H:%M:%S",t_m);
00019   // changed from "%c", to make it generic, size=19, and avoid compiler warning
00020   vcl_sprintf(datetime,"%19s",tmp);
00021   return vcl_string(datetime);
00022 }
00023 
00024 static void read_string(TIFF* tif, ttag_t tag, vcl_string& stag, vcl_string const& deflt = "not_defined")
00025 {
00026   char* adr = 0;
00027   TIFFGetField(tif, tag, &adr);
00028   if (adr)
00029     stag = vcl_string(adr);
00030   else
00031     stag = deflt;
00032 }
00033 
00034 static void read_short_tag(TIFF* tif, ttag_t tag, ushort_tag& utag, vxl_uint_16 deflt =0)
00035 {
00036   utag.valid = TIFFGetField(tif, tag, &(utag.val))>0;
00037   if (!utag.valid)
00038     utag.val = deflt;
00039 }
00040 
00041 static void read_long_tag(TIFF* tif, ttag_t tag, ulong_tag& utag, vxl_uint_32 deflt = 0)
00042 {
00043   utag.valid = TIFFGetField(tif, tag, &(utag.val))>0;
00044   if (!utag.valid)
00045     utag.val = deflt;
00046 }
00047 
00048 static void read_float_tag(TIFF* tif, ttag_t tag, float& val, bool& valid, float deflt = 0)
00049 {
00050   valid = TIFFGetField(tif, tag, &(val))>0;
00051   if (!valid)
00052     val = deflt;
00053 }
00054 
00055 #if 0 // unused static function
00056 //assumes array is resized properly
00057 static bool read_long_array(TIFF* tif, ttag_t tag,
00058                             vcl_vector<vxl_uint_32>& array)
00059 {
00060   vxl_uint_32 * a;
00061   if (TIFFGetField(tif, tag, &a))
00062   {
00063     for (vxl_uint_32 i=0; i<array.size(); ++i) { array[i]=a[i]; }
00064     return true;
00065   }
00066   else return false;
00067 }
00068 #endif // unused static function
00069 
00070 static void write_short_tag(TIFF* tif, ttag_t tag, ushort_tag const& ustag)
00071 {
00072   if (ustag.valid)
00073     TIFFSetField(tif, tag, ustag.val);
00074 }
00075 
00076 static void write_long_tag(TIFF* tif, ttag_t tag, ulong_tag const& ultag)
00077 {
00078   if (ultag.valid)
00079     TIFFSetField(tif, tag, ultag.val);
00080 }
00081 
00082 #if 0 // not currently used...
00083 static void write_float_tag(TIFF* tif, ttag_t tag, float const val, bool const valid)
00084 {
00085   if (valid)
00086     TIFFSetField(tif, tag, val);
00087 }
00088 #endif
00089 
00090 static void write_string(TIFF* tif, ttag_t tag, vcl_string const& stag)
00091 {
00092   TIFFSetField(tif, tag, stag.c_str());
00093 }
00094 
00095 
00096 bool vil_tiff_header::read_header()
00097 {
00098   //DEBUG
00099 #ifdef DEBUG
00100   vcl_cout << date_and_time() << '\n';
00101 #endif
00102   //====
00103   //Determine the endian state of the file and machine
00104   file_is_big_endian_ = TIFFIsByteSwapped(tif_)>0;
00105 
00106   //also need machine endian
00107 #if VXL_BIG_ENDIAN
00108     machine_is_big_endian_ = true;
00109 #else
00110     machine_is_big_endian_ = false;
00111 #endif
00112   //the following group must be read first since they
00113   //dictate subsequent tag structures
00114   ///-----------------------------------------------///
00115   read_short_tag(tif_,TIFFTAG_PHOTOMETRIC, photometric);
00116   read_short_tag(tif_,TIFFTAG_PLANARCONFIG, planar_config, 1);
00117   read_short_tag(tif_,TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel, 1);
00118   read_short_tag(tif_,TIFFTAG_BITSPERSAMPLE, bits_per_sample, 8);
00119   is_tiled_flag = TIFFIsTiled(tif_)>0;
00120   ///-----------------------------------------------///
00121   read_string(tif_,TIFFTAG_ARTIST , artist);
00122   read_short_tag(tif_,TIFFTAG_CELLLENGTH, cell_length);
00123   read_short_tag(tif_,TIFFTAG_CELLWIDTH, cell_width);
00124   color_map_valid = false;
00125   if (bits_per_sample.valid &&
00126       photometric.valid &&
00127       photometric.val == PHOTOMETRIC_PALETTE)
00128   {
00129     vxl_uint_16* cm[3];
00130     TIFFGetField(tif_,TIFFTAG_COLORMAP, &cm[0], &cm[1], &cm[2]);
00131     unsigned size = 1<<bits_per_sample.val;
00132     color_map.resize(size);
00133     for (unsigned i = 0; i<size; ++i)
00134     {
00135       vcl_vector<vxl_uint_16> rgb(3);
00136       rgb[0]=cm[0][i];  rgb[1]=cm[1][i];  rgb[2]=cm[2][i];
00137       color_map[i] = rgb;
00138 #ifdef DEBUG
00139       vcl_cout << "RGB[" << i << "]=(" << rgb[0] << ' ' << rgb[1] << ' ' << rgb[2] << ")\n";
00140 #endif
00141     }
00142     color_map_valid = true;
00143   }
00144   read_short_tag(tif_,TIFFTAG_COMPRESSION, compression);
00145   read_string(tif_,TIFFTAG_COPYRIGHT, copyright);
00146   read_string(tif_,TIFFTAG_DATETIME,date_time);
00147 
00148   // EXTRASAMPLES tag requires two input arguments, which is different
00149   // from other 16bit values.
00150   vxl_uint_16* sample_info=0;
00151   extra_samples.val=0;
00152   extra_samples.valid = false;
00153   int const ret_extrasamples = TIFFGetField(tif_, TIFFTAG_EXTRASAMPLES, &extra_samples.val, &sample_info);
00154   if (ret_extrasamples && extra_samples.val > 0)
00155     extra_samples.valid = true;
00156 
00157   read_short_tag(tif_,TIFFTAG_FILLORDER, fill_order);
00158   vxl_uint_16* gc=0;
00159   TIFFGetField(tif_,TIFFTAG_GRAYRESPONSECURVE, &gc);
00160   read_short_tag(tif_,TIFFTAG_GRAYRESPONSEUNIT, gray_response_unit);
00161   read_string(tif_,TIFFTAG_HOSTCOMPUTER, host_computer);
00162   read_string(tif_,TIFFTAG_IMAGEDESCRIPTION, image_description);
00163   read_long_tag(tif_,TIFFTAG_IMAGELENGTH, image_length);
00164   read_long_tag(tif_,TIFFTAG_IMAGEWIDTH, image_width);
00165   read_string(tif_,TIFFTAG_MAKE, make);
00166   read_short_tag(tif_,TIFFTAG_MAXSAMPLEVALUE, max_sample_value, 255);
00167   read_short_tag(tif_,TIFFTAG_MINSAMPLEVALUE, min_sample_value, 0);
00168   read_string(tif_,TIFFTAG_MODEL, model);
00169   read_short_tag(tif_,TIFFTAG_SUBFILETYPE, subfile_type);
00170   read_short_tag(tif_,TIFFTAG_ORIENTATION, orientation, 1);
00171   read_short_tag(tif_,TIFFTAG_RESOLUTIONUNIT, resolution_unit);
00172   read_long_tag(tif_,TIFFTAG_ROWSPERSTRIP, rows_per_strip);
00173   read_string(tif_,TIFFTAG_SOFTWARE, software);
00174   read_short_tag(tif_,TIFFTAG_SAMPLEFORMAT, sample_format, 1);
00175   strip_byte_counts_valid = false;
00176   if (rows_per_strip.valid)
00177   {
00178     strip_byte_counts_valid =
00179       TIFFGetField(tif_,TIFFTAG_STRIPBYTECOUNTS , &strip_byte_counts)>0;
00180 #ifdef DEBUG
00181     //      vxl_uint_32 size = strips_per_image()*samples_per_pixel.val;
00182     vxl_uint_32 size = strips_per_image();
00183     for (vxl_uint_32 i = 0; i<size; ++i)
00184       vcl_cout << "SBC[" << i << "]=" << strip_byte_counts[i] << '\n';
00185 #endif
00186   }
00187 
00188   strip_offsets_valid = false;
00189 #ifdef DEBUG
00190   if (rows_per_strip.valid)
00191   {
00192     strip_offsets_valid =
00193       TIFFGetField(tif_, TIFFTAG_STRIPOFFSETS, &strip_offsets)>0;
00194     //      vxl_uint_32 size = strips_per_image()*samples_per_pixel.val;
00195     vxl_uint_32 size = strips_per_image();
00196       for (vxl_uint_32 i = 0; i<size; ++i)
00197       vcl_cout << "SOFF[" << i << "]=" << strip_offsets[i] << '\n';
00198   }
00199 #endif
00200   read_short_tag(tif_,TIFFTAG_THRESHHOLDING, thresholding);
00201 
00202   read_float_tag(tif_, TIFFTAG_XRESOLUTION, x_resolution, x_resolution_valid);
00203   read_float_tag(tif_, TIFFTAG_YRESOLUTION, y_resolution, y_resolution_valid);
00204 
00205   read_long_tag(tif_, TIFFTAG_TILEWIDTH, tile_width, 0);
00206   read_long_tag(tif_, TIFFTAG_TILELENGTH, tile_length, 0);
00207 
00208   tile_offsets_valid = false;
00209 
00210 #ifdef DEBUG
00211   if (tile_width.valid&&tile_length.valid)
00212   {
00213     tile_offsets_valid =
00214       TIFFGetField(tif_, TIFFTAG_TILEOFFSETS, &tile_offsets)>0;
00215     //      vxl_uint_32 size = tiles_per_image()*samples_per_pixel.val;
00216     vxl_uint_32 size = tiles_per_image();
00217     for (vxl_uint_32 i = 0; i<size; ++i)
00218       vcl_cout << "TOFF[" << i << "]=" << tile_offsets[i] << '\n';
00219   }
00220 #endif
00221 
00222   tile_byte_counts_valid = false;
00223 #ifdef DEBUG
00224   if (tile_width.valid&&tile_length.valid)
00225   {
00226     tile_byte_counts_valid =
00227      TIFFGetField(tif_, TIFFTAG_TILEBYTECOUNTS, &tile_byte_counts)>0;
00228     //      vxl_uint_32 size = tiles_per_image()*samples_per_pixel.val;
00229     vxl_uint_32 size = tiles_per_image();
00230     for (vxl_uint_32 i = 0; i<size; ++i)
00231       vcl_cout << "TBC[" << i << "]=" << tile_byte_counts[i] << '\n';
00232   }
00233 #endif
00234   return this->compute_pixel_format();
00235   // int success = TIFFReadDirectory(tif_);
00236 }
00237 
00238 // the number of separate sample planes defined by the tiff file
00239 // for example a multi-band image.
00240 unsigned vil_tiff_header::n_separate_image_planes() const
00241 {
00242   if (planar_config.valid)
00243   {
00244     if (planar_config.val == PLANARCONFIG_SEPARATE)
00245       return samples_per_pixel.val;
00246     else if (planar_config.val == PLANARCONFIG_CONTIG)
00247       return 1;
00248     else
00249       return 0;
00250   }
00251   else
00252     return 0;
00253 }
00254 
00255 bool vil_tiff_header::is_tiled() const
00256 {
00257   return is_tiled_flag ||
00258     (tile_width.valid&&tile_length.valid&&tile_width.val>0&&tile_length.val>0);
00259 }
00260 
00261 bool vil_tiff_header::is_striped() const
00262 {
00263   // Assume if rows_per_strip is not provided, assume it is infinity,
00264   // and that the image is striped.
00265   return (rows_per_strip.valid && rows_per_strip.val > 0) || !rows_per_strip.valid;
00266 }
00267 
00268 #if HAS_GEOTIFF
00269 bool vil_tiff_header::is_GEOTIFF() const
00270 {
00271   short *data;
00272   short count;
00273   return TIFFGetField(tif_, 34735 /*TIFFTAG_GEOKEYDIRECTORY*/, &count, &data)!=0;
00274 }
00275 #endif
00276 
00277 unsigned vil_tiff_header::encoded_bytes_per_block() const
00278 {
00279   if (is_tiled())
00280     return static_cast<unsigned>(bytes_per_tile());
00281   else if (is_striped())
00282     return static_cast<unsigned>(bytes_per_strip());
00283   else
00284     return 0;
00285 }
00286 
00287 // the number of samples in a scan line
00288 unsigned vil_tiff_header::samples_per_line() const
00289 {
00290   if (image_width.valid)
00291     return samples_per_pixel.val*image_width.val;
00292   return 0;
00293 }
00294 
00295 vxl_uint_32 vil_tiff_header::bytes_per_line() const
00296 {
00297   unsigned nsamp = this->samples_per_line();
00298   unsigned bits_per_line = bits_per_sample.val*nsamp;
00299   return (bits_per_line + 7)/8;
00300 }
00301 
00302 vxl_uint_32 vil_tiff_header::actual_bytes_per_line() const
00303 {
00304     return TIFFScanlineSize(tif_);
00305 }
00306 
00307 vxl_uint_32 vil_tiff_header::rows_in_strip() const
00308 {
00309   if (rows_per_strip.valid&&image_length.valid)
00310   {
00311     vxl_uint_32 rps = rows_per_strip.val;
00312     if (rps>image_length.val)
00313       return image_length.val;
00314     return rps;
00315   }
00316   else if (image_length.valid)
00317   {
00318     return image_length.val;
00319   }
00320   return 0;
00321 }
00322 
00323 //this value can vary from one strip to the next
00324 vxl_uint_32 vil_tiff_header::
00325 actual_bytes_per_strip(const vxl_uint_32 strip_index) const
00326 {
00327   if (strip_byte_counts_valid)
00328   return strip_byte_counts[strip_index];
00329   return 0;
00330 }
00331 
00332 //the theoretical amount needed
00333 vxl_uint_32 vil_tiff_header::bytes_per_strip() const
00334 {
00335   return rows_in_strip()*bytes_per_line();
00336 }
00337 
00338 vxl_uint_32 vil_tiff_header::bytes_per_tile() const
00339 {
00340   return TIFFTileSize(tif_);
00341 }
00342 
00343 //The number of images in the tiff file
00344 vxl_uint_16  vil_tiff_header::n_images()
00345 {
00346   return TIFFNumberOfDirectories(tif_);
00347 }
00348 
00349 //assemble the information to define the vil_pixel_format
00350 //return false if the format cannot be handled
00351 bool vil_tiff_header::compute_pixel_format()
00352 {
00353   //also need sample_format.valid but use default (1) for images that don't have it
00354   // -GY- use default (1) for images that do not have SamplesPerPixel tag
00355   if (!(bits_per_sample.valid) || /*!(samples_per_pixel.valid) ||*/
00356       !(planar_config.valid) || !photometric.valid           )
00357   {
00358     pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00359     return false;
00360   }
00361 
00362   vxl_uint_16 b = bits_per_sample.val;
00363   vxl_uint_16 bbs = bytes_per_sample();
00364   nplanes = 1;
00365   //Let's do the easy case first -- scalar pixels but various types
00366   if (samples_per_pixel.val==1)
00367   {
00368     //handle sample formats (unsigned, signed, float, double)
00369     switch (sample_format.val)
00370     {
00371       case 2: //2s complement signed
00372         switch (b)
00373         {
00374           case 8:
00375             pix_fmt = VIL_PIXEL_FORMAT_SBYTE;
00376             return true;
00377           case 16:
00378             pix_fmt = VIL_PIXEL_FORMAT_INT_16;
00379             return true;
00380           case 32:
00381             pix_fmt = VIL_PIXEL_FORMAT_INT_32;
00382             return false;
00383           default: //other bit sizes don't make sense
00384             pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00385             return false;
00386         }
00387       case 3: // floating point
00388         switch (bbs)
00389         {
00390           case (sizeof(float)):
00391             pix_fmt = VIL_PIXEL_FORMAT_FLOAT;
00392             return true;
00393           case (sizeof(double)):
00394             pix_fmt = VIL_PIXEL_FORMAT_DOUBLE;
00395             return true;
00396           default: //other bit sizes don't make sense
00397             pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00398             return false;
00399         }
00400       case 4: //undefined format
00401       case 1: //unsigned values
00402       default:
00403         if (b==1){
00404           pix_fmt = VIL_PIXEL_FORMAT_BOOL;
00405           return true;}
00406         else
00407           switch (bbs)
00408           {
00409            case 1:
00410             pix_fmt = VIL_PIXEL_FORMAT_BYTE;
00411             return true;
00412            case 2:
00413             pix_fmt = VIL_PIXEL_FORMAT_UINT_16;
00414             return true;
00415            case 3:
00416            case 4:
00417             pix_fmt = VIL_PIXEL_FORMAT_UINT_32;
00418             return true;
00419            default:
00420             pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00421             return true;
00422           }
00423     }
00424   }
00425 
00426   // The next easiest case is palette images
00427   // vil doesn't currently support color maps so need to convert to
00428   // regular three component RGB image (LATER)
00429   if (samples_per_pixel.val==1 && photometric.val==PHOTOMETRIC_RGB &&
00430       sample_format.val == 1) //only support unsigned
00431     switch (bbs)
00432     {
00433       case 1:
00434         pix_fmt = VIL_PIXEL_FORMAT_BYTE;
00435         nplanes = 3;
00436         return false;
00437       case 2:
00438         pix_fmt = VIL_PIXEL_FORMAT_UINT_16;
00439         nplanes = 4;
00440         return false;
00441       default://other palette dynamic ranges don't make sense
00442         pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00443         return false;
00444     }
00445   // Now for regular color images
00446   // handle sample formats (unsigned, signed, float, double)
00447   // vil normally doesn't directly express these interleaved formats but
00448   // pretends the samples are in different planes.
00449   // The current implementation can't handle planar_config ==2, which is
00450   // separate color bands.
00451   vxl_uint_16 s = samples_per_pixel.val;
00452   if (samples_per_pixel.val>1 && photometric.val==2 && planar_config.val == 1 )
00453   {
00454     switch (sample_format.val)
00455     {
00456       case 1: //unsigned values
00457         switch (b)
00458         {
00459           case 8:
00460             pix_fmt = VIL_PIXEL_FORMAT_BYTE;
00461             switch (s)
00462             {
00463               case 3:
00464                 nplanes = 3;
00465                 return true;
00466               case 4:
00467                 nplanes = 4;
00468                 return true;
00469               default:
00470                 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00471                 return false;
00472             }
00473           case 16:
00474             pix_fmt = VIL_PIXEL_FORMAT_UINT_16;
00475             switch (s)
00476             {
00477               case 3:
00478                 nplanes = 3;
00479                 return true;
00480               case 4:
00481                 nplanes = 4;
00482                 return true;
00483               default:
00484                 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00485                 return false;
00486             }
00487           case 32:
00488             pix_fmt = VIL_PIXEL_FORMAT_UINT_32;
00489             switch (s)
00490             {
00491               case 3:
00492                 nplanes = 3;
00493                 return true;
00494               case 4:
00495                 nplanes = 4;
00496                 return false;
00497               default:
00498                 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00499                 return false;
00500             }
00501           default: //other dynamic ranges, e.g. 12 bits/sample
00502             switch (bbs)
00503             {
00504               case 1:
00505                 pix_fmt = VIL_PIXEL_FORMAT_RGB_BYTE;
00506                 switch (s)
00507                 {
00508                   case 3:
00509                     nplanes = 3;
00510                     return true;
00511                   case 4:
00512                     nplanes = 4;
00513                     return false;
00514                   default:
00515                     pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00516                     return false;
00517                 }
00518               case 2:
00519                 pix_fmt = VIL_PIXEL_FORMAT_UINT_16;
00520                 switch (s)
00521                 {
00522                   case 3:
00523                     nplanes = 3;
00524                     return true;
00525                   case 4:
00526                     nplanes = 4;
00527                     return true;
00528                   default:
00529                     pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00530                     return false;
00531                 }
00532               case 4:
00533                 pix_fmt = VIL_PIXEL_FORMAT_UINT_32;
00534                 switch (s)
00535                 {
00536                   case 3:
00537                     nplanes = 3;
00538                     return true;
00539                   case 4:
00540                     nplanes = 4;
00541                     return false;
00542                   default:
00543                     pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00544                     return false;
00545                 }
00546               default:
00547                 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00548                 return false;
00549             }
00550         }
00551       case 2: //do signed color images make sense?
00552         pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00553         return false;
00554 
00555       case 3: // do floating point color images make sense?
00556         pix_fmt = VIL_PIXEL_FORMAT_FLOAT; // DEC changed from vil_pixel_format_unknown
00557         nplanes = s; // DEC
00558         return true; // DEC changed from false
00559       case 4: //undefined format
00560       default:
00561         pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00562         return false;
00563     }
00564   }
00565   //Separate TIFF transparency mask - not handled
00566   if (photometric.val==PHOTOMETRIC_MASK)
00567   {
00568     pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00569     return false;
00570   }
00571 
00572   //TIFF color separations - not handled
00573   if (photometric.val==PHOTOMETRIC_SEPARATED)
00574   {
00575     pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00576     return false;
00577   }
00578 
00579   pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00580   return false;
00581 }
00582 
00583 //Returns false if the pixel format cannot be written
00584 bool vil_tiff_header::parse_pixel_format(vil_pixel_format const& fmt)
00585 {
00586   //Check for supported types
00587   sample_format.val = 1; sample_format.valid = true;
00588   switch ( fmt )
00589   {
00590     case VIL_PIXEL_FORMAT_BOOL:
00591       bits_per_sample.val = 1; bits_per_sample.valid = true;
00592       return true;
00593     case VIL_PIXEL_FORMAT_BYTE:
00594       bits_per_sample.val = 8; bits_per_sample.valid = true;
00595       return true;
00596     case VIL_PIXEL_FORMAT_UINT_16:
00597       bits_per_sample.val = 16; bits_per_sample.valid = true;
00598       return true;
00599     case VIL_PIXEL_FORMAT_UINT_32:
00600       bits_per_sample.val = 32; bits_per_sample.valid = true;
00601       return true;
00602     case VIL_PIXEL_FORMAT_FLOAT:
00603       bits_per_sample.val = 8*sizeof(float); bits_per_sample.valid = true;
00604       sample_format.val = 3;
00605       return true;
00606     case VIL_PIXEL_FORMAT_DOUBLE:
00607       bits_per_sample.val = 8*sizeof(double); bits_per_sample.valid = true;
00608       sample_format.val = 3;
00609       return true;
00610     default:
00611       break;
00612   }
00613   return false;
00614 }
00615 
00616 //Setup the required header information in preparation for writing to
00617 //the tiff file header
00618 bool vil_tiff_header::set_header(unsigned ni, unsigned nj, unsigned nplns,
00619                                  vil_pixel_format const& fmt,
00620                                  const unsigned size_block_i,
00621                                  const unsigned size_block_j)
00622 {
00623   //also need machine endian
00624 #if VXL_BIG_ENDIAN
00625     machine_is_big_endian_ = true;
00626 #else
00627     machine_is_big_endian_ = false;
00628 #endif
00629     //write file with same endian state as the machine
00630     file_is_big_endian_ = machine_is_big_endian_;
00631   pix_fmt = fmt;
00632   if (!this->parse_pixel_format(fmt))
00633     return false;
00634   nplanes = nplns;
00635   //check for color type
00636   photometric.valid = true;
00637   switch ( nplanes )
00638   {
00639     case 1:
00640     case 2:
00641       photometric.val = 1;
00642       break;
00643     case 3:
00644     case 4:
00645       photometric.val = 2;
00646       break;
00647     default:
00648       return false;
00649   }
00650   image_length.val = nj; image_length.valid = true;
00651   image_width.val = ni; image_width.valid = true;
00652   if (size_block_i>0&&size_block_j>0)
00653   {
00654     is_tiled_flag = true;
00655     tile_width.val = size_block_i; tile_width.valid = true;
00656     tile_length.val = size_block_j; tile_length.valid = true;
00657   }
00658   else
00659   {
00660     is_tiled_flag = false;
00661     //Check for default -- one scanline per row
00662     unsigned n_rows = size_block_j;
00663     if (n_rows == 0)
00664       n_rows = 1u;
00665     rows_per_strip.val = n_rows; rows_per_strip.valid = true;
00666   }
00667   samples_per_pixel.val = nplanes; samples_per_pixel.valid=true;
00668   // Can't handle separate color planes
00669   planar_config.val = 1; planar_config.valid = true;
00670   // The sensible way ..
00671   orientation.val = ORIENTATION_TOPLEFT; orientation.valid = true;
00672   software = "http://vxl.sourceforge.net/  vil image library";
00673   return true;
00674 }
00675 
00676 // Constructor - writes the necessary header information to the open tiff file
00677 vil_tiff_header::
00678 vil_tiff_header(TIFF* tif, const unsigned ni, const unsigned nj,
00679                 const unsigned nplanes, vil_pixel_format const& fmt,
00680                 const unsigned size_block_i, const unsigned size_block_j)
00681 {
00682   tif_ = tif;
00683 
00684   format_supported =
00685     this->set_header(ni, nj, nplanes, fmt, size_block_i, size_block_j);
00686   if (!format_supported)
00687     return;
00688   write_short_tag(tif_,TIFFTAG_PHOTOMETRIC, photometric);
00689   write_short_tag(tif_,TIFFTAG_PLANARCONFIG, planar_config);
00690   write_short_tag(tif_,TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel);
00691   write_short_tag(tif_,TIFFTAG_BITSPERSAMPLE, bits_per_sample);
00692   write_string(tif_, TIFFTAG_DATETIME, date_and_time());
00693   write_long_tag(tif_,TIFFTAG_IMAGELENGTH, image_length);
00694   write_long_tag(tif_,TIFFTAG_IMAGEWIDTH, image_width);
00695   write_short_tag(tif_,TIFFTAG_ORIENTATION, orientation);
00696   write_long_tag(tif_,TIFFTAG_ROWSPERSTRIP, rows_per_strip);
00697   write_string(tif_, TIFFTAG_SOFTWARE, software);
00698   write_short_tag(tif_,TIFFTAG_SAMPLEFORMAT, sample_format);
00699   write_long_tag(tif_, TIFFTAG_TILEWIDTH, tile_width);
00700   write_long_tag(tif_, TIFFTAG_TILELENGTH, tile_length);
00701 #if 1  // Handle Alpha channel, assuming it is the last channel
00702   if (nplanes == 2 || nplanes == 4)
00703   {
00704     //extra_samples.val = 1;
00705     //extra_samples.valid = true;
00706     vxl_uint_32 num_extra_samples = 1;
00707     vxl_uint_16 extra_sample_values[] = { EXTRASAMPLE_ASSOCALPHA/*1*/ };  // Indicate Associated Alpha Data
00708     TIFFSetField(tif_, TIFFTAG_EXTRASAMPLES, num_extra_samples, extra_sample_values);
00709   }
00710 #endif
00711   //initialize other flags to false
00712   color_map_valid = false;
00713   grey_response_curve_valid = false;
00714   strip_byte_counts_valid = false;
00715   strip_offsets_valid = false;
00716   tile_offsets_valid = false;
00717   tile_byte_counts_valid = false;
00718 }