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