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 h;
00312 return 0;
00313 }
00314 tif_smart_ptr tsptr = new tif_ref_cnt(tss->tif);
00315 return new vil_tiff_image(tsptr, h);
00316 }
00317
00318
00319 vil_image_resource_sptr
00320 vil_tiff_file_format::make_output_image(vil_stream* vs,
00321 unsigned ni,
00322 unsigned nj,
00323 unsigned nplanes,
00324 enum vil_pixel_format format)
00325 {
00326 return make_blocked_output_image(vs, ni, nj, nplanes, 0, 0, format).ptr();
00327 }
00328
00329 vil_pyramid_image_resource_sptr
00330 vil_tiff_file_format::make_pyramid_output_image(char const* filename)
00331 {
00332 TIFF* out = TIFFOpen(filename, "w");
00333 if (!out)
00334 return 0;
00335 bool open_for_reading = false;
00336 tif_smart_ptr tsptr = new tif_ref_cnt(out);
00337 return new vil_tiff_pyramid_resource(tsptr, open_for_reading);
00338 }
00339
00340 char const* vil_tiff_file_format::tag() const
00341 {
00342 return vil_tiff_format_tag;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351 vil_tiff_image::vil_tiff_image(tif_smart_ptr const& tif_sptr,
00352 vil_tiff_header* th, const unsigned nimages):
00353 t_(tif_sptr), h_(th), index_(0), nimages_(nimages)
00354 {
00355 }
00356
00357 bool vil_tiff_image::get_property(char const * tag, void * value) const
00358 {
00359 if (vcl_strcmp(vil_property_quantisation_depth, tag)==0)
00360 {
00361 if (value)
00362 *static_cast<unsigned*>(value) = h_->bits_per_sample.val;
00363 return true;
00364 }
00365 if (vcl_strcmp(vil_property_size_block_i, tag)==0)
00366 {
00367 if (!h_->is_tiled())
00368 return false;
00369 if (value)
00370 *static_cast<unsigned*>(value) = this->size_block_i();
00371 return true;
00372 }
00373
00374 if (vcl_strcmp(vil_property_size_block_j, tag)==0)
00375 {
00376 if (!h_->is_tiled())
00377 return false;
00378 if (value)
00379 *static_cast<unsigned*>(value) = this->size_block_j();
00380 return true;
00381 }
00382
00383 return false;
00384 }
00385 #if HAS_GEOTIFF
00386 vil_geotiff_header* vil_tiff_image::get_geotiff_header()
00387 {
00388 vil_geotiff_header* gtif = new vil_geotiff_header(t_.tif());
00389 if (gtif->gtif_number_of_keys() == 0) {
00390 delete gtif;
00391 return 0;
00392 }
00393
00394 return gtif;
00395 }
00396 #endif
00397
00398 vil_pixel_format vil_tiff_image::pixel_format() const
00399 {
00400 return h_->pix_fmt;
00401 }
00402
00403 vil_tiff_image::~vil_tiff_image()
00404 {
00405 delete h_;
00406 }
00407
00408
00409
00410
00411 char const* vil_tiff_image::file_format() const
00412 {
00413 return vil_tiff_format_tag;
00414 }
00415
00416 static void tif_swap16(vxl_byte *a, unsigned n)
00417 {
00418 for (unsigned i = 0; i < n * 2; i += 2)
00419 vcl_swap( a[i+0], a[i+1] );
00420 }
00421
00422 static void tif_swap32(vxl_byte *a, unsigned n)
00423 {
00424 for (unsigned i = 0; i < n * 4; i += 4)
00425 {
00426 vcl_swap( a[i+0], a[i+3] );
00427 vcl_swap( a[i+1], a[i+2] );
00428 }
00429 }
00430
00431 static void endian_swap( vxl_byte* a, unsigned n_bytes,
00432 unsigned bytes_per_sample)
00433 {
00434 switch ( bytes_per_sample ) {
00435 case 1: break;
00436 case 2: tif_swap16( a, n_bytes / 2 ); break;
00437 case 4: tif_swap32( a, n_bytes / 4 ); break;
00438 default: assert(!"Unsupported number of bytes per sample.");
00439 }
00440 }
00441
00442 template<> bool* tiff_byte_align_data<bool>(bool* in_data, unsigned num_samples, unsigned in_bits_per_sample, bool* out_data)
00443 {
00444 switch (sizeof(bool))
00445 {
00446 case 1:
00447 tiff_byte_align_data((vxl_byte*)in_data, num_samples, in_bits_per_sample, (vxl_byte*)out_data);
00448 break;
00449 case 2:
00450 tiff_byte_align_data((vxl_uint_16*)in_data, num_samples, in_bits_per_sample, (vxl_uint_16*)out_data);
00451 break;
00452 case 4:
00453 tiff_byte_align_data((vxl_uint_32*)in_data, num_samples, in_bits_per_sample, (vxl_uint_32*)out_data);
00454 break;
00455 default:
00456 assert(!"Unsupported size of bool in tiff file format.");
00457 }
00458 return out_data;
00459 }
00460
00461
00462 bool integral_type(unsigned bits_per_sample)
00463 {
00464 switch (bits_per_sample)
00465 {
00466 case 8:
00467 case 16:
00468 case 32: return true;
00469 default: break;
00470 }
00471 return false;
00472 }
00473
00474 template< class T >
00475 vil_memory_chunk_sptr
00476 tiff_maybe_byte_align_data(vil_memory_chunk_sptr in_data,
00477 unsigned num_samples,
00478 unsigned in_bits_per_sample,
00479 unsigned bytes_per_block)
00480 {
00481 if (!integral_type(in_bits_per_sample))
00482 {
00483 vil_memory_chunk_sptr new_memory = new vil_memory_chunk(bytes_per_block, in_data->pixel_format());
00484 #ifdef DEBUG
00485 vcl_cout << "Debug tiff_byte_align_data:"
00486 << " Num Samples = " << num_samples
00487 << " Input Bits/Sample = " << in_bits_per_sample
00488 << " Bytes/Block = " << bytes_per_block
00489 << " Output Bytes/Sample = " << vil_pixel_format_sizeof_components(in_data->pixel_format())
00490 << vcl_flush;
00491 #endif
00492 T* out_ptr = reinterpret_cast<T*>(new_memory->data());
00493 T* in_ptr = reinterpret_cast<T*>(in_data->data());
00494 tiff_byte_align_data(in_ptr, num_samples, in_bits_per_sample, out_ptr );
00495 #ifdef DEBUG
00496 vcl_cout << " .\n" << vcl_flush;
00497 #endif
00498 return new_memory;
00499 }
00500 return in_data;
00501 }
00502
00503
00504 template<> vil_memory_chunk_sptr tiff_maybe_byte_align_data<float>
00505 ( vil_memory_chunk_sptr in_data ,
00506 unsigned ,
00507 unsigned ,
00508 unsigned )
00509 { return in_data; }
00510
00511 template<> vil_memory_chunk_sptr tiff_maybe_byte_align_data<double>
00512 ( vil_memory_chunk_sptr in_data ,
00513 unsigned ,
00514 unsigned ,
00515 unsigned )
00516 { return in_data; }
00517
00518
00519
00520
00521 unsigned vil_tiff_image::nplanes() const
00522 {
00523 return h_->nplanes;
00524 }
00525
00526 unsigned vil_tiff_image::ni() const
00527 {
00528 if (h_->image_width.valid)
00529 return h_->image_width.val;
00530 return 0;
00531 }
00532
00533 unsigned vil_tiff_image::nj() const
00534 {
00535 if (h_->image_length.valid)
00536 return h_->image_length.val;
00537 return 0;
00538 }
00539
00540
00541 unsigned vil_tiff_image::size_block_i() const
00542 {
00543 if (h_->tile_width.valid)
00544 return static_cast<unsigned>(h_->tile_width.val);
00545 if (h_->image_width.valid)
00546 return static_cast<unsigned>(h_->image_width.val);
00547 return 0;
00548 }
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
00613 vil_image_view_base_sptr vil_tiff_image::
00614 view_from_buffer(vil_pixel_format& fmt, vil_memory_chunk_sptr const& buf,
00615 unsigned samples_per_block, unsigned bits_per_sample
00616 ) const
00617 {
00618 vil_image_view_base_sptr view = 0;
00619 vil_memory_chunk_sptr buf_out;
00620 unsigned spp = h_->samples_per_pixel.val;
00621 switch (fmt)
00622 {
00623 #define GET_BLOCK_CASE(FORMAT, T) \
00624 case FORMAT: { \
00625 vil_image_view_base_sptr view; \
00626 buf_out = tiff_maybe_byte_align_data<T>(buf, samples_per_block, \
00627 bits_per_sample, \
00628 samples_per_block*vil_pixel_format_sizeof_components(fmt)); \
00629 view = new vil_image_view<T>(buf_out, reinterpret_cast<T*>(buf_out->data()), \
00630 size_block_i(), size_block_j(), \
00631 spp, spp, size_block_i()*spp, 1); \
00632 return view; }
00633 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00634 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte);
00635 #if VXL_HAS_INT_64
00636 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
00637 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
00638 #endif
00639 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00640 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_32, vxl_int_32);
00641 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00642 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_16, vxl_int_16);
00643 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_BOOL, bool);
00644 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_FLOAT, float);
00645 GET_BLOCK_CASE(VIL_PIXEL_FORMAT_DOUBLE, double);
00646 #undef GET_BLOCK_CASE
00647 default:
00648 assert(!"Unknown vil data type in tiff file format");
00649 break;
00650 }
00651 return view;
00652 }
00653
00654
00655
00656 vil_image_view_base_sptr
00657 vil_tiff_image::get_block( unsigned block_index_i,
00658 unsigned block_index_j ) const
00659 {
00660
00661 assert(h_->is_tiled() || h_->is_striped());
00662
00663
00664
00665
00666
00667 if (nimages_>1)
00668 {
00669 if (TIFFSetDirectory(t_.tif(), index_)<=0)
00670 return 0;
00671 vil_tiff_header* h = new vil_tiff_header(t_.tif());
00672
00673 vil_tiff_image* ti = (vil_tiff_image*)this;
00674 delete h_;
00675 ti->h_=h;
00676 }
00677
00678 vil_image_view_base_sptr view = 0;
00679
00680
00681
00682 unsigned encoded_block_size = h_->encoded_bytes_per_block();
00683 assert(encoded_block_size>0);
00684 vxl_byte* data = new vxl_byte[encoded_block_size];
00685
00686
00687 unsigned blk_indx = this->block_index(block_index_i, block_index_j);
00688
00689
00690 vil_pixel_format fmt = vil_pixel_format_component_format(h_->pix_fmt);
00691
00692
00693 vil_memory_chunk_sptr buf =
00694 new vil_memory_chunk(encoded_block_size, fmt);
00695 unsigned expanded_sample_bytes = vil_pixel_format_sizeof_components(fmt);
00696
00697
00698 if (h_->is_tiled())
00699 {
00700 if (TIFFReadEncodedTile(t_.tif(), blk_indx, data, (tsize_t) -1)<=0)
00701 {
00702 delete [] data;
00703 return view;
00704 }
00705 this->copy_byte_block(data, encoded_block_size, buf);
00706 delete [] data;
00707 if (h_->need_byte_swap())
00708 endian_swap( reinterpret_cast<vxl_byte*>(buf->data()),
00709 encoded_block_size,
00710 expanded_sample_bytes);
00711 return this->fill_block_from_tile(buf);
00712 }
00713
00714 if (h_->is_striped())
00715 {
00716 if (TIFFReadEncodedStrip(t_.tif(), blk_indx, data, (tsize_t) -1)<=0)
00717 {
00718 delete [] data;
00719 return view;
00720 }
00721 this->copy_byte_block(data, encoded_block_size, buf);
00722 delete [] data;
00723 if (h_->need_byte_swap())
00724 endian_swap( reinterpret_cast<vxl_byte*>(buf->data()),
00725 encoded_block_size,
00726 expanded_sample_bytes);
00727 return this->fill_block_from_strip(buf);
00728 }
00729
00730 return view;
00731 }
00732
00733
00734
00735
00736 vil_image_view_base_sptr vil_tiff_image::
00737 fill_block_from_tile(vil_memory_chunk_sptr const & buf) const
00738 {
00739 vil_image_view_base_sptr view = 0;
00740
00741
00742 unsigned samples_per_block = this->samples_per_block();
00743 assert(samples_per_block>0);
00744
00745 vil_pixel_format fmt = vil_pixel_format_component_format(h_->pix_fmt);
00746 view = view_from_buffer(fmt, buf, samples_per_block, h_->bits_per_sample.val);
00747 return view;
00748 }
00749
00750
00751
00752
00753
00754
00755
00756
00757 vil_image_view_base_sptr vil_tiff_image::fill_block_from_strip(vil_memory_chunk_sptr const & buf) const
00758 {
00759 vil_image_view_base_sptr view = 0;
00760 vxl_uint_32 tl = size_block_j();
00761
00762 unsigned bpl = h_->bytes_per_line();
00763 unsigned bytes_per_strip = h_->bytes_per_strip();
00764 unsigned lines_per_strip = bytes_per_strip/bpl;
00765
00766 vil_pixel_format fmt = vil_pixel_format_component_format(h_->pix_fmt);
00767 unsigned expanded_bytes_per_sample =
00768 vil_pixel_format_sizeof_components(fmt);
00769 unsigned spl = h_->samples_per_line();
00770 unsigned bytes_expanded_line = spl*expanded_bytes_per_sample;
00771
00772
00773 unsigned expanded_bytes_per_strip = tl*bytes_expanded_line;
00774
00775
00776 vxl_byte* buf_ptr = reinterpret_cast<vxl_byte*>(buf->data());
00777
00778
00779 vil_memory_chunk_sptr line_buf =
00780 new vil_memory_chunk(bpl, fmt);
00781
00782
00783 vil_memory_chunk_sptr zero_buf =
00784 new vil_memory_chunk(bytes_expanded_line, fmt);
00785 vxl_byte* zero_ptr = reinterpret_cast<vxl_byte*>(zero_buf->data());
00786 for (unsigned i = 0; i<bytes_expanded_line; ++i)
00787 zero_ptr[i]=0;
00788
00789
00790 vil_memory_chunk_sptr block_buf =
00791 new vil_memory_chunk(expanded_bytes_per_strip, fmt);
00792 vxl_byte* block_ptr = reinterpret_cast<vxl_byte*>(block_buf->data());
00793
00794 for (unsigned j = 0; j<tl; ++j, buf_ptr+=bpl,
00795 block_ptr+=bytes_expanded_line)
00796 {
00797 if (j<lines_per_strip)
00798 {
00799
00800 copy_byte_block(buf_ptr, bpl, line_buf);
00801 vil_memory_chunk_sptr out_line_buf;
00802 switch (fmt)
00803 {
00804 #define GET_LINE_CASE(FORMAT, T) \
00805 case FORMAT:\
00806 out_line_buf = \
00807 tiff_maybe_byte_align_data<T>(line_buf,\
00808 spl, h_->bits_per_sample.val,\
00809 bytes_expanded_line); \
00810 break
00811 GET_LINE_CASE(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00812 GET_LINE_CASE(VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte);
00813 #if VXL_HAS_INT_64
00814 GET_LINE_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
00815 GET_LINE_CASE(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
00816 #endif
00817 GET_LINE_CASE(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00818 GET_LINE_CASE(VIL_PIXEL_FORMAT_INT_32, vxl_int_32);
00819 GET_LINE_CASE(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00820 GET_LINE_CASE(VIL_PIXEL_FORMAT_INT_16, vxl_int_16);
00821 GET_LINE_CASE(VIL_PIXEL_FORMAT_BOOL, bool);
00822 GET_LINE_CASE(VIL_PIXEL_FORMAT_FLOAT, float);
00823 GET_LINE_CASE(VIL_PIXEL_FORMAT_DOUBLE, double);
00824 #undef GET_LINE_CASE
00825 default:
00826 assert(!"Unknown vil data type in tiff file format");
00827 break;
00828 }
00829
00830
00831 vxl_byte* out_line_buf_ptr =
00832 reinterpret_cast<vxl_byte*>(out_line_buf->data());
00833 vcl_memcpy(block_ptr, out_line_buf_ptr, bytes_expanded_line);
00834 }
00835 else
00836 vcl_memcpy(block_ptr, zero_ptr, bytes_expanded_line);
00837 }
00838
00839 return this->view_from_buffer(fmt, block_buf, spl*tl,
00840 expanded_bytes_per_sample*8);
00841 }
00842
00843 void vil_tiff_image::pad_block_with_zeros(unsigned ioff, unsigned joff,
00844 unsigned iclip, unsigned jclip,
00845 unsigned bytes_per_pixel,
00846 vxl_byte* block_buf)
00847 {
00848 unsigned jstep = size_block_i()*bytes_per_pixel;
00849 unsigned row_start = ioff*bytes_per_pixel;
00850 unsigned bptr = 0;
00851
00852 if (ioff>0||joff>0)
00853 for (unsigned j = 0; j<joff-1; ++j)
00854 {
00855 unsigned row_ptr = row_start;
00856 for (unsigned i = 0; i<ioff-1; ++i)
00857 {
00858 for (unsigned p = 0; p<nplanes(); ++p)
00859 *(block_buf + bptr + row_ptr + p) = 0;
00860 row_ptr += bytes_per_pixel;
00861 }
00862 bptr += jstep;
00863 }
00864 bptr = jstep*jclip;
00865 row_start = iclip*bytes_per_pixel;
00866 if (iclip>0||jclip>0)
00867 for (unsigned j = jclip; j<size_block_j(); ++j)
00868 {
00869 unsigned row_ptr = row_start;
00870 for (unsigned i = iclip; i<size_block_i(); ++i)
00871 {
00872 for (unsigned p = 0; p<nplanes(); ++p)
00873 *(block_buf + bptr + row_ptr + p) = 0;
00874 row_ptr += bytes_per_pixel;
00875 }
00876 bptr += jstep;
00877 }
00878 }
00879
00880 void vil_tiff_image::fill_block_from_view(unsigned bi, unsigned bj,
00881 unsigned i0, unsigned j0,
00882 unsigned ioff, unsigned joff,
00883 unsigned iclip, unsigned jclip,
00884 const vil_image_view_base& im,
00885 vxl_byte*& block_buf)
00886 {
00887 unsigned bytes_per_sample = h_->bytes_per_sample();
00888 unsigned bytes_per_pixel = bytes_per_sample*nplanes();
00889 unsigned sbi = size_block_i(), sbj = size_block_j();
00890 unsigned bytes_per_block=bytes_per_pixel*sbi*sbj;
00891 unsigned view_i0 = bi*sbi-i0, view_j0 = bj*sbj-j0;
00892 unsigned block_jstep = sbi*bytes_per_pixel;
00893 #if 0
00894
00895 unsigned view_istep = 1, view_jstep = im.ni()*bytes_per_pixel, view_pstep = 1;
00896 #endif
00897 vcl_ptrdiff_t view_istep, view_jstep, view_pstep;
00898 vxl_byte* view_buf;
00899
00900 switch (h_->pix_fmt)
00901 {
00902 #define GET_VIEW_PTR(FORMAT, T) \
00903 case FORMAT: { \
00904 vil_image_view<T> view = static_cast<const vil_image_view<T>& >(im);\
00905 view_istep = view.istep(); view_jstep = view.jstep(); view_pstep = view.planestep(); \
00906 view_buf = reinterpret_cast<vxl_byte*>(view.top_left_ptr());\
00907 } break
00908 GET_VIEW_PTR(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00909 GET_VIEW_PTR(VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte);
00910 #if VXL_HAS_INT_64
00911 GET_VIEW_PTR(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
00912 GET_VIEW_PTR(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
00913 #endif
00914 GET_VIEW_PTR(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00915 GET_VIEW_PTR(VIL_PIXEL_FORMAT_INT_32, vxl_int_32);
00916 GET_VIEW_PTR(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00917 GET_VIEW_PTR(VIL_PIXEL_FORMAT_INT_16, vxl_int_16);
00918 GET_VIEW_PTR(VIL_PIXEL_FORMAT_BOOL, bool);
00919 GET_VIEW_PTR(VIL_PIXEL_FORMAT_FLOAT, float);
00920 GET_VIEW_PTR(VIL_PIXEL_FORMAT_DOUBLE, double);
00921 #undef GET_VIEW_PTR
00922 default:
00923 assert(!"Unknown vil data type.");
00924 return;
00925 }
00926
00927 unsigned bptr = joff*block_jstep;
00928 unsigned ibstart = ioff*bytes_per_pixel;
00929 vcl_ptrdiff_t vistp = view_istep*bytes_per_sample;
00930 vcl_ptrdiff_t vjstp = view_jstep*bytes_per_sample;
00931 vcl_ptrdiff_t vpstp = view_pstep*bytes_per_sample;
00932
00933
00934
00935 vcl_ptrdiff_t vptr = (view_j0 + joff)*vjstp;
00936 unsigned ivstart = (view_i0 + ioff)*bytes_per_pixel;
00937 for (unsigned j = joff; j<jclip; ++j)
00938 {
00939 vcl_ptrdiff_t vrow_ptr = ivstart;
00940 vcl_ptrdiff_t brow_ptr = ibstart;
00941 for (unsigned i = ioff; i<iclip; ++i)
00942 {
00943 vcl_ptrdiff_t bpptr = 0, vpptr = 0;
00944 for (unsigned p = 0; p<nplanes(); ++p)
00945 {
00946 for (unsigned b = 0; b<bytes_per_sample; ++b)
00947 *(block_buf + bptr + brow_ptr + bpptr + b) =
00948 *(view_buf + vptr + vrow_ptr + vpptr + b);
00949 bpptr += bytes_per_sample; vpptr += vpstp;
00950 }
00951 brow_ptr += bytes_per_pixel; vrow_ptr += vistp;
00952 }
00953 bptr += block_jstep; vptr += vjstp;
00954 }
00955
00956
00957 if (this->pixel_format() == VIL_PIXEL_FORMAT_BOOL)
00958 {
00959 unsigned outsize = (bytes_per_block+7*sizeof(bool))/(8*sizeof(bool));
00960 vxl_byte* outbuf = new vxl_byte[outsize];
00961 this->bitpack_block(bytes_per_block, block_buf, outbuf);
00962 delete [] block_buf;
00963 block_buf = outbuf;
00964 }
00965 }
00966
00967 bool vil_tiff_image::write_block_to_file(unsigned bi, unsigned bj,
00968 unsigned block_size_bytes,
00969 vxl_byte* block_buf)
00970 {
00971 unsigned blk_indx = this->block_index(bi, bj);
00972 if (h_->is_tiled())
00973 return TIFFWriteEncodedTile(t_.tif(), blk_indx, block_buf,
00974 block_size_bytes)>0;
00975 if (h_->is_striped())
00976 return TIFFWriteEncodedStrip(t_.tif(), blk_indx, block_buf,
00977 block_size_bytes ) > 0;
00978 return false;
00979 }
00980
00981
00982
00983 void vil_tiff_image::bitpack_block(unsigned bytes_per_block,
00984 vxl_byte* in_block_buf,
00985 vxl_byte* out_block_buf)
00986 {
00987 unsigned bytes_per_bool = sizeof(bool);
00988 vxl_byte* bl = new vxl_byte[bytes_per_bool];
00989 unsigned bitctr = 0;
00990 unsigned outctr = 0;
00991 vxl_byte packed_byte=0;
00992 for (unsigned i = 0; i<bytes_per_block; )
00993 {
00994
00995 if (bitctr==8)
00996 {
00997 bitctr = 0;
00998 out_block_buf[outctr] = packed_byte;
00999 packed_byte = 0;
01000 ++outctr;
01001 }
01002
01003 for (unsigned b = 0; b<bytes_per_bool; ++b)
01004 bl[b] = *(in_block_buf + i + b);
01005 bool blv = *(reinterpret_cast<bool*>(bl));
01006 if (blv)
01007 packed_byte |= vxl_byte(1<<(7-bitctr));
01008 else
01009 packed_byte &= vxl_byte(~(1<<(7-bitctr)));
01010 ++bitctr;
01011
01012 i+=bytes_per_bool;
01013 if (i>=bytes_per_block)
01014 out_block_buf[outctr] = packed_byte;
01015 }
01016 delete [] bl;
01017 }
01018
01019
01020
01021
01022
01023
01024
01025 bool vil_tiff_image::put_block(unsigned bi, unsigned bj, unsigned i0,
01026 unsigned j0, const vil_image_view_base& im)
01027 {
01028
01029
01030
01031 unsigned ioff =0, joff = 0;
01032 unsigned sbi = size_block_i(), sbj = size_block_j();
01033 unsigned iclip =sbi , jclip = sbj;
01034
01035 if (bi*sbi<i0&&(bi+1)*sbi>i0)
01036 if (!block_i_offset(bi, i0, ioff))
01037 return false;
01038
01039 if (bj*sbj<j0&&(bj+1)*sbj>j0)
01040 if (!block_j_offset(bj, j0, joff))
01041 return false;
01042
01043
01044
01045
01046
01047 if ( (bi+1)*sbi > (im.ni()+i0) )
01048 {
01049 iclip = (i0+im.ni())-bi*sbi;
01050 if (iclip > sbi)
01051 return false;
01052 }
01053
01054
01055 if ( (bj+1)*sbj > (im.nj()+j0) )
01056 {
01057 jclip = (j0+im.nj())-bj*sbj;
01058 if (jclip > sbj)
01059 return false;
01060 }
01061 unsigned bps = h_->bytes_per_sample();
01062 unsigned bytes_per_pixel = bps*nplanes();
01063
01064 unsigned bytes_per_block = bytes_per_pixel*sbi*sbj;
01065
01066
01067
01068 vxl_byte* block_buf = new vxl_byte[bytes_per_block];
01069
01070 this->pad_block_with_zeros(ioff, joff, iclip, jclip,
01071 bytes_per_pixel, block_buf);
01072
01073
01074 this->fill_block_from_view(bi, bj, i0, j0, ioff, joff, iclip, jclip,
01075 im, block_buf);
01076
01077 bool good_write = write_block_to_file(bi, bj, bytes_per_block, block_buf);
01078 delete [] block_buf;
01079 return good_write;
01080 }
01081
01082 bool vil_tiff_image::put_view(const vil_image_view_base& im,
01083 unsigned i0, unsigned j0)
01084 {
01085 if (!vil_image_resource::view_fits(im, i0, j0))
01086 {
01087 vil_exception_warning(vil_exception_out_of_bounds("vil_tiff_image::put_view"));
01088 return false;
01089 }
01090
01091 unsigned tw = size_block_i(), tl = size_block_j();
01092 if (tw==0||tl==0)
01093 return false;
01094 unsigned bi_start = i0/tw, bi_end = (i0+im.ni()-1)/tw;
01095 unsigned bj_start = j0/tl, bj_end = (j0+im.nj()-1)/tl;
01096 for (unsigned bi = bi_start; bi<=bi_end; ++bi)
01097 for (unsigned bj = bj_start; bj<=bj_end; ++bj)
01098 if (!this->put_block(bi, bj, i0, j0, im))
01099 return false;
01100 return true;
01101 }
01102
01103
01104 bool vil_tiff_image::put_block( unsigned block_index_i,
01105 unsigned block_index_j,
01106 const vil_image_view_base& blk )
01107 {
01108 if (blk.ni()==0||blk.nj()==0)
01109 return false;
01110 unsigned sbi = this->size_block_i(), sbj = this->size_block_j();
01111 unsigned bps = h_->bytes_per_sample();
01112 unsigned bytes_per_pixel = bps*nplanes();
01113
01114 unsigned bytes_per_block = bytes_per_pixel*sbi*sbj;
01115
01116
01117 vxl_byte* block_buf = new vxl_byte[bytes_per_block];
01118
01119 this->fill_block_from_view(0, 0, 0, 0, 0, 0,sbi, sbj, blk, block_buf);
01120
01121
01122 bool good_write = write_block_to_file(block_index_i, block_index_j, bytes_per_block, block_buf);
01123 delete [] block_buf;
01124 return good_write;
01125 }
01126
01127
01128 static bool level_compare(tiff_pyramid_level* const l1, tiff_pyramid_level* const l2)
01129 {
01130 assert(l1&&l2);
01131 return l1->ni_ > l2->ni_;
01132 }
01133
01134
01135 void vil_tiff_pyramid_resource::normalize_scales()
01136 {
01137 unsigned nlevels = this->nlevels();
01138 if (nlevels==0)
01139 return;
01140 levels_[0]->scale_ = 1.0f;
01141 if (nlevels==1)
01142 return;
01143 float ni0 = static_cast<float>(levels_[0]->ni_);
01144 for (unsigned i = 1; i<nlevels; ++i)
01145 levels_[i]->scale_ = static_cast<float>(levels_[i]->ni_)/ni0;
01146 }
01147
01148
01149 tiff_pyramid_level* vil_tiff_pyramid_resource::closest(const float scale) const
01150 {
01151 unsigned nlevels = this->nlevels();
01152 if (nlevels == 0)
01153 return 0;
01154 if (nlevels == 1)
01155 return levels_[0];
01156 float mind = 1.0e08f;
01157 unsigned lmin = 0;
01158 for (unsigned i = 0; i<nlevels; ++i)
01159 {
01160 float ds = vcl_fabs(scale - levels_[i]->scale_);
01161 if (ds<mind)
01162 {
01163 mind = ds;
01164 lmin = i;
01165 }
01166 }
01167 tiff_pyramid_level* pl = levels_[lmin];
01168 if (pl)
01169 pl->cur_level_ = lmin;
01170 return pl;
01171 }
01172
01173 vil_tiff_pyramid_resource::vil_tiff_pyramid_resource()
01174 : read_(true), t_(0)
01175 {
01176 }
01177
01178 vil_tiff_pyramid_resource::
01179 vil_tiff_pyramid_resource(tif_smart_ptr const& t, bool read)
01180 : read_(read), t_(t)
01181 {
01182 bool trace = false;
01183 if (!read)
01184 return;
01185
01186 while (true)
01187 {
01188 vil_tiff_header h(t_.tif());
01189 if (trace)
01190 vcl_cerr << "In vil_tiff_pyramid_resource constructor"
01191 << " constructed header\n"
01192 << "n-levels = " << this->nlevels() << '\n';
01193 tiff_pyramid_level* pl = new tiff_pyramid_level(this->nlevels(),
01194 h.image_width.val,
01195 h.image_length.val,
01196 h.nplanes,
01197 h.pix_fmt);
01198 levels_.push_back(pl);
01199 if (trace)
01200 vcl_cerr << "In vil_tiff_pyramid_resource constructor"
01201 << " constructed level\n";
01202 int status = TIFFReadDirectory(t_.tif());
01203 if (trace)
01204 vcl_cerr << "In vil_tiff_pyramid_resource constructor"
01205 << " Read new directory\n";
01206
01207 if (!status)
01208 break;
01209 }
01210 if (trace)
01211 vcl_cerr << "In vil_tiff_pyramid_resource constructor"
01212 << " Begin sorting\n";
01213
01214 vcl_sort(levels_.begin(), levels_.end(), level_compare);
01215
01216 this->normalize_scales();
01217 }
01218
01219 vil_tiff_pyramid_resource::~vil_tiff_pyramid_resource()
01220 {
01221 for (unsigned L = 0; L<this->nlevels(); ++L)
01222 delete levels_[L];
01223 }
01224
01225
01226 vil_image_view_base_sptr
01227 vil_tiff_pyramid_resource::get_copy_view(unsigned i0, unsigned n_i,
01228 unsigned j0, unsigned n_j,
01229 unsigned level) const
01230 {
01231 unsigned nl = this->nlevels();
01232 if (level>=nl)
01233 return vil_image_view_base_sptr();
01234 vil_image_resource_sptr resc = this->get_resource(level);
01235
01236 float scale = levels_[level]->scale_;
01237 float fi0 = vcl_floor(scale*i0), fj0 = vcl_floor(scale*j0);
01238 float fni = vcl_floor(scale*n_i), fnj = vcl_floor(scale*n_j);
01239 unsigned si0 = static_cast<unsigned>(fi0);
01240 unsigned sj0 = static_cast<unsigned>(fj0);
01241 unsigned sni = static_cast<unsigned>(fni);
01242 if (sni == 0) sni = 1;
01243 unsigned snj = static_cast<unsigned>(fnj);
01244 if (snj == 0) snj = 1;
01245 vil_image_view_base_sptr view = resc->get_copy_view(si0, sni, sj0, snj);
01246 #if 0 //DON'T NEED CLEAR?
01247 resc->clear_TIFF();
01248 #endif
01249 return view;
01250 }
01251
01252
01253
01254
01255
01256 vil_image_view_base_sptr
01257 vil_tiff_pyramid_resource::get_copy_view(unsigned i0, unsigned n_i,
01258 unsigned j0, unsigned n_j,
01259 const float scale,
01260 float& actual_scale) const
01261 {
01262
01263 tiff_pyramid_level* pl = this->closest(scale);
01264 if (!pl)
01265 return 0;
01266 actual_scale = pl->scale_;
01267 return this->get_copy_view(i0, n_i, j0, n_j, pl->cur_level_);
01268 }
01269
01270
01271
01272 bool vil_tiff_pyramid_resource::put_resource(vil_image_resource_sptr const& ir)
01273 {
01274 unsigned level = this->nlevels();
01275 unsigned ni = ir->ni(), nj = ir->nj();
01276 unsigned nplanes = ir->nplanes();
01277 vil_pixel_format fmt = ir->pixel_format();
01278 vil_blocked_image_resource_sptr bir = blocked_image_resource(ir);
01279 unsigned sbi = 0, sbj = 0;
01280 if (bir) { sbi = bir->size_block_i(); sbj = bir->size_block_j(); }
01281
01282 vil_tiff_header* h = new vil_tiff_header(t_.tif(), ni, nj, nplanes,
01283 fmt, sbi, sbj);
01284
01285
01286 TIFFSetField(t_.tif(), TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
01287
01288 TIFFSetField(t_.tif(), TIFFTAG_PAGENUMBER,level, 3);
01289 vil_tiff_image* ti = new vil_tiff_image(t_, h, level);
01290 vil_image_resource_sptr resc = ti;
01291 if (!vil_copy_deep(ir, resc))
01292 return false;
01293 #if 0 //DON'T NEED CLEAR?
01294 ti->clear_TIFF();
01295 #endif
01296 tiff_pyramid_level* pl = new tiff_pyramid_level((unsigned int)(levels_.size()), ni, nj, nplanes, fmt);
01297 levels_.push_back(pl);
01298 int status = TIFFWriteDirectory(t_.tif());
01299 return status == 1 ;
01300 }
01301
01302 vil_image_resource_sptr vil_tiff_pyramid_resource::get_resource(const unsigned level) const
01303 {
01304 unsigned nl = this->nlevels();
01305 if (level>=nl)
01306 return 0;
01307
01308 unsigned header_index = levels_[level]->header_index_;
01309
01310 if (TIFFSetDirectory(t_.tif(), header_index)<=0)
01311 return 0;
01312 vil_tiff_header* h = new vil_tiff_header(t_.tif());
01313 vil_tiff_image* i = new vil_tiff_image(t_, h, nl);
01314 i->set_index(header_index);
01315 return i;
01316 }