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