vil_tiff_header.cxx
Go to the documentation of this file.
1 #include <iostream>
2 #include <cstdio>
3 #include <ctime>
4 #include "vil_tiff_header.h"
5 #ifdef _MSC_VER
6 # include <vcl_msvc_warnings.h>
7 #endif
8 
9 #if HAS_GEOTIFF
11 #endif
12 
13 static std::string date_and_time()
14 {
15  std::time_t clock;
16  struct std::tm *t_m;
17  clock = std::time(nullptr);
18  t_m = std::localtime(&clock);
19  char tmp[20];
20  char datetime[20];
21  std::strftime(tmp,sizeof(datetime),"%Y-%m-%d %H:%M:%S",t_m);
22  // changed from "%c", to make it generic, size=19, and avoid compiler warning
23  std::sprintf(datetime,"%19s",tmp);
24  return std::string(datetime);
25 }
26 
27 static void read_string(TIFF* tif, ttag_t tag, std::string& stag, std::string const& deflt = "not_defined")
28 {
29  char* adr = nullptr;
30  TIFFGetField(tif, tag, &adr);
31  if (adr)
32  stag = std::string(adr);
33  else
34  stag = deflt;
35 }
36 
37 static void read_short_tag(TIFF* tif, ttag_t tag, ushort_tag& utag, vxl_uint_16 deflt =0)
38 {
39  utag.valid = TIFFGetField(tif, tag, &(utag.val))>0;
40  if (!utag.valid)
41  utag.val = deflt;
42 }
43 
44 static void read_long_tag(TIFF* tif, ttag_t tag, ulong_tag& utag, vxl_uint_32 deflt = 0)
45 {
46  utag.valid = TIFFGetField(tif, tag, &(utag.val))>0;
47  if (!utag.valid)
48  utag.val = deflt;
49 }
50 
51 static void read_float_tag(TIFF* tif, ttag_t tag, float& val, bool& valid, float deflt = 0)
52 {
53  valid = TIFFGetField(tif, tag, &(val))>0;
54  if (!valid)
55  val = deflt;
56 }
57 
58 #if 0 // unused static function
59 //assumes array is resized properly
60 static bool read_long_array(TIFF* tif, ttag_t tag,
61  std::vector<vxl_uint_32>& array)
62 {
63  vxl_uint_32 * a;
64  if (TIFFGetField(tif, tag, &a))
65  {
66  for (vxl_uint_32 i=0; i<array.size(); ++i) { array[i]=a[i]; }
67  return true;
68  }
69  else return false;
70 }
71 #endif // unused static function
72 
73 static void write_short_tag(TIFF* tif, ttag_t tag, ushort_tag const& ustag)
74 {
75  if (ustag.valid)
76  TIFFSetField(tif, tag, ustag.val);
77 }
78 
79 static void write_long_tag(TIFF* tif, ttag_t tag, ulong_tag const& ultag)
80 {
81  if (ultag.valid)
82  TIFFSetField(tif, tag, ultag.val);
83 }
84 
85 #if 0 // not currently used...
86 static void write_float_tag(TIFF* tif, ttag_t tag, float const val, bool const valid)
87 {
88  if (valid)
89  TIFFSetField(tif, tag, val);
90 }
91 #endif
92 
93 static void write_string(TIFF* tif, ttag_t tag, std::string const& stag)
94 {
95  TIFFSetField(tif, tag, stag.c_str());
96 }
97 
98 
100 {
101  //DEBUG
102 #ifdef DEBUG
103  std::cout << date_and_time() << '\n';
104 #endif
105  //====
106  //Determine the endian state of the file and machine
107  file_is_big_endian_ = TIFFIsByteSwapped(tif_)>0;
108 
109  //also need machine endian
110 #if VXL_BIG_ENDIAN
111  machine_is_big_endian_ = true;
112 #else
113  machine_is_big_endian_ = false;
114 #endif
115  //the following group must be read first since they
116  //dictate subsequent tag structures
117  ///-----------------------------------------------///
118  read_short_tag(tif_,TIFFTAG_PHOTOMETRIC, photometric);
119  read_short_tag(tif_,TIFFTAG_PLANARCONFIG, planar_config, 1);
120  read_short_tag(tif_,TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel, 1);
121  read_short_tag(tif_,TIFFTAG_BITSPERSAMPLE, bits_per_sample, 8);
122  is_tiled_flag = TIFFIsTiled(tif_)>0;
123  ///-----------------------------------------------///
124  read_string(tif_,TIFFTAG_ARTIST , artist);
125  read_short_tag(tif_,TIFFTAG_CELLLENGTH, cell_length);
126  read_short_tag(tif_,TIFFTAG_CELLWIDTH, cell_width);
127  color_map_valid = false;
128  if (bits_per_sample.valid &&
129  photometric.valid &&
130  photometric.val == PHOTOMETRIC_PALETTE)
131  {
132  vxl_uint_16* cm[3];
133  TIFFGetField(tif_,TIFFTAG_COLORMAP, &cm[0], &cm[1], &cm[2]);
134  unsigned size = 1<<bits_per_sample.val;
135  color_map.resize(size);
136  for (unsigned i = 0; i<size; ++i)
137  {
138  std::vector<vxl_uint_16> rgb(3);
139  rgb[0]=cm[0][i]; rgb[1]=cm[1][i]; rgb[2]=cm[2][i];
140  color_map[i] = rgb;
141 #ifdef DEBUG
142  std::cout << "RGB[" << i << "]=(" << rgb[0] << ' ' << rgb[1] << ' ' << rgb[2] << ")\n";
143 #endif
144  }
145  color_map_valid = true;
146  }
147  read_short_tag(tif_,TIFFTAG_COMPRESSION, compression);
148  read_string(tif_,TIFFTAG_COPYRIGHT, copyright);
149  read_string(tif_,TIFFTAG_DATETIME,date_time);
150 
151  // EXTRASAMPLES tag requires two input arguments, which is different
152  // from other 16bit values.
153  vxl_uint_16* sample_info=nullptr;
154  extra_samples.val=0;
155  extra_samples.valid = false;
156  int const ret_extrasamples = TIFFGetField(tif_, TIFFTAG_EXTRASAMPLES, &extra_samples.val, &sample_info);
157  if (ret_extrasamples && extra_samples.val > 0)
158  extra_samples.valid = true;
159 
160  read_short_tag(tif_,TIFFTAG_FILLORDER, fill_order);
161  vxl_uint_16* gc=nullptr;
162  TIFFGetField(tif_,TIFFTAG_GRAYRESPONSECURVE, &gc);
163  read_short_tag(tif_,TIFFTAG_GRAYRESPONSEUNIT, gray_response_unit);
164  read_string(tif_,TIFFTAG_HOSTCOMPUTER, host_computer);
165  read_string(tif_,TIFFTAG_IMAGEDESCRIPTION, image_description);
166  read_long_tag(tif_,TIFFTAG_IMAGELENGTH, image_length);
167  read_long_tag(tif_,TIFFTAG_IMAGEWIDTH, image_width);
168  read_string(tif_,TIFFTAG_MAKE, make);
169  read_short_tag(tif_,TIFFTAG_MAXSAMPLEVALUE, max_sample_value, 255);
170  read_short_tag(tif_,TIFFTAG_MINSAMPLEVALUE, min_sample_value, 0);
171  read_string(tif_,TIFFTAG_MODEL, model);
172  read_short_tag(tif_,TIFFTAG_SUBFILETYPE, subfile_type);
173  read_short_tag(tif_,TIFFTAG_ORIENTATION, orientation, 1);
174  read_short_tag(tif_,TIFFTAG_RESOLUTIONUNIT, resolution_unit);
175  read_long_tag(tif_,TIFFTAG_ROWSPERSTRIP, rows_per_strip);
176  read_string(tif_,TIFFTAG_SOFTWARE, software);
177  read_short_tag(tif_,TIFFTAG_SAMPLEFORMAT, sample_format, 1);
178  strip_byte_counts_valid = false;
179  if (rows_per_strip.valid)
180  {
182  TIFFGetField(tif_,TIFFTAG_STRIPBYTECOUNTS , &strip_byte_counts)>0;
183 #ifdef DEBUG
184  // vxl_uint_32 size = strips_per_image()*samples_per_pixel.val;
185  vxl_uint_32 size = strips_per_image();
186  for (vxl_uint_32 i = 0; i<size; ++i)
187  std::cout << "SBC[" << i << "]=" << strip_byte_counts[i] << '\n';
188 #endif
189  }
190 
191  strip_offsets_valid = false;
192 #ifdef DEBUG
193  if (rows_per_strip.valid)
194  {
196  TIFFGetField(tif_, TIFFTAG_STRIPOFFSETS, &strip_offsets)>0;
197  // vxl_uint_32 size = strips_per_image()*samples_per_pixel.val;
198  vxl_uint_32 size = strips_per_image();
199  for (vxl_uint_32 i = 0; i<size; ++i)
200  std::cout << "SOFF[" << i << "]=" << strip_offsets[i] << '\n';
201  }
202 #endif
203  read_short_tag(tif_,TIFFTAG_THRESHHOLDING, thresholding);
204 
205  read_float_tag(tif_, TIFFTAG_XRESOLUTION, x_resolution, x_resolution_valid);
206  read_float_tag(tif_, TIFFTAG_YRESOLUTION, y_resolution, y_resolution_valid);
207 
208  read_long_tag(tif_, TIFFTAG_TILEWIDTH, tile_width, 0);
209  read_long_tag(tif_, TIFFTAG_TILELENGTH, tile_length, 0);
210 
211  tile_offsets_valid = false;
212 
213 #ifdef DEBUG
215  {
217  TIFFGetField(tif_, TIFFTAG_TILEOFFSETS, &tile_offsets)>0;
218  // vxl_uint_32 size = tiles_per_image()*samples_per_pixel.val;
219  vxl_uint_32 size = tiles_per_image();
220  for (vxl_uint_32 i = 0; i<size; ++i)
221  std::cout << "TOFF[" << i << "]=" << tile_offsets[i] << '\n';
222  }
223 #endif
224 
225  tile_byte_counts_valid = false;
226 #ifdef DEBUG
228  {
230  TIFFGetField(tif_, TIFFTAG_TILEBYTECOUNTS, &tile_byte_counts)>0;
231  // vxl_uint_32 size = tiles_per_image()*samples_per_pixel.val;
232  vxl_uint_32 size = tiles_per_image();
233  for (vxl_uint_32 i = 0; i<size; ++i)
234  std::cout << "TBC[" << i << "]=" << tile_byte_counts[i] << '\n';
235  }
236 #endif
237  return this->compute_pixel_format();
238  // int success = TIFFReadDirectory(tif_);
239 }
240 
241 // the number of separate sample planes defined by the tiff file
242 // for example a multi-band image.
244 {
245  if (planar_config.valid)
246  {
247  if (planar_config.val == PLANARCONFIG_SEPARATE)
248  return samples_per_pixel.val;
249  else if (planar_config.val == PLANARCONFIG_CONTIG)
250  return 1;
251  else
252  return 0;
253  }
254  else
255  return 0;
256 }
257 
259 {
260  return is_tiled_flag ||
262 }
263 
265 {
266  // Assume if rows_per_strip is not provided, assume it is infinity,
267  // and that the image is striped.
269 }
270 
271 #if HAS_GEOTIFF
272 bool vil_tiff_header::is_GEOTIFF() const
273 {
274  short *data;
275  short count;
276  return TIFFGetField(tif_, 34735 /*TIFFTAG_GEOKEYDIRECTORY*/, &count, &data)!=0;
277 }
278 #endif
279 
281 {
282  if (is_tiled())
283  return static_cast<unsigned>(bytes_per_tile());
284  else if (is_striped())
285  return static_cast<unsigned>(bytes_per_strip());
286  else
287  return 0;
288 }
289 
290 // the number of samples in a scan line
292 {
293  if (image_width.valid)
295  return 0;
296 }
297 
299 {
300  unsigned nsamp = this->samples_per_line();
301  unsigned bits_per_line = bits_per_sample.val*nsamp;
302  return (bits_per_line + 7)/8;
303 }
304 
306 {
307  return TIFFScanlineSize(tif_);
308 }
309 
311 {
313  {
314  vxl_uint_32 rps = rows_per_strip.val;
315  if (rps>image_length.val)
316  return image_length.val;
317  return rps;
318  }
319  else if (image_length.valid)
320  {
321  return image_length.val;
322  }
323  return 0;
324 }
325 
326 //this value can vary from one strip to the next
327 vxl_uint_32 vil_tiff_header::
328 actual_bytes_per_strip(const vxl_uint_32 strip_index) const
329 {
331  return strip_byte_counts[strip_index];
332  return 0;
333 }
334 
335 //the theoretical amount needed
337 {
338  return rows_in_strip()*bytes_per_line();
339 }
340 
342 {
343  return TIFFTileSize(tif_);
344 }
345 
346 //The number of images in the tiff file
348 {
349  return TIFFNumberOfDirectories(tif_);
350 }
351 
352 //assemble the information to define the vil_pixel_format
353 //return false if the format cannot be handled
355 {
356  //also need sample_format.valid but use default (1) for images that don't have it
357  // -GY- use default (1) for images that do not have SamplesPerPixel tag
358  if (!(bits_per_sample.valid) || /*!(samples_per_pixel.valid) ||*/
360  {
362  return false;
363  }
364 
365  vxl_uint_16 const b = bits_per_sample.val;
366  vxl_uint_16 const bbs = bytes_per_sample();
367  nplanes = 1;
368  //Let's do the easy case first -- scalar pixels but various types
369  if (samples_per_pixel.val==1)
370  {
371  //handle sample formats (unsigned, signed, float, double)
372  switch (sample_format.val)
373  {
374  case 2: //2s complement signed
375  switch (b)
376  {
377  case 8:
379  return true;
380  case 16:
382  return true;
383  case 32:
385  return true;
386  default: //other bit sizes don't make sense
388  return false;
389  }
390  case 3: // floating point
391  switch (bbs)
392  {
393  case (sizeof(float)):
395  return true;
396  case (sizeof(double)):
398  return true;
399  default: //other bit sizes don't make sense
401  return false;
402  }
403  case 4: //undefined format
404  case 1: //unsigned values
405  default:
406  // One special case is palette images
407  // vil doesn't currently support color maps so need to convert to
408  // regular three component RGB image (LATER)
409  if (photometric.val==PHOTOMETRIC_RGB /*&& samples_per_pixel.val==1 &&
410  sample_format.val == 1*/) //only support unsigned
411  switch (bbs)
412  {
413  case 1:
415  nplanes = 3;
416  return false;
417  case 2:
419  nplanes = 4;
420  return false;
421  default://other palette dynamic ranges don't make sense
423  return false;
424  }
425 
426  if (b==1){
428  return true;}
429  else
430  switch (bbs)
431  {
432  case 1:
434  return true;
435  case 2:
437  return true;
438  case 3:
439  case 4:
441  return true;
442  default:
444  return false;
445  }
446  }
447  }
448 
449  // Two-channel case --- greyscale+alpha
450  else if (samples_per_pixel.val==2)
451  {
452  nplanes = 2;
453  switch (sample_format.val)
454  {
455  case 1: //unsigned values
456  switch (b)
457  {
458  case 8:
460  return true;
461  case 16:
463  return true;
464  case 32:
466  return true;
467  default: //other dynamic ranges, e.g. 12 bits/sample
469  return false;
470  }
471  default:
472  // Need to handle other signed values??
473  return false;
474  }
475  }
476  // Now for regular color images
477  // handle sample formats (unsigned, signed, float, double)
478  // vil normally doesn't directly express these interleaved formats but
479  // pretends the samples are in different planes.
480  // The current implementation can't handle planar_config ==2, which is
481  // separate color bands.
482  else if (/*samples_per_pixel.val>1 &&*/ photometric.val==PHOTOMETRIC_RGB && planar_config.val == 1 )
483  {
484  vxl_uint_16 const s = samples_per_pixel.val;
485  switch (sample_format.val)
486  {
487  case 1: //unsigned values
488  switch (b)
489  {
490  case 8:
492  switch (s)
493  {
494  case 3:
495  nplanes = 3;
496  return true;
497  case 4:{
498  nplanes = 4;
501  return true;
502  }
503  default:
505  return false;
506  }
507  case 16:
509  switch (s)
510  {
511  case 3:
512  nplanes = 3;
513  return true;
514  case 4:{
515  nplanes = 4;
516  // can be RBGA if extra samples and
517  // so shouldn't be treated as a simple multiband image
520  return true;
521  }
522  default:
524  return false;
525  }
526  case 32:
528  switch (s)
529  {
530  case 3:
531  nplanes = 3;
532  return true;
533  case 4:
534  nplanes = 4;
535  return false;
536  default:
538  return false;
539  }
540  default: //other dynamic ranges, e.g. 12 bits/sample
541  switch (bbs)
542  {
543  case 1:
545  switch (s)
546  {
547  case 3:
548  nplanes = 3;
549  return true;
550  case 4:
551  nplanes = 4;
552  return false;
553  default:
555  return false;
556  }
557  case 2:
559  switch (s)
560  {
561  case 3:
562  nplanes = 3;
563  return true;
564  case 4:
565  nplanes = 4;
566  return true;
567  default:
569  return false;
570  }
571  case 4:
573  switch (s)
574  {
575  case 3:
576  nplanes = 3;
577  return true;
578  case 4:
579  nplanes = 4;
580  return false;
581  default:
583  return false;
584  }
585  default:
587  return false;
588  }
589  }
590  case 2: //do signed color images make sense?
592  return false;
593 
594  case 3: // do floating point color images make sense?
595  pix_fmt = VIL_PIXEL_FORMAT_FLOAT; // DEC changed from vil_pixel_format_unknown
596  nplanes = s; // DEC
597  return true; // DEC changed from false
598  case 4: //undefined format
599  default:
601  return false;
602  }
603  }else if(planar_config.val == 2){//TIFF multiband images
604  // only handle unsigned pixel types for planar config == 2
605  if(sample_format.val != 1){
607  return false;
608  }
609  vxl_uint_16 const s = samples_per_pixel.val;
610  switch (b){
611  case 16://only handle 2 byte pixels for now
613  switch (s)
614  {
615  case 3:
616  nplanes = 3;
617  return true;
618  case 4:{
619  nplanes = 4;
620  return true;
621  }
622  case 8:{
623  nplanes = 8;
624  return true;
625  }
626  default:
628  return false;
629  }
630  }
631  }
632  //Separate TIFF transparency mask - not handled
633  if (photometric.val==PHOTOMETRIC_MASK)
634  {
636  return false;
637  }
638 
639  //TIFF color separations - not handled
640  if (photometric.val==PHOTOMETRIC_SEPARATED)
641  {
643  return false;
644  }
645 
647  return false;
648 }
649 
650 //Returns false if the pixel format cannot be written
652 {
653  //Check for supported types
654  sample_format.val = 1; sample_format.valid = true;
655  switch ( fmt )
656  {
659  return true;
662  return true;
665  return true;
668  return true;
670  bits_per_sample.val = 8*sizeof(float); bits_per_sample.valid = true;
671  sample_format.val = 3;
672  return true;
674  bits_per_sample.val = 8*sizeof(double); bits_per_sample.valid = true;
675  sample_format.val = 3;
676  return true;
677  default:
678  break;
679  }
680  return false;
681 }
682 
683 //Setup the required header information in preparation for writing to
684 //the tiff file header
685 bool vil_tiff_header::set_header(unsigned ni, unsigned nj, unsigned nplns,
686  vil_pixel_format const& fmt,
687  const unsigned size_block_i,
688  const unsigned size_block_j)
689 {
690  //also need machine endian
691 #if VXL_BIG_ENDIAN
692  machine_is_big_endian_ = true;
693 #else
694  machine_is_big_endian_ = false;
695 #endif
696  //write file with same endian state as the machine
698  pix_fmt = fmt;
699  if (!this->parse_pixel_format(fmt))
700  return false;
701  nplanes = nplns;
702  //check for color type
703  photometric.valid = true;
704  switch ( nplanes )
705  {
706  case 1:
707  case 2:
708  photometric.val = 1;
709  break;
710  case 3:
711  case 4:
712  photometric.val = 2;
713  break;
714  default:
715  return false;
716  }
717  image_length.val = nj; image_length.valid = true;
718  image_width.val = ni; image_width.valid = true;
719  if (size_block_i>0&&size_block_j>0)
720  {
721  is_tiled_flag = true;
722  tile_width.val = size_block_i; tile_width.valid = true;
723  tile_length.val = size_block_j; tile_length.valid = true;
724  }
725  else
726  {
727  is_tiled_flag = false;
728  //Check for default -- one scanline per row
729  unsigned n_rows = size_block_j;
730  if (n_rows == 0)
731  n_rows = 1u;
732  rows_per_strip.val = n_rows; rows_per_strip.valid = true;
733  }
735  // Can't handle separate color planes
736  planar_config.val = 1; planar_config.valid = true;
737  // The sensible way ..
738  orientation.val = ORIENTATION_TOPLEFT; orientation.valid = true;
739  software = "https://vxl.github.io/ vil image library";
740  return true;
741 }
742 
743 // Constructor - writes the necessary header information to the open tiff file
745 vil_tiff_header(TIFF* tif, const unsigned ni, const unsigned nj,
746  const unsigned nplanes, vil_pixel_format const& fmt,
747  const unsigned size_block_i, const unsigned size_block_j)
748 {
749  tif_ = tif;
750 
752  this->set_header(ni, nj, nplanes, fmt, size_block_i, size_block_j);
753  if (!format_supported)
754  return;
755  write_short_tag(tif_,TIFFTAG_PHOTOMETRIC, photometric);
756  write_short_tag(tif_,TIFFTAG_PLANARCONFIG, planar_config);
757  write_short_tag(tif_,TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel);
758  write_short_tag(tif_,TIFFTAG_BITSPERSAMPLE, bits_per_sample);
759  write_string(tif_, TIFFTAG_DATETIME, date_and_time());
760  write_long_tag(tif_,TIFFTAG_IMAGELENGTH, image_length);
761  write_long_tag(tif_,TIFFTAG_IMAGEWIDTH, image_width);
762  write_short_tag(tif_,TIFFTAG_ORIENTATION, orientation);
763  write_long_tag(tif_,TIFFTAG_ROWSPERSTRIP, rows_per_strip);
764  write_string(tif_, TIFFTAG_SOFTWARE, software);
765  write_short_tag(tif_,TIFFTAG_SAMPLEFORMAT, sample_format);
766  write_long_tag(tif_, TIFFTAG_TILEWIDTH, tile_width);
767  write_long_tag(tif_, TIFFTAG_TILELENGTH, tile_length);
768 #if 1 // Handle Alpha channel, assuming it is the last channel
769  if (nplanes == 2 || nplanes == 4)
770  {
771  //extra_samples.val = 1;
772  //extra_samples.valid = true;
773  vxl_uint_32 num_extra_samples = 1;
774  vxl_uint_16 extra_sample_values[] = { EXTRASAMPLE_ASSOCALPHA/*1*/ }; // Indicate Associated Alpha Data
775  TIFFSetField(tif_, TIFFTAG_EXTRASAMPLES, num_extra_samples, extra_sample_values);
776  }
777 #endif
778  //initialize other flags to false
779  color_map_valid = false;
781  strip_byte_counts_valid = false;
782  strip_offsets_valid = false;
783  tile_offsets_valid = false;
784  tile_byte_counts_valid = false;
785 }
vil_pixel_format
Describes the type of the concrete data.
ushort_tag subfile_type
ulong_tag tile_length
ushort_tag thresholding
vxl_uint_32 bytes_per_line() const
theoretical from samples per line.
vxl_uint_32 tiles_per_image() const
unsigned samples_per_line() const
the number of samples in a block.
std::string copyright
vil_tiff_header(TIFF *tif)
ushort_tag cell_width
unsigned encoded_bytes_per_block() const
the number of encoded bytes in a tile or strip.
ushort_tag extra_samples
ushort_tag orientation
bool format_supported
true if the specified format can be read or written.
ushort_tag compression
vxl_uint_32 strips_per_image() const
ushort_tag sample_format
ushort_tag fill_order
vxl_uint_32 bytes_per_strip() const
vxl_uint_32 actual_bytes_per_strip(const vxl_uint_32 strip_index) const
ulong_tag rows_per_strip
vxl_uint_32 * strip_byte_counts
vxl_uint_32 * tile_byte_counts
bool is_tiled() const
is the image tiled.
vxl_uint_32 rows_in_strip() const
vil_pixel_format pix_fmt
vxl_uint_32 bytes_per_tile() const
ulong_tag tile_width
ulong_tag image_length
std::string host_computer
std::string image_description
vxl_uint_16 n_images()
the number of images in the file.
std::vector< std::vector< vxl_uint_16 > > color_map
ushort_tag gray_response_unit
ushort_tag photometric
bool is_striped() const
is the image striped (one of these must be true or read failed).
bool grey_response_curve_valid
ushort_tag planar_config
std::string software
ushort_tag bits_per_sample
std::string make
vxl_uint_32 val
std::string date_time
vxl_uint_32 actual_bytes_per_line() const
As returned by the TIFF library.
ushort_tag max_sample_value
bool parse_pixel_format(vil_pixel_format const &fmt)
returns false if the format not handled by this writer.
vxl_uint_32 * tile_offsets
ushort_tag samples_per_pixel
bool compute_pixel_format()
returns false if the format not handled by this reader.
vxl_uint_16 val
A header structure for geotiff files.
ushort_tag min_sample_value
std::string model
std::string artist
ushort_tag resolution_unit
vxl_uint_32 * strip_offsets
bool set_header(unsigned ni, unsigned nj, unsigned nplanes, vil_pixel_format const &fmt, const unsigned size_block_i, const unsigned size_block_j)
returns false if the format cannot be written by current version.
vxl_uint_16 bytes_per_sample() const
ulong_tag image_width
A header structure for tiff files.
ushort_tag cell_length
unsigned n_separate_image_planes() const
the actual number of separate image planes in the tiff image.
bool read_header()
read/write mode true for read.