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
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
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
00084 #ifdef DEBUG
00085 vcl_cout << date_and_time() << '\n';
00086 #endif
00087
00088
00089 file_is_big_endian_ = TIFFIsByteSwapped(tif_)>0;
00090
00091
00092 #if VXL_BIG_ENDIAN
00093 machine_is_big_endian_ = true;
00094 #else
00095 machine_is_big_endian_ = false;
00096 #endif
00097
00098
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
00134
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
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
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
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
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
00230 }
00231
00232
00233
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
00258
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 , &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
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
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
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
00338 vxl_uint_16 vil_tiff_header::n_images()
00339 {
00340 return TIFFNumberOfDirectories(tif_);
00341 }
00342
00343
00344
00345 bool vil_tiff_header::compute_pixel_format()
00346 {
00347
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
00359 if (samples_per_pixel.val==1)
00360 {
00361
00362 switch (sample_format.val)
00363 {
00364 case 1:
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:
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:
00398 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00399 return false;
00400 }
00401 case 3:
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:
00411 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00412 return false;
00413 }
00414 case 4:
00415 default:
00416 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00417 return false;
00418 }
00419 }
00420
00421
00422
00423
00424 if (samples_per_pixel.val==1 && photometric.val==PHOTOMETRIC_RGB &&
00425 sample_format.val == 1)
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:
00437 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00438 return false;
00439 }
00440
00441
00442
00443
00444
00445
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:
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:
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:
00547 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00548 return false;
00549
00550 case 3:
00551 pix_fmt = VIL_PIXEL_FORMAT_FLOAT;
00552 nplanes = s;
00553 return true;
00554 case 4:
00555 default:
00556 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00557 return false;
00558 }
00559 }
00560
00561 if (photometric.val==PHOTOMETRIC_MASK)
00562 {
00563 pix_fmt = VIL_PIXEL_FORMAT_UNKNOWN;
00564 return false;
00565 }
00566
00567
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
00579 bool vil_tiff_header::parse_pixel_format(vil_pixel_format const& fmt)
00580 {
00581
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
00612
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
00619 #if VXL_BIG_ENDIAN
00620 machine_is_big_endian_ = true;
00621 #else
00622 machine_is_big_endian_ = false;
00623 #endif
00624
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
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
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
00663 planar_config.val = 1; planar_config.valid = true;
00664
00665 orientation.val = ORIENTATION_TOPLEFT; orientation.valid = true;
00666 software = "http://vxl.sourceforge.net/ vil image library";
00667 return true;
00668 }
00669
00670
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
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 }