00001
00002 #include "vil_tiff.h"
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <vcl_cassert.h>
00017 #include <vcl_cstring.h>
00018 #include <vcl_iostream.h>
00019 #include <vcl_algorithm.h>
00020 #include <vcl_sstream.h>
00021 #include <vil/vil_stream.h>
00022 #include <vil/vil_property.h>
00023 #include <vil/vil_image_view.h>
00024 #include <vil/vil_memory_chunk.h>
00025 #include <vil/vil_copy.h>
00026 #include <vil/vil_image_list.h>
00027 #include "vil_tiff_header.h"
00028 #include <vil/vil_exception.h>
00029
00030
00031
00032 char const* vil_tiff_format_tag = "tiff";
00033
00034 static unsigned nimg(TIFF* tif)
00035 {
00036 if (!tif)
00037 return 0;
00038 TIFFSetDirectory(tif, 0);
00039 unsigned int dircount = 0;
00040 do {
00041 dircount++;
00042 } while (TIFFReadDirectory(tif));
00043 return dircount;
00044 }
00045
00046
00047 bool vil_tiff_file_format_probe(vil_stream* is)
00048 {
00049
00050
00051
00052 char hdr[4];
00053 unsigned read = (unsigned)is->read(hdr, sizeof hdr);
00054 if (read < sizeof hdr)
00055 return false;
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 if (hdr[0]==0x4D && hdr[1]==0x4D &&
00066 hdr[2]==0x00 && hdr[3]==0x2A)
00067 return true;
00068
00069 else if (hdr[0]==0x49 && hdr[1]==0x49 &&
00070 hdr[2]==0x2A && hdr[3]==0x00)
00071 return true;
00072
00073 else if ( ((hdr[0]==0x4D && hdr[1]==0x4D) || (hdr[1]==0x49 && hdr[1]==0x49)) &&
00074 ((hdr[2]==0x00 && hdr[3]==0x2A) || (hdr[2]==0x2A && hdr[3]==0x00)) ) {
00075 vcl_cerr << __FILE__ ": suspicious TIFF header\n";
00076 return true;
00077 }
00078
00079 else
00080 return false;
00081 }
00082
00083 struct tif_stream_structures
00084 {
00085 tif_stream_structures(vil_stream *vs_)
00086 : vs(vs_), filesize(0)
00087 { if (vs) vs->ref(); }
00088
00089 ~tif_stream_structures() { if (vs) vs->unref(); }
00090
00091 TIFF* tif;
00092 vil_stream* vs;
00093 vil_streampos filesize;
00094 };
00095
00096 static tsize_t vil_tiff_readproc(thandle_t h, tdata_t buf, tsize_t n)
00097 {
00098 tif_stream_structures* p = (tif_stream_structures*)h;
00099 if (n > p->filesize) p->filesize= n;
00100
00101
00102 tsize_t ret = (tsize_t)p->vs->read(buf, n);
00103 return ret;
00104 }
00105
00106 static tsize_t vil_tiff_writeproc(thandle_t h, tdata_t buf, tsize_t n)
00107 {
00108 tif_stream_structures* p = (tif_stream_structures*)h;
00109
00110
00111 tsize_t ret = (tsize_t)p->vs->write(buf, n);
00112 vil_streampos s = p->vs->tell();
00113 if (s > p->filesize)
00114 p->filesize = s;
00115 return ret;
00116 }
00117
00118 static toff_t vil_tiff_seekproc(thandle_t h, toff_t offset, int whence)
00119 {
00120 tif_stream_structures* p = (tif_stream_structures*)h;
00121 if (whence == SEEK_SET) p->vs->seek(offset);
00122 else if (whence == SEEK_CUR) p->vs->seek(p->vs->tell() + offset);
00123 else if (whence == SEEK_END) p->vs->seek(p->filesize + offset);
00124 vil_streampos s = p->vs->tell();
00125 if (s > p->filesize)
00126 p->filesize = s;
00127 return (toff_t)s;
00128 }
00129
00130 static int vil_tiff_closeproc(thandle_t h)
00131 {
00132 tif_stream_structures* p = (tif_stream_structures*)h;
00133 p->vs->unref();
00134 p->vs = 0;
00135 delete p;
00136 return 0;
00137 }
00138
00139 static toff_t vil_tiff_sizeproc(thandle_t)
00140 {
00141
00142 #ifdef DEBUG
00143 vcl_cerr << "Warning: vil_tiff_sizeproc() not yet implemented\n";
00144 #endif
00145 return (toff_t)(-1);
00146 }
00147
00148 static int vil_tiff_mapfileproc(thandle_t, tdata_t*, toff_t*)
00149 {
00150
00151 #ifdef DEBUG
00152 vcl_cerr << "Warning: mmap support not yet in vil_tiff_mapfileproc()\n";
00153 #endif
00154 return 0;
00155 }
00156
00157 static void vil_tiff_unmapfileproc(thandle_t, tdata_t, toff_t)
00158 {
00159 }
00160
00161
00162 static TIFF* open_tiff(tif_stream_structures* tss, const char* mode)
00163 {
00164 tss->vs->seek(0L);
00165 TIFF* tiff = TIFFClientOpen("unknown filename",
00166 mode,
00167 (thandle_t)tss,
00168 vil_tiff_readproc, vil_tiff_writeproc,
00169 vil_tiff_seekproc, vil_tiff_closeproc,
00170 vil_tiff_sizeproc,
00171 vil_tiff_mapfileproc, vil_tiff_unmapfileproc);
00172
00173 if (!tiff)
00174 return 0;
00175 else
00176 return tiff;
00177 }
00178
00179 vil_image_resource_sptr vil_tiff_file_format::make_input_image(vil_stream* is)
00180 {
00181 if (!vil_tiff_file_format_probe(is))
00182 return 0;
00183 tif_stream_structures* tss = new tif_stream_structures(is);
00184
00185 tss->tif = open_tiff(tss, "rC");
00186
00187 if (!tss->tif)
00188 return 0;
00189 vil_tiff_header* h = new vil_tiff_header(tss->tif);
00190
00191 if (!h->format_supported)
00192 {
00193 TIFFClose(tss->tif);
00194 delete h;
00195 return 0;
00196 }
00197 unsigned n = nimg(tss->tif);
00198 tif_smart_ptr tif_sptr = new tif_ref_cnt(tss->tif);
00199 return new vil_tiff_image(tif_sptr, h, n);
00200 }
00201
00202 vil_pyramid_image_resource_sptr
00203 vil_tiff_file_format::make_input_pyramid_image(char const* file)
00204 {
00205 bool trace = false;
00206 if (vil_image_list::vil_is_directory(file))
00207 return 0;
00208 TIFF* in = TIFFOpen(file, "rC");
00209 if (!in)
00210 return 0;
00211 bool open_for_reading = true;
00212 if (trace)
00213 vcl_cerr << "make_input_pyramid_image::opening multi-image tiff pyramid resource\n";
00214 tif_smart_ptr tif_sptr = new tif_ref_cnt(in);
00215 vil_pyramid_image_resource_sptr pyr =
00216 new vil_tiff_pyramid_resource(tif_sptr, open_for_reading);
00217 if (pyr->nlevels()<=1)
00218 return 0;
00219 else
00220 return pyr;
00221 }
00222
00223 static vcl_string level_filename(vcl_string& directory, vcl_string& filename,
00224 unsigned level)
00225 {
00226 vcl_string slash;
00227
00228 #ifdef VCL_WIN32
00229 slash = "\\";
00230 #else
00231 slash = "/";
00232 #endif
00233 vcl_stringstream cs;
00234 cs << level;
00235 return directory + slash + filename + cs.str();
00236 }
00237
00238 vil_pyramid_image_resource_sptr vil_tiff_file_format::
00239 make_pyramid_image_from_base(char const* file,
00240 vil_image_resource_sptr const& base_image,
00241 unsigned nlevels,
00242 char const* temp_dir)
00243 {
00244 {
00245 vil_pyramid_image_resource_sptr pyr = make_pyramid_output_image(file);
00246 pyr->put_resource(base_image);
00247
00248 {
00249 vcl_string d = temp_dir;
00250 vcl_string fn = "tempR";
00251 vil_image_resource_sptr image = base_image;
00252 for (unsigned L = 1; L<nlevels; ++L)
00253 {
00254 vcl_cout << "Decimating Level " << L << vcl_endl;
00255 vcl_string full_filename = level_filename(d, fn, L) + ".tif";
00256 image =
00257 vil_pyramid_image_resource::decimate(image, full_filename.c_str());
00258 }
00259 }
00260
00261
00262 {
00263 vil_image_list il(temp_dir);
00264 vcl_vector<vil_image_resource_sptr> rescs = il.resources();
00265 for (vcl_vector<vil_image_resource_sptr>::iterator rit = rescs.begin();
00266 rit != rescs.end(); ++rit)
00267 pyr->put_resource(*rit);
00268 }
00269 }
00270
00271
00272 vil_image_list vl(temp_dir);
00273 if (!vl.clean_directory())
00274 {
00275 vcl_cout <<"Warning: In vil_tiff::make_pyramid_from_base(..) -"
00276 << " temporary directory not cleaned\n";
00277 }
00278
00279 return make_input_pyramid_image(file);
00280 }
00281
00282 vil_blocked_image_resource_sptr
00283 vil_tiff_file_format::make_blocked_output_image(vil_stream* vs,
00284 unsigned nx,
00285 unsigned ny,
00286 unsigned nplanes,
00287 unsigned size_block_i,
00288 unsigned size_block_j,
00289 enum vil_pixel_format format)
00290 {
00291 if (size_block_i%16!=0||size_block_j%16!=0)
00292 {
00293 vcl_cerr << "In vil_tiff_file_format - Block dimensions must be a multiple of 16\n";
00294 return 0;
00295 }
00296
00297 tif_stream_structures* tss = new tif_stream_structures(vs);
00298 tss->filesize = 0;
00299 tss->tif = open_tiff(tss, "w");
00300 if (!tss->tif)
00301 return 0;
00302
00303
00304
00305
00306 vil_tiff_header* h = new vil_tiff_header(tss->tif, nx, ny, nplanes,
00307 format, size_block_i, size_block_j);
00308 if (!h->format_supported)
00309 {
00310 TIFFClose(tss->tif);
00311 delete tss;
00312 delete h;
00313 return 0;
00314 }
00315 tif_smart_ptr tsptr = new tif_ref_cnt(tss->tif);
00316 return new vil_tiff_image(tsptr, h);
00317 }
00318
00319
00320 vil_image_resource_sptr
00321 vil_tiff_file_format::make_output_image(vil_stream* vs,
00322 unsigned ni,
00323 unsigned nj,
00324 unsigned nplanes,
00325 enum vil_pixel_format format)
00326 {
00327 return make_blocked_output_image(vs, ni, nj, nplanes, 0, 0, format).ptr();
00328 }
00329
00330 vil_pyramid_image_resource_sptr
00331 vil_tiff_file_format::make_pyramid_output_image(char const* filename)
00332 {
00333 TIFF* out = TIFFOpen(filename, "w");
00334 if (!out)
00335 return 0;
00336 bool open_for_reading = false;
00337 tif_smart_ptr tsptr = new tif_ref_cnt(out);
00338 return new vil_tiff_pyramid_resource(tsptr, open_for_reading);
00339 }
00340
00341 char const* vil_tiff_file_format::tag() const
00342 {
00343 return vil_tiff_format_tag;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352 vil_tiff_image::vil_tiff_image(tif_smart_ptr const& tif_sptr,
00353 vil_tiff_header* th, const unsigned nimages):
00354 t_(tif_sptr), h_(th), index_(0), nimages_(nimages)
00355 {
00356 }
00357
00358 bool vil_tiff_image::get_property(char const * tag, void * value) const
00359 {
00360 if (vcl_strcmp(vil_property_quantisation_depth, tag)==0)
00361 {
00362 if (value)
00363 *static_cast<unsigned*>(value) = h_->bits_per_sample.val;
00364 return true;
00365 }
00366 if (vcl_strcmp(vil_property_size_block_i, tag)==0)
00367 {
00368 if (!h_->is_tiled())
00369 return false;
00370 if (value)
00371 *static_cast<unsigned*>(value) = this->size_block_i();
00372 return true;
00373 }
00374
00375 if (vcl_strcmp(vil_property_size_block_j, tag)==0)
00376 {
00377 if (!h_->is_tiled())
00378 return false;
00379 if (value)
00380 *static_cast<unsigned*>(value) = this->size_block_j();
00381 return true;
00382 }
00383
00384 return false;
00385 }
00386 #if HAS_GEOTIFF
00387 vil_geotiff_header* vil_tiff_image::get_geotiff_header()
00388 {
00389 vil_geotiff_header* gtif = new vil_geotiff_header(t_.tif());
00390 if (gtif->gtif_number_of_keys() == 0) {
00391 delete gtif;
00392 return 0;
00393 }
00394
00395 return gtif;
00396 }
00397 #endif
00398
00399 vil_pixel_format vil_tiff_image::pixel_format() const
00400 {
00401 return h_->pix_fmt;
00402 }
00403
00404 vil_tiff_image::~vil_tiff_image()
00405 {
00406 delete h_;
00407 }
00408
00409
00410
00411
00412 char const* vil_tiff_image::file_format() const
00413 {
00414 return vil_tiff_format_tag;
00415 }
00416
00417 static void tif_swap16(vxl_byte *a, unsigned n)
00418 {
00419 for (unsigned i = 0; i < n * 2; i += 2)
00420 vcl_swap( a[i+0], a[i+1] );
00421 }
00422
00423 static void tif_swap32(vxl_byte *a, unsigned n)
00424 {
00425 for (unsigned i = 0; i < n * 4; i += 4)
00426 {
00427 vcl_swap( a[i+0], a[i+3] );
00428 vcl_swap( a[i+1], a[i+2] );
00429 }
00430 }
00431
00432 static void endian_swap( vxl_byte* a, unsigned n_bytes,
00433 unsigned bytes_per_sample)
00434 {
00435 switch ( bytes_per_sample ) {
00436 case 1: break;
00437 case 2: tif_swap16( a, n_bytes / 2 ); break;
00438 case 4: tif_swap32( a, n_bytes / 4 ); break;
00439 default: assert(!"Unsupported number of bytes per sample.");
00440 }
00441 }
00442
00443 template<> bool* tiff_byte_align_data<bool>(bool* in_data, unsigned num_samples, unsigned in_bits_per_sample, bool* out_data)
00444 {
00445 switch (sizeof(bool))
00446 {
00447 case 1:
00448 tiff_byte_align_data((vxl_byte*)in_data, num_samples, in_bits_per_sample, (vxl_byte*)out_data);
00449 break;
00450 case 2:
00451 tiff_byte_align_data((vxl_uint_16*)in_data, num_samples, in_bits_per_sample, (vxl_uint_16*)out_data);
00452 break;
00453 case 4:
00454 tiff_byte_align_data((vxl_uint_32*)in_data, num_samples, in_bits_per_sample, (vxl_uint_32*)out_data);
00455 break;
00456 default:
00457 assert(!"Unsupported size of bool in tiff file format.");
00458 }
00459 return out_data;
00460 }
00461
00462
00463 bool integral_type(unsigned bits_per_sample)
00464 {
00465 switch (bits_per_sample)
00466 {
00467 case 8:
00468 case 16:
00469 case 32: return true;
00470 default: break;
00471 }
00472 return false;
00473 }
00474
00475 template< class T >
00476 vil_memory_chunk_sptr
00477 tiff_maybe_byte_align_data(vil_memory_chunk_sptr in_data,
00478 unsigned num_samples,
00479 unsigned in_bits_per_sample,
00480 unsigned bytes_per_block)
00481 {
00482 if (!integral_type(in_bits_per_sample))
00483 {
00484 vil_memory_chunk_sptr new_memory = new vil_memory_chunk(bytes_per_block, in_data->pixel_format());
00485 #ifdef DEBUG
00486 vcl_cout << "Debug tiff_byte_align_data:"
00487 << " Num Samples = " << num_samples
00488 << " Input Bits/Sample = " << in_bits_per_sample
00489 << " Bytes/Block = " << bytes_per_block
00490 << " Output Bytes/Sample = " << vil_pixel_format_sizeof_components(in_data->pixel_format())
00491 << vcl_flush;
00492 #endif
00493 T* out_ptr = reinterpret_cast<T*>(new_memory->data());
00494 T* in_ptr = reinterpret_cast<T*>(in_data->data());
00495 tiff_byte_align_data(in_ptr, num_samples, in_bits_per_sample, out_ptr );
00496 #ifdef DEBUG
00497 vcl_cout << " .\n" << vcl_flush;
00498 #endif
00499 return new_memory;
00500 }
00501 return in_data;
00502 }
00503
00504
00505 template<> vil_memory_chunk_sptr tiff_maybe_byte_align_data<float>
00506 ( vil_memory_chunk_sptr in_data ,
00507 unsigned ,
00508 unsigned ,
00509 unsigned )
00510 { return in_data; }
00511
00512 template<> vil_memory_chunk_sptr tiff_maybe_byte_align_data<double>
00513 ( vil_memory_chunk_sptr in_data ,
00514 unsigned ,
00515 unsigned ,
00516 unsigned )
00517 { return in_data; }
00518
00519
00520
00521
00522 unsigned vil_tiff_image::nplanes() const
00523 {
00524 return h_->nplanes;
00525 }
00526
00527 unsigned vil_tiff_image::ni() const
00528 {
00529 if (h_->image_width.valid)
00530 return h_->image_width.val;
00531 return 0;
00532 }
00533
00534 unsigned vil_tiff_image::nj() const
00535 {
00536 if (h_->image_length.valid)
00537 return h_->image_length.val;
00538 return 0;
00539 }
00540
00541
00542 unsigned vil_tiff_image::size_block_i() const
00543 {
00544 if (h_->tile_width.valid)
00545 return static_cast<unsigned>(h_->tile_width.val);
00546 if (h_->image_width.valid)
00547 return static_cast<unsigned>(h_->image_width.val);
00548 return 0;
00549 }
00550
00551
00552
00553
00554
00555 unsigned vil_tiff_image::size_block_j() const
00556 {
00557 if (h_->tile_length.valid)
00558 return static_cast<unsigned>(h_->tile_length.val);
00559
00560 unsigned bps = static_cast<unsigned>(h_->bytes_per_strip());
00561 unsigned bpl = static_cast<unsigned>(h_->bytes_per_line());
00562 unsigned size = bps/bpl;
00563 return size;
00564 return 0;
00565 }
00566
00567
00568 unsigned vil_tiff_image::n_block_i() const
00569 {
00570 if (h_->tile_width.valid)
00571 return static_cast<unsigned>(h_->tiles_across());
00572 return 1;
00573 }
00574
00575
00576 unsigned vil_tiff_image::n_block_j() const
00577 {
00578 if (h_->tile_length.valid&&h_->image_length.valid)
00579 return static_cast<unsigned>(h_->tiles_down());
00580 return static_cast<unsigned>(h_->strips_per_image());
00581 }
00582
00583
00584
00585 unsigned vil_tiff_image::
00586 block_index(unsigned block_i, unsigned block_j) const
00587 {
00588 return block_j*n_block_i() + block_i;
00589 }
00590
00591
00592 unsigned vil_tiff_image::samples_per_block() const
00593 {
00594 if (h_->samples_per_pixel.valid)
00595 return static_cast<unsigned>(h_->samples_per_pixel.val*
00596 size_block_i()*size_block_j());
00597 return 0;
00598 }
00599
00600
00601
00602 void vil_tiff_image::copy_byte_block(vxl_byte* data, const vxl_uint_32 nbytes, vil_memory_chunk_sptr& cnk) const
00603 {
00604 if (nbytes==0)
00605 return;
00606 vxl_byte* c_data = reinterpret_cast<vxl_byte*>(cnk->data());
00607 vcl_memcpy(c_data, data, nbytes);
00608 }
00609
00610
00611
00612 vil_image_view_base_sptr vil_tiff_image::
00613 view_from_buffer(vil_pixel_format& fmt, vil_memory_chunk_sptr const& buf,
00614 unsigned samples_per_block, unsigned bits_per_sample
00615 ) const
00616 {
00617 vil_image_view_base_sptr view = 0;
00618 vil_memory_chunk_sptr buf_out;
00619 unsigned spp = h_->samples_per_pixel.val;
00620 switch (fmt)
00621 {
00622 #define GET_BLOCK_CASE(FORMAT, T) \
00623 case FORMAT: { \
00624 vil_image_view_base_sptr view; \
00625 buf_out = tiff_maybe_byte_align_data<T>(buf, samples_per_block, \
00626 bits_per_sample, \
00627 samples_per_block*vil_pixel_format_sizeof_components(fmt)); \
00628 view = new vil_image_view<T>(buf_out, reinterpret_cast<T*>(buf_out->data()), \
00629 size_block_i(), size_block_j(), \
00630 spp, spp, size_block_i()*spp, 1); \
00631 return view; }
00632 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00633 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte);
00634 #if VXL_HAS_INT_64
00635 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
00636 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
00637 #endif
00638 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00639 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_32, vxl_int_32);
00640 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00641 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_16, vxl_int_16);
00642 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_BOOL, bool);
00643 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_FLOAT, float);
00644 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_DOUBLE, double);
00645 #undef GET_BLOCK_CASE
00646 default:
00647 assert(!"Unknown vil data type in tiff file format");
00648 break;
00649 }
00650 return view;
00651 }
00652
00653
00654
00655 vil_image_view_base_sptr
00656 vil_tiff_image::get_block( unsigned block_index_i,
00657 unsigned block_index_j ) const
00658 {
00659
00660 assert(h_->is_tiled()||h_->is_striped());
00661
00662
00663
00664
00665
00666 if (nimages_>1)
00667 {
00668 if (TIFFSetDirectory(t_.tif(), index_)<=0)
00669 return 0;
00670 vil_tiff_header* h = new vil_tiff_header(t_.tif());
00671
00672 vil_tiff_image* ti = (vil_tiff_image*)this;
00673 delete h_;
00674 ti->h_=h;
00675 }
00676
00677 vil_image_view_base_sptr view = 0;
00678
00679
00680
00681 unsigned encoded_block_size = h_->encoded_bytes_per_block();
00682 assert(encoded_block_size>0);
00683 vxl_byte* data = new vxl_byte[encoded_block_size];
00684
00685
00686 unsigned blk_indx = this->block_index(block_index_i, block_index_j);
00687
00688
00689 vil_pixel_format fmt = vil_pixel_format_component_format(h_->pix_fmt);
00690
00691
00692 vil_memory_chunk_sptr buf =
00693 new vil_memory_chunk(encoded_block_size, fmt);
00694 unsigned expanded_sample_bytes = vil_pixel_format_sizeof_components(fmt);
00695
00696
00697 if (h_->is_tiled())
00698 {
00699 if (TIFFReadEncodedTile(t_.tif(), blk_indx, data, (tsize_t) -1)<=0)
00700 {
00701 delete [] data;
00702 return view;
00703 }
00704 this->copy_byte_block(data, encoded_block_size, buf);
00705 delete [] data;
00706 if (h_->need_byte_swap())
00707 endian_swap( reinterpret_cast<vxl_byte*>(buf->data()),
00708 encoded_block_size,
00709 expanded_sample_bytes);
00710 return this->fill_block_from_tile(buf);
00711 }
00712
00713 if (h_->is_striped())
00714 {
00715 if (TIFFReadEncodedStrip(t_.tif(), blk_indx, data, (tsize_t) -1)<=0)
00716 {
00717 delete [] data;
00718 return view;
00719 }
00720 this->copy_byte_block(data, encoded_block_size, buf);
00721 delete [] data;
00722 if (h_->need_byte_swap())
00723 endian_swap( reinterpret_cast<vxl_byte*>(buf->data()),
00724 encoded_block_size,
00725 expanded_sample_bytes);
00726 return this->fill_block_from_strip(buf);
00727 }
00728
00729 return view;
00730 }
00731
00732
00733
00734
00735 vil_image_view_base_sptr vil_tiff_image::
00736 fill_block_from_tile(vil_memory_chunk_sptr const & buf) const
00737 {
00738 vil_image_view_base_sptr view = 0;
00739
00740
00741 unsigned samples_per_block = this->samples_per_block();
00742 assert(samples_per_block>0);
00743
00744 vil_pixel_format fmt = vil_pixel_format_component_format(h_->pix_fmt);
00745 view = view_from_buffer(fmt, buf, samples_per_block, h_->bits_per_sample.val);
00746 return view;
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756 vil_image_view_base_sptr vil_tiff_image::fill_block_from_strip(vil_memory_chunk_sptr const & buf) const
00757 {
00758 vil_image_view_base_sptr view = 0;
00759 vxl_uint_32 tl = size_block_j();
00760
00761 unsigned bpl = h_->bytes_per_line();
00762 unsigned bytes_per_strip = h_->bytes_per_strip();
00763 unsigned lines_per_strip = bytes_per_strip/bpl;
00764
00765 vil_pixel_format fmt = vil_pixel_format_component_format(h_->pix_fmt);
00766 unsigned expanded_bytes_per_sample =
00767 vil_pixel_format_sizeof_components(fmt);
00768 unsigned spl = h_->samples_per_line();
00769 unsigned bytes_expanded_line = spl*expanded_bytes_per_sample;
00770
00771
00772 unsigned expanded_bytes_per_strip = tl*bytes_expanded_line;
00773
00774
00775 vxl_byte* buf_ptr = reinterpret_cast<vxl_byte*>(buf->data());
00776
00777
00778 vil_memory_chunk_sptr line_buf =
00779 new vil_memory_chunk(bpl, fmt);
00780
00781
00782 vil_memory_chunk_sptr zero_buf =
00783 new vil_memory_chunk(bytes_expanded_line, fmt);
00784 vxl_byte* zero_ptr = reinterpret_cast<vxl_byte*>(zero_buf->data());
00785 for (unsigned i = 0; i<bytes_expanded_line; ++i)
00786 zero_ptr[i]=0;
00787
00788
00789 vil_memory_chunk_sptr block_buf =
00790 new vil_memory_chunk(expanded_bytes_per_strip, fmt);
00791 vxl_byte* block_ptr = reinterpret_cast<vxl_byte*>(block_buf->data());
00792
00793 for (unsigned j = 0; j<tl; ++j, buf_ptr+=bpl,
00794 block_ptr+=bytes_expanded_line)
00795 {
00796 if (j<lines_per_strip)
00797 {
00798
00799 copy_byte_block(buf_ptr, bpl, line_buf);
00800 vil_memory_chunk_sptr out_line_buf;
00801 switch (fmt)
00802 {
00803 #define GET_LINE_CASE(FORMAT, T) \
00804 case FORMAT:\
00805 out_line_buf = \
00806 tiff_maybe_byte_align_data<T>(line_buf,\
00807 spl, h_->bits_per_sample.val,\
00808 bytes_expanded_line); \
00809 break
00810 GET_LINE_CASE(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00811 GET_LINE_CASE(VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte);
00812 #if VXL_HAS_INT_64
00813 GET_LINE_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
00814 GET_LINE_CASE(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
00815 #endif
00816 GET_LINE_CASE(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00817 GET_LINE_CASE(VIL_PIXEL_FORMAT_INT_32, vxl_int_32);
00818 GET_LINE_CASE(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00819 GET_LINE_CASE(VIL_PIXEL_FORMAT_INT_16, vxl_int_16);
00820 GET_LINE_CASE(VIL_PIXEL_FORMAT_BOOL, bool);
00821 GET_LINE_CASE(VIL_PIXEL_FORMAT_FLOAT, float);
00822 GET_LINE_CASE(VIL_PIXEL_FORMAT_DOUBLE, double);
00823 #undef GET_LINE_CASE
00824 default:
00825 assert(!"Unknown vil data type in tiff file format");
00826 break;
00827 }
00828
00829
00830 vxl_byte* out_line_buf_ptr =
00831 reinterpret_cast<vxl_byte*>(out_line_buf->data());
00832 vcl_memcpy(block_ptr, out_line_buf_ptr, bytes_expanded_line);
00833 }
00834 else
00835 vcl_memcpy(block_ptr, zero_ptr, bytes_expanded_line);
00836 }
00837
00838 return this->view_from_buffer(fmt, block_buf, spl*tl,
00839 expanded_bytes_per_sample*8);
00840 }
00841
00842 void vil_tiff_image::pad_block_with_zeros(unsigned ioff, unsigned joff,
00843 unsigned iclip, unsigned jclip,
00844 unsigned bytes_per_pixel,
00845 vxl_byte* block_buf)
00846 {
00847 unsigned jstep = size_block_i()*bytes_per_pixel;
00848 unsigned row_start = ioff*bytes_per_pixel;
00849 unsigned bptr = 0;
00850
00851 if (ioff>0||joff>0)
00852 for (unsigned j = 0; j<joff-1; ++j)
00853 {
00854 unsigned row_ptr = row_start;
00855 for (unsigned i = 0; i<ioff-1; ++i)
00856 {
00857 for (unsigned p = 0; p<nplanes(); ++p)
00858 *(block_buf + bptr + row_ptr + p) = 0;
00859 row_ptr += bytes_per_pixel;
00860 }
00861 bptr += jstep;
00862 }
00863 bptr = jstep*jclip;
00864 row_start = iclip*bytes_per_pixel;
00865 if (iclip>0||jclip>0)
00866 for (unsigned j = jclip; j<size_block_j(); ++j)
00867 {
00868 unsigned row_ptr = row_start;
00869 for (unsigned i = iclip; i<size_block_i(); ++i)
00870 {
00871 for (unsigned p = 0; p<nplanes(); ++p)
00872 *(block_buf + bptr + row_ptr + p) = 0;
00873 row_ptr += bytes_per_pixel;
00874 }
00875 bptr += jstep;
00876 }
00877 }
00878
00879 void vil_tiff_image::fill_block_from_view(unsigned bi, unsigned bj,
00880 unsigned i0, unsigned j0,
00881 unsigned ioff, unsigned joff,
00882 unsigned iclip, unsigned jclip,
00883 const vil_image_view_base& im,
00884 vxl_byte*& block_buf)
00885 {
00886 unsigned bytes_per_sample = h_->bytes_per_sample();
00887 unsigned bytes_per_pixel = bytes_per_sample*nplanes();
00888 unsigned sbi = size_block_i(), sbj = size_block_j();
00889 unsigned bytes_per_block=bytes_per_pixel*sbi*sbj;
00890 unsigned view_i0 = bi*sbi-i0, view_j0 = bj*sbj-j0;
00891 unsigned block_jstep = sbi*bytes_per_pixel;
00892 #if 0
00893
00894 unsigned view_istep = 1, view_jstep = im.ni()*bytes_per_pixel, view_pstep = 1;
00895 #endif
00896 vcl_ptrdiff_t view_istep, view_jstep, view_pstep;
00897 vxl_byte* view_buf;
00898
00899 switch (h_->pix_fmt)
00900 {
00901 #define GET_VIEW_PTR(FORMAT, T) \
00902 case FORMAT: { \
00903 vil_image_view<T> view = static_cast<const vil_image_view<T>& >(im);\
00904 view_istep = view.istep(); view_jstep = view.jstep(); view_pstep = view.planestep(); \
00905 view_buf = reinterpret_cast<vxl_byte*>(view.top_left_ptr());\
00906 } break
00907 GET_VIEW_PTR(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00908 GET_VIEW_PTR(VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte);
00909 #if VXL_HAS_INT_64
00910 GET_VIEW_PTR(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
00911 GET_VIEW_PTR(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
00912 #endif
00913 GET_VIEW_PTR(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00914 GET_VIEW_PTR(VIL_PIXEL_FORMAT_INT_32, vxl_int_32);
00915 GET_VIEW_PTR(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00916 GET_VIEW_PTR(VIL_PIXEL_FORMAT_INT_16, vxl_int_16);
00917 GET_VIEW_PTR(VIL_PIXEL_FORMAT_BOOL, bool);
00918 GET_VIEW_PTR(VIL_PIXEL_FORMAT_FLOAT, float);
00919 GET_VIEW_PTR(VIL_PIXEL_FORMAT_DOUBLE, double);
00920 #undef GET_VIEW_PTR
00921 default:
00922 assert(!"Unknown vil data type.");
00923 return;
00924 }
00925
00926 unsigned bptr = joff*block_jstep;
00927 unsigned ibstart = ioff*bytes_per_pixel;
00928 vcl_ptrdiff_t vistp = view_istep*bytes_per_sample;
00929 vcl_ptrdiff_t vjstp = view_jstep*bytes_per_sample;
00930 vcl_ptrdiff_t vpstp = view_pstep*bytes_per_sample;
00931
00932
00933
00934 vcl_ptrdiff_t vptr = (view_j0 + joff)*vjstp;
00935 unsigned ivstart = (view_i0 + ioff)*bytes_per_pixel;
00936 for (unsigned j = joff; j<jclip; ++j)
00937 {
00938 vcl_ptrdiff_t vrow_ptr = ivstart;
00939 vcl_ptrdiff_t brow_ptr = ibstart;
00940 for (unsigned i = ioff; i<iclip; ++i)
00941 {
00942 vcl_ptrdiff_t bpptr = 0, vpptr = 0;
00943 for (unsigned p = 0; p<nplanes(); ++p)
00944 {
00945 for (unsigned b = 0; b<bytes_per_sample; ++b)
00946 *(block_buf + bptr + brow_ptr + bpptr + b) =
00947 *(view_buf + vptr + vrow_ptr + vpptr + b);
00948 bpptr += bytes_per_sample; vpptr += vpstp;
00949 }
00950 brow_ptr += bytes_per_pixel; vrow_ptr += vistp;
00951 }
00952 bptr += block_jstep; vptr += vjstp;
00953 }
00954
00955
00956 if (this->pixel_format() == VIL_PIXEL_FORMAT_BOOL)
00957 {
00958 unsigned outsize = (bytes_per_block+7*sizeof(bool))/(8*sizeof(bool));
00959 vxl_byte* outbuf = new vxl_byte[outsize];
00960 this->bitpack_block(bytes_per_block, block_buf, outbuf);
00961 delete [] block_buf;
00962 block_buf = outbuf;
00963 }
00964 }
00965
00966 bool vil_tiff_image::write_block_to_file(unsigned bi, unsigned bj,
00967 unsigned block_size_bytes,
00968 vxl_byte* block_buf)
00969 {
00970 unsigned blk_indx = this->block_index(bi, bj);
00971 if (h_->is_tiled())
00972 return TIFFWriteEncodedTile(t_.tif(), blk_indx, block_buf,
00973 block_size_bytes)>0;
00974 if (h_->is_striped())
00975 return TIFFWriteEncodedStrip(t_.tif(), blk_indx, block_buf,
00976 block_size_bytes ) > 0;
00977 return false;
00978 }
00979
00980
00981
00982 void vil_tiff_image::bitpack_block(unsigned bytes_per_block,
00983 vxl_byte* in_block_buf,
00984 vxl_byte* out_block_buf)
00985 {
00986 unsigned bytes_per_bool = sizeof(bool);
00987 vxl_byte* bl = new vxl_byte[bytes_per_bool];
00988 unsigned bitctr = 0;
00989 unsigned outctr = 0;
00990 vxl_byte packed_byte=0;
00991 for (unsigned i = 0; i<bytes_per_block; )
00992 {
00993
00994 if (bitctr==8)
00995 {
00996 bitctr = 0;
00997 out_block_buf[outctr] = packed_byte;
00998 packed_byte = 0;
00999 ++outctr;
01000 }
01001
01002 for (unsigned b = 0; b<bytes_per_bool; ++b)
01003 bl[b] = *(in_block_buf + i + b);
01004 bool blv = *(reinterpret_cast<bool*>(bl));
01005 if (blv)
01006 packed_byte |= vxl_byte(1<<(7-bitctr));
01007 else
01008 packed_byte &= vxl_byte(~(1<<(7-bitctr)));
01009 ++bitctr;
01010
01011 i+=bytes_per_bool;
01012 if (i>=bytes_per_block)
01013 out_block_buf[outctr] = packed_byte;
01014 }
01015 delete [] bl;
01016 }
01017
01018
01019
01020
01021
01022
01023
01024 bool vil_tiff_image::put_block(unsigned bi, unsigned bj, unsigned i0,
01025 unsigned j0, const vil_image_view_base& im)
01026 {
01027
01028
01029
01030 unsigned ioff =0, joff = 0;
01031 unsigned sbi = size_block_i(), sbj = size_block_j();
01032 unsigned iclip =sbi , jclip = sbj;
01033
01034 if (bi*sbi<i0&&(bi+1)*sbi>i0)
01035 if (!block_i_offset(bi, i0, ioff))
01036 return false;
01037
01038 if (bj*sbj<j0&&(bj+1)*sbj>j0)
01039 if (!block_j_offset(bj, j0, joff))
01040 return false;
01041
01042
01043
01044
01045
01046 if ( (bi+1)*sbi > (im.ni()+i0) )
01047 {
01048 iclip = (i0+im.ni())-bi*sbi;
01049 if (iclip > sbi)
01050 return false;
01051 }
01052
01053
01054 if ( (bj+1)*sbj > (im.nj()+j0) )
01055 {
01056 jclip = (j0+im.nj())-bj*sbj;
01057 if (jclip > sbj)
01058 return false;
01059 }
01060 unsigned bps = h_->bytes_per_sample();
01061 unsigned bytes_per_pixel = bps*nplanes();
01062
01063 unsigned bytes_per_block = bytes_per_pixel*sbi*sbj;
01064
01065
01066
01067 vxl_byte* block_buf = new vxl_byte[bytes_per_block];
01068
01069 this->pad_block_with_zeros(ioff, joff, iclip, jclip,
01070 bytes_per_pixel, block_buf);
01071
01072
01073 this->fill_block_from_view(bi, bj, i0, j0, ioff, joff, iclip, jclip,
01074 im, block_buf);
01075
01076 bool good_write = write_block_to_file(bi, bj, bytes_per_block, block_buf);
01077 delete [] block_buf;
01078 return good_write;
01079 }
01080
01081 bool vil_tiff_image::put_view(const vil_image_view_base& im,
01082 unsigned i0, unsigned j0)
01083 {
01084 if (!vil_image_resource::view_fits(im, i0, j0))
01085 {
01086 vil_exception_warning(vil_exception_out_of_bounds("vil_tiff_image::put_view"));
01087 return false;
01088 }
01089
01090 unsigned tw = size_block_i(), tl = size_block_j();
01091 if (tw==0||tl==0)
01092 return false;
01093 unsigned bi_start = i0/tw, bi_end = (i0+im.ni()-1)/tw;
01094 unsigned bj_start = j0/tl, bj_end = (j0+im.nj()-1)/tl;
01095 for (unsigned bi = bi_start; bi<=bi_end; ++bi)
01096 for (unsigned bj = bj_start; bj<=bj_end; ++bj)
01097 if (!this->put_block(bi, bj, i0, j0, im))
01098 return false;
01099 return true;
01100 }
01101
01102
01103 bool vil_tiff_image::put_block( unsigned block_index_i,
01104 unsigned block_index_j,
01105 const vil_image_view_base& blk )
01106 {
01107 if (blk.ni()==0||blk.nj()==0)
01108 return false;
01109 unsigned sbi = this->size_block_i(), sbj = this->size_block_j();
01110 unsigned bps = h_->bytes_per_sample();
01111 unsigned bytes_per_pixel = bps*nplanes();
01112
01113 unsigned bytes_per_block = bytes_per_pixel*sbi*sbj;
01114
01115
01116 vxl_byte* block_buf = new vxl_byte[bytes_per_block];
01117
01118 this->fill_block_from_view(0, 0, 0, 0, 0, 0,sbi, sbj, blk, block_buf);
01119
01120
01121 bool good_write = write_block_to_file(block_index_i, block_index_j, bytes_per_block, block_buf);
01122 delete [] block_buf;
01123 return good_write;
01124 }
01125
01126
01127 static bool level_compare(tiff_pyramid_level* const l1, tiff_pyramid_level* const l2)
01128 {
01129 assert(l1&&l2);
01130 return l1->ni_ > l2->ni_;
01131 }
01132
01133
01134 void vil_tiff_pyramid_resource::normalize_scales()
01135 {
01136 unsigned nlevels = this->nlevels();
01137 if (nlevels==0)
01138 return;
01139 levels_[0]->scale_ = 1.0f;
01140 if (nlevels==1)
01141 return;
01142 float ni0 = static_cast<float>(levels_[0]->ni_);
01143 for (unsigned i = 1; i<nlevels; ++i)
01144 levels_[i]->scale_ = static_cast<float>(levels_[i]->ni_)/ni0;
01145 }
01146
01147
01148 tiff_pyramid_level* vil_tiff_pyramid_resource::closest(const float scale) const
01149 {
01150 unsigned nlevels = this->nlevels();
01151 if (nlevels == 0)
01152 return 0;
01153 if (nlevels == 1)
01154 return levels_[0];
01155 float mind = 1.0e08f;
01156 unsigned lmin = 0;
01157 for (unsigned i = 0; i<nlevels; ++i)
01158 {
01159 float ds = vcl_fabs(scale - levels_[i]->scale_);
01160 if (ds<mind)
01161 {
01162 mind = ds;
01163 lmin = i;
01164 }
01165 }
01166 tiff_pyramid_level* pl = levels_[lmin];
01167 if (pl)
01168 pl->cur_level_ = lmin;
01169 return pl;
01170 }
01171
01172 vil_tiff_pyramid_resource::vil_tiff_pyramid_resource()
01173 : read_(true), t_(0)
01174 {
01175 }
01176
01177 vil_tiff_pyramid_resource::
01178 vil_tiff_pyramid_resource(tif_smart_ptr const& t, bool read)
01179 : read_(read), t_(t)
01180 {
01181 bool trace = false;
01182 if (!read)
01183 return;
01184
01185 while (true)
01186 {
01187 vil_tiff_header h(t_.tif());
01188 if (trace)
01189 vcl_cerr << "In vil_tiff_pyramid_resource constructor"
01190 << " constructed header\n"
01191 << "n-levels = " << this->nlevels() << '\n';
01192 tiff_pyramid_level* pl = new tiff_pyramid_level(this->nlevels(),
01193 h.image_width.val,
01194 h.image_length.val,
01195 h.nplanes,
01196 h.pix_fmt);
01197 levels_.push_back(pl);
01198 if (trace)
01199 vcl_cerr << "In vil_tiff_pyramid_resource constructor"
01200 << " constructed level\n";
01201 int status = TIFFReadDirectory(t_.tif());
01202 if (trace)
01203 vcl_cerr << "In vil_tiff_pyramid_resource constructor"
01204 << " Read new directory\n";
01205
01206 if (!status)
01207 break;
01208 }
01209 if (trace)
01210 vcl_cerr << "In vil_tiff_pyramid_resource constructor"
01211 << " Begin sorting\n";
01212
01213 vcl_sort(levels_.begin(), levels_.end(), level_compare);
01214
01215 this->normalize_scales();
01216 }
01217
01218 vil_tiff_pyramid_resource::~vil_tiff_pyramid_resource()
01219 {
01220 for (unsigned L = 0; L<this->nlevels(); ++L)
01221 delete levels_[L];
01222 }
01223
01224
01225 vil_image_view_base_sptr
01226 vil_tiff_pyramid_resource::get_copy_view(unsigned i0, unsigned n_i,
01227 unsigned j0, unsigned n_j,
01228 unsigned level) const
01229 {
01230 unsigned nl = this->nlevels();
01231 if (level>=nl)
01232 return vil_image_view_base_sptr();
01233 vil_image_resource_sptr resc = this->get_resource(level);
01234
01235 float scale = levels_[level]->scale_;
01236 float fi0 = vcl_floor(scale*i0), fj0 = vcl_floor(scale*j0);
01237 float fni = vcl_floor(scale*n_i), fnj = vcl_floor(scale*n_j);
01238 unsigned si0 = static_cast<unsigned>(fi0);
01239 unsigned sj0 = static_cast<unsigned>(fj0);
01240 unsigned sni = static_cast<unsigned>(fni);
01241 if (sni == 0) sni = 1;
01242 unsigned snj = static_cast<unsigned>(fnj);
01243 if (snj == 0) snj = 1;
01244 vil_image_view_base_sptr view = resc->get_copy_view(si0, sni, sj0, snj);
01245 #if 0 //DON'T NEED CLEAR?
01246 resc->clear_TIFF();
01247 #endif
01248 return view;
01249 }
01250
01251
01252
01253
01254
01255 vil_image_view_base_sptr
01256 vil_tiff_pyramid_resource::get_copy_view(unsigned i0, unsigned n_i,
01257 unsigned j0, unsigned n_j,
01258 const float scale,
01259 float& actual_scale) const
01260 {
01261
01262 tiff_pyramid_level* pl = this->closest(scale);
01263 if (!pl)
01264 return 0;
01265 actual_scale = pl->scale_;
01266 return this->get_copy_view(i0, n_i, j0, n_j, pl->cur_level_);
01267 }
01268
01269
01270
01271 bool vil_tiff_pyramid_resource::put_resource(vil_image_resource_sptr const& ir)
01272 {
01273 unsigned level = this->nlevels();
01274 unsigned ni = ir->ni(), nj = ir->nj();
01275 unsigned nplanes = ir->nplanes();
01276 vil_pixel_format fmt = ir->pixel_format();
01277 vil_blocked_image_resource_sptr bir = blocked_image_resource(ir);
01278 unsigned sbi = 0, sbj = 0;
01279 if (bir) { sbi = bir->size_block_i(); sbj = bir->size_block_j(); }
01280
01281 vil_tiff_header* h = new vil_tiff_header(t_.tif(), ni, nj, nplanes,
01282 fmt, sbi, sbj);
01283
01284
01285 TIFFSetField(t_.tif(), TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
01286
01287 TIFFSetField(t_.tif(), TIFFTAG_PAGENUMBER,level, 3);
01288 vil_tiff_image* ti = new vil_tiff_image(t_, h, level);
01289 vil_image_resource_sptr resc = ti;
01290 if (!vil_copy_deep(ir, resc))
01291 return false;
01292 #if 0 //DON'T NEED CLEAR?
01293 ti->clear_TIFF();
01294 #endif
01295 tiff_pyramid_level* pl = new tiff_pyramid_level(levels_.size(), ni, nj, nplanes, fmt);
01296 levels_.push_back(pl);
01297 int status = TIFFWriteDirectory(t_.tif());
01298 return status == 1 ;
01299 }
01300
01301 vil_image_resource_sptr vil_tiff_pyramid_resource::get_resource(const unsigned level) const
01302 {
01303 unsigned nl = this->nlevels();
01304 if (level>=nl)
01305 return 0;
01306
01307 unsigned header_index = levels_[level]->header_index_;
01308
01309 if (TIFFSetDirectory(t_.tif(), header_index)<=0)
01310 return 0;
01311 vil_tiff_header* h = new vil_tiff_header(t_.tif());
01312 vil_tiff_image* i = new vil_tiff_image(t_, h, nl);
01313 i->set_index(header_index);
01314 return i;
01315 }