OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimTiffTileSource.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author: David Burken
8 // Frank Warmerdam (warmerdam@pobox.com)
9 //
10 // Description:
11 //
12 // Contains class definition for TiffTileSource.
13 //
14 //*******************************************************************
15 // $Id: ossimTiffTileSource.cpp 23548 2015-09-28 21:01:36Z dburken $
16 
21 #include <ossim/base/ossimCommon.h>
24 #include <ossim/base/ossimTrace.h>
25 #include <ossim/base/ossimIpt.h>
26 #include <ossim/base/ossimDpt.h>
28 #include <ossim/base/ossimIoStream.h> /* for ossimIOMemoryStream */
31 #include <ossim/base/ossimDatum.h>
36 #include <xtiffio.h>
37 #include <geo_normalize.h>
38 #include <cstdlib> /* for abs(int) */
41 
42 RTTI_DEF1(ossimTiffTileSource, "ossimTiffTileSource", ossimImageHandler)
43 
44 static ossimTrace traceDebug("ossimTiffTileSource:debug");
45 
46 #define OSSIM_TIFF_UNPACK_R4(value) ( (value)&0x000000FF)
47 #define OSSIM_TIFF_UNPACK_G4(value) ( ((value)>>8)&0x000000FF)
48 #define OSSIM_TIFF_UNPACK_B4(value) ( ((value)>>16)&0x000000FF)
49 #define OSSIM_TIFF_UNPACK_A4(value) ( ((value)>>24)&0x000000FF)
50 
51 //---
52 // OSSIM_BUFFER_SCAN_LINE_READS:
53 // If set to 1 ossimTiffTileSource::loadFromScanLine method will buffer image
54 // width by tile height. If set to 0 one line will be read at a time which
55 // conserves memory on wide images or tall tiles.
56 //
57 // Buffered read is faster but uses more memory. Non-buffered slower less
58 // memory.
59 //
60 // Only affects reading strip tiffs.
61 //---
62 #define OSSIM_BUFFER_SCAN_LINE_READS 1
63 
64 
65 //*******************************************************************
66 // Public Constructor:
67 //*******************************************************************
69  :
71  theTiffPtr(0),
72  theTile(0),
73  theBuffer(0),
74  theBufferSize(0),
75  theBufferRect(0, 0, 0, 0),
76  theBufferRLevel(0),
77  theCurrentTileWidth(0),
78  theCurrentTileHeight(0),
79  theSamplesPerPixel(0),
80  theBitsPerSample(0),
81  theSampleFormatUnit(0),
82  theMaxSampleValue(ossim::nan()),
83  theMinSampleValue(ossim::nan()),
84  theNullSampleValue(ossim::nan()),
85  theNumberOfDirectories(0),
86  theCurrentDirectory(0),
87  theR0isFullRes(false),
88  theBytesPerPixel(0),
89  theScalarType(OSSIM_SCALAR_UNKNOWN),
90  theApplyColorPaletteFlag(true),
91  theImageWidth(0),
92  theImageLength(0),
93  theReadMethod(0),
94  thePlanarConfig(0),
95  thePhotometric(0),
96  theRowsPerStrip(0),
97  theImageTileWidth(0),
98  theImageTileLength(0),
99  theImageDirectoryList(0),
100  theCurrentTiffRlevel(0),
101  theCompressionType(0),
102  theOutputBandList(0)
103 {}
104 
106 {
107  close();
108 }
109 
111  const ossimIrect& tile_rect, ossim_uint32 resLevel )
112 {
113  if ( theTile.valid() == false )
114  {
115  allocateTile(); // First time through...
116  }
117 
118  if ( theTile.valid() )
119  {
120  // Image rectangle must be set prior to calling getTile.
121  theTile->setImageRectangle(tile_rect);
122 
123  if ( getTile( theTile.get(), resLevel ) == false )
124  {
126  {
127  theTile->makeBlank();
128  }
129  }
130  }
131 
132  return theTile;
133 }
134 
136  ossim_uint32 resLevel)
137 {
138  static const char MODULE[] = "ossimTiffTileSource::getTile(ossimImageData*, resLevel)";
139 
140  bool status = false;
141 
142  //---
143  // Not open, this tile source bypassed, or invalid res level,
144  // return a blank tile.
145  //---
146  if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
147  result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
148  {
149  result->ref(); // Increment ref count.
150 
151  //---
152  // Check for overview tile. Some overviews can contain r0 so always
153  // call even if resLevel is 0. Method returns true on success, false
154  // on error.
155  //---
156  status = getOverviewTile(resLevel, result);
157 
158  if (!status) // Did not get an overview tile.
159  {
160  status = true;
161 
162  ossim_uint32 level = resLevel;
163 
164  //---
165  // If we have r0 our reslevels are the same as the callers so
166  // no adjustment necessary.
167  //---
168  if (theStartingResLevel && !theR0isFullRes) // Used as overview.
169  {
170  //---
171  // If we have r0 our reslevels are the same as the callers so
172  // no adjustment necessary.
173  //---
174  if (level >= theStartingResLevel)
175  {
176  //---
177  // Adjust the level to be relative to the reader using this
178  // as overview.
179  //---
180  level -= theStartingResLevel;
181  }
182  }
183 
184  ossimIrect tile_rect = result->getImageRectangle();
185 
186  //---
187  // This should be the zero base image rectangle for this res level.
188  // Note passed the non adjusted resLevel by design.
189  //---
190  ossimIrect image_rect = getImageRectangle(resLevel);
191 
192  // See if any point of the requested tile is in the image.
193  if ( tile_rect.intersects(image_rect) )
194  {
195  // Initialize the tile if needed as we're going to stuff it.
196  if (result->getDataObjectStatus() == OSSIM_NULL)
197  {
198  result->initialize();
199  }
200 
201  bool reallocateBuffer = false;
202  if ( (tile_rect.width() != theCurrentTileWidth) ||
203  (tile_rect.height() != theCurrentTileHeight) )
204  {
205  // Current tile size must be set prior to allocatBuffer call.
206  theCurrentTileWidth = tile_rect.width();
207  theCurrentTileHeight = tile_rect.height();
208 
209  reallocateBuffer = true;
210  }
211 
213  {
215  if (status)
216  {
217  reallocateBuffer = true;
218  }
219  }
220 
221  if (status)
222  {
223  if (reallocateBuffer)
224  {
225  // NOTE: Using this buffer will be a thread issue. (drb)
227  }
228  }
229 
230  if ( status )
231  {
232  ossimIrect clip_rect = tile_rect.clipToRect( image_rect );
233 
234  if ( !tile_rect.completely_within( clip_rect ) )
235  {
236  //---
237  // We're not going to fill the whole tile so start with a
238  // blank tile.
239  //---
240  result->makeBlank();
241  }
242 
243  // Load the tile buffer with data from the tif.
244  if ( loadTile( tile_rect, clip_rect, result ) )
245  {
246  result->validate();
247  status = true;
248  }
249  else
250  {
251  // Would like to change this to throw ossimException.(drb)
252  status = false;
253  if(traceDebug())
254  {
255  // Error in filling buffer.
257  << MODULE
258  << " Error filling buffer. Return status = false..."
259  << std::endl;
260  }
261  }
262 
263  } // matches: if (status)
264 
265  } // matches: if ( zeroBasedTileRect.intersects(image_rect) )
266  else
267  {
268  // No part of requested tile within the image rectangle.
269  status = true; // Not an error.
270  result->makeBlank();
271  }
272 
273  } // matches: if (!status)
274 
275  result->unref(); // Decrement ref count.
276 
277  } // matches: if( isOpen() && isSourceEnabled() && isValidRLevel(level) )
278 
279  return status;
280 }
281 
282 //*******************************************************************
283 // Public method:
284 //*******************************************************************
286  const char* prefix) const
287 {
288  bool result = ossimImageHandler::saveState(kwl, prefix);
289 
290  if ( result )
291  {
292  if ( isBandSelector() && theOutputBandList.size() )
293  {
294  if ( isIdentityBandList( theOutputBandList ) == false )
295  {
296  // If we're not identity output the bands.
297  ossimString bandsString;
299  kwl.add(prefix,
301  bandsString,
302  true);
303  }
304  }
305 
306  kwl.add(prefix,
307  "apply_color_palette_flag",
309  true);
310  }
311 
312  return result;
313 }
314 
315 //*******************************************************************
316 // Public method:
317 //*******************************************************************
319  const char* prefix)
320 {
321  bool result = false;
322  theOutputBandList.clear();
323 
324  if (ossimImageHandler::loadState(kwl, prefix))
325  {
326  std::string pfx = ( prefix ? prefix : "" );
327  std::string key = "apply_color_palette_flag";
328  ossimString value;
329 
330  value.string() = kwl.findKey( pfx, key );
331  if ( value.size() )
332  {
334  }
335  else
336  {
338  }
339 
341  value.string() = kwl.findKey( pfx, key );
342  if ( value.size() )
343  {
345  }
346 
347  if ( open() )
348  {
349  // Set the band list after open so that the overview also gets set.
350  result = true;
351  }
352  }
353  return result;
354 }
355 
357 {
358  if (theTiffPtr)
359  {
360  close();
361  }
362  theImageFile = image_file;
363  return open();
364 }
365 
367 {
368  if(theTiffPtr)
369  {
370  XTIFFClose(theTiffPtr);
371  theTiffPtr = 0;
372  }
373  if(m_streamAdaptor)
374  {
375  m_streamAdaptor->close();
376  m_streamAdaptor.reset();
377  }
378 
379  theImageWidth.clear();
380  theImageLength.clear();
381  theReadMethod.clear();
382  thePlanarConfig.clear();
383  thePhotometric.clear();
384  theRowsPerStrip.clear();
385  theImageTileWidth.clear();
386  theImageTileLength.clear();
387  if (theBuffer)
388  {
389  delete [] theBuffer;
390  theBuffer = 0;
391  theBufferSize = 0;
392  }
394 }
395 
396 bool ossimTiffTileSource::open( std::shared_ptr<ossim::istream>& str,
397  const std::string& connectionString )
398 {
399  static const char MODULE[] = "ossimTiffTileSource::open";
400  if(isOpen())
401  {
402  close();
403  }
404 
405  // Check for empty file name.
406  if ( connectionString.empty() )
407  {
408  return false;
409  }
410  theImageFile = ossimFilename(connectionString);
411  theImageDirectoryList.clear();
412 
413  //---
414  // Note: The 'm' in "rm" is to tell TIFFOpen to not memory map the file.
415  //---
416  //theTiffPtr = XTIFFOpen(theImageFile.c_str(), "rm");
417  //m_streamAdaptor = std::make_shared<TiffStreamAdaptor>(this);
418  m_streamAdaptor = std::make_shared<ossim::TiffIStreamAdaptor>(str,
419  connectionString);
420 
421  theTiffPtr = XTIFFClientOpen(connectionString.c_str(), "rm",
422  (thandle_t)m_streamAdaptor.get(),
423  ossim::TiffIStreamAdaptor::tiffRead,
424  ossim::TiffIStreamAdaptor::tiffWrite,
425  ossim::TiffIStreamAdaptor::tiffSeek,
426  ossim::TiffIStreamAdaptor::tiffClose,
427  ossim::TiffIStreamAdaptor::tiffSize,
428  ossim::TiffIStreamAdaptor::tiffMap,
429  ossim::TiffIStreamAdaptor::tiffUnmap);
430  if (!theTiffPtr)
431  {
432  if (traceDebug())
433  {
435  << MODULE << " ERROR:\n"
436  << "libtiff could not open..." << std::endl;
437  }
438  return false;
439  }
440  std::shared_ptr<ossim::TiffHandlerState> state = getStateAs<ossim::TiffHandlerState>();
441  if(!state)
442  {
443  state = std::make_shared<ossim::TiffHandlerState>();
444  setState(state);
445  state->loadDefaults(theTiffPtr);
446  state->setImageHandlerType(getClassName());
447  }
448  state->setConnectionString(connectionString);
449 
450  // Current dir.
451  theCurrentDirectory = TIFFCurrentDirectory(theTiffPtr);
452  ossimString tempValue;
453  // Get the number of directories.
454  if(state->getValue(tempValue, "number_of_directories"))
455  {
456  theNumberOfDirectories = tempValue.toUInt32();
457  }
458  else
459  {
460  if (traceDebug())
461  {
463  << MODULE << " ERROR:\n"
464  << "Unable to get the number of directories\n";
465  }
466  return false;
467  }
468 
470 
471  //***
472  // Get the general tiff info.
473  //***
474 
475  if(!state->getValue(tempValue, theCurrentDirectory, "tifftag.compression"))
476  {
478  }
479  else
480  {
481  theCompressionType = tempValue.toInt32();
482  }
483  //***
484  // See if the first directory is of FILETYPE_REDUCEDIMAGE; if not,
485  // the first level is considered to be full resolution data.
486  // Note: If the tag is not present, consider the first level full
487  // resolution.
488  //***
489  theImageDirectoryList.push_back(0);
490 
491  if (state->isReduced(theCurrentDirectory))
492  {
493  theR0isFullRes = false;
494  }
495  else
496  {
497  theR0isFullRes = true;
498  }
499 
500  if(!state->getValue(tempValue, theCurrentDirectory, "tifftag.bits_per_sample"))
501  {
502  theBitsPerSample = 8;
503  }
504  else
505  {
506  theBitsPerSample = tempValue.toUInt16();
507  }
508  if(!state->getValue(tempValue, theCurrentDirectory, "tifftag.samples_per_pixel"))
509  {
510  theSamplesPerPixel = 1;
511  }
512  else
513  {
514  theSamplesPerPixel = tempValue.toUInt16();
515  }
516 
517  if(!state->getValue(tempValue, theCurrentDirectory, "tifftag.sample_format"))
518  {
520  }
521  else
522  {
523  theSampleFormatUnit = tempValue.toUInt16();;
524  }
525  if ( theSampleFormatUnit == SAMPLEFORMAT_COMPLEXINT )
526  {
527  //---
528  // Override the samples per pixel set above as sample data has set to
529  // one.
530  //---
531  theSamplesPerPixel = 2;
532  }
533 
534  if(!state->getValue(tempValue, theCurrentDirectory, "tifftag.max_sample_value"))
535  {
537  }
538  else
539  {
540  theMaxSampleValue = tempValue.toFloat32();
541  }
542  if(!state->getValue(tempValue, theCurrentDirectory, "tifftag.min_sample_value"))
543  {
545  }
546  else
547  {
548  theMinSampleValue = tempValue.toFloat32();
549  }
550 
551  if (traceDebug())
552  {
553  CLOG << "DEBUG:"
554  << "\ntheMinSampleValue: " << theMinSampleValue
555  << "\ntheMaxSampleValue: " << theMaxSampleValue
556  << endl;
557  }
558 
567 
568  for (ossim_uint32 dir=0; dir<theNumberOfDirectories; ++dir)
569  {
570  // if (setTiffDirectory(dir) == false)
571  // {
572  // return false;
573  // }
574 
575  // Note: Need lines, samples before acceptAsRrdsLayer check.
576 
577  // lines:
578  if(!state->getValue(tempValue, dir, "tifftag.image_length"))
579  {
582  << MODULE << " Cannot determine image length."
583  << endl;
584  }
585  else
586  {
587  theImageLength[dir] = tempValue.toUInt32();
588  }
589  // samples:
590  if(!state->getValue(tempValue, dir, "tifftag.image_width"))
591  {
594  << MODULE << " Cannot determine image width."
595  << endl;
596  }
597  else
598  {
599  theImageWidth[dir] = tempValue.toUInt32();
600  }
601 
602  if (state->isReduced(dir))
603  {
604  //---
605  // Check for a thumbnail image. If present don't use as it will mess with
606  // overviews. Currently only checking if it's a two directory image, i.e. a full
607  // res and a thumbnail.
608  //
609  // Note this shuts off the thumbnail which someone may want to see. We could make
610  // this a reader prop if it becomes an issue. drb - 09 Jan. 2012.
611  //---
612  if ( dir!=0 )
613  {
614  bool acceptAsRrdsLayer = true;
615  if ( ( theNumberOfDirectories == 2 ) && ( dir == 1 ) )
616  {
617  acceptAsRrdsLayer = isPowerOfTwoDecimation(dir);
618  }
619 
620  if ( acceptAsRrdsLayer )
621  {
622  theImageDirectoryList.push_back(dir);
623  }
624  }
625  }
626 
627  if(!state->getValue(tempValue, dir, "tifftag.planar_config"))
628  {
629  thePlanarConfig[dir] = PLANARCONFIG_CONTIG;
630  }
631  else
632  {
633  thePlanarConfig[dir] = tempValue.toUInt16();
634  }
635 
636  if(!state->getValue(tempValue, dir, "tifftag.photometric"))
637  {
638  thePhotometric[dir] = PHOTOMETRIC_MINISBLACK;
639  }
640  else
641  {
642  thePhotometric[dir] = tempValue.toUInt16();
643  }
644  theLut = 0;
645  if(state->exists(dir, "tifftag.colormap.red")&&
646  state->exists(dir, "tifftag.colormap.green")&&
647  state->exists(dir, "tifftag.colormap.blue"))
648  {
650  {
651  thePhotometric[dir] = PHOTOMETRIC_PALETTE;
652  theSamplesPerPixel = 3;
653  }
654  populateLut();
655  }
656  theRowsPerStrip[dir] = 0;
657  theImageTileWidth[dir] = 0;
658  theImageTileLength[dir] = 0;
659 
660  if(state->isTiled(dir))
661  {
662  if(state->getValue(tempValue, dir, "tifftag.tile_width"))
663  {
664  theImageTileWidth[dir] = tempValue.toUInt32();
665  }
666  else
667  {
670  << "ossimTiffTileSource::getTiffTileWidth ERROR:"
671  << "\nCannot determine tile width." << endl;
672 
673  }
674  if(state->getValue(tempValue, dir, "tifftag.tile_length"))
675  {
676  theImageTileLength[dir] = tempValue.toUInt32();
677  }
678  else
679  {
682  << "ossimTiffTileSource::getTiffTileLength ERROR:"
683  << "\nCannot determine tile length." << endl;
684  theImageTileLength[dir] = 0;
685  }
686  }
687  else
688  {
689  if(state->getValue(tempValue, dir, "tifftag.rows_per_strip"))
690  {
691  theRowsPerStrip[dir] = tempValue.toUInt32();
692  }
693  else
694  {
695  theRowsPerStrip[dir] = 1;
696  }
697  //---
698  // Let's default the tile size to something efficient.
699  //
700  // NOTE:
701  //
702  // This is not used by the strip reader method. Only by the getImageTileHeight
703  // and getImageTileHeight methods.
704  //---
705  if ( theImageTileWidth[dir] > 256 )
706  {
707  theImageTileWidth[dir] = 256;
708  }
709  else if( theImageTileWidth[dir] < 64 )
710  {
711  theImageTileWidth[dir] = 64;
712  }
713  if( theImageTileLength[dir] > 256 )
714  {
715  theImageTileLength[dir] = 256;
716  }
717  else if(theImageTileLength[dir] < 64)
718  {
719  theImageTileLength[dir] = 64;
720  }
721  }
722  } // End of "for (ossim_uint32 dir=0; dir<theNumberOfDirectories; dir++)"
723 
724  // Reset the directory back to "0".
725  if (setTiffDirectory(0) == false)
726  {
727  return false;
728  }
729 
730  //---
731  // Get the scalar type.
732  //---
734  if (theBitsPerSample == 16)
735  {
736  theBytesPerPixel = 2;
737 
738  if (theSampleFormatUnit == SAMPLEFORMAT_INT)
739  {
740  // this is currently causing pixel problems. I am going to comment this out until we figure out a better solution
741  //
742 #if 0
743  if (theMinSampleValue == 0) // && (theMaxSampleValue > 36535) )
744  {
745  //---
746  // This is a hack for RadarSat data which is has tag 339 set to
747  // signed sixteen bit data with a min sample value of 0 and
748  // sometimes a max sample value greater than 36535.
749  //---
751  }
752  else
753  {
755  }
756 #else
758 #endif
759 
760  }
761  else if (theSampleFormatUnit == SAMPLEFORMAT_UINT)
762  {
763  // ESH 03/2009 -- Changed "== 2047" to "<= 2047"
764  if (theMaxSampleValue <= 2047) // 2^11-1
765  {
766  // 11 bit EO, i.e. Ikonos, QuickBird, WorldView, GeoEye.
767  theScalarType = OSSIM_USHORT11; // IKONOS probably...
768  }
769  else if (theMaxSampleValue <= 4095) // 2^12-1
770  {
772  }
773  else if (theMaxSampleValue <= 8191) // 2^13-1
774  {
776  }
777  else if (theMaxSampleValue <= 16383) // 2^14-1
778  {
780  }
781  else if (theMaxSampleValue <= 32767) // 2^15-1
782  {
784  }
785  else
786  {
788  }
789  }
790  else
791  {
792  if (theMaxSampleValue <= 2047) // 2^11-1
793  {
794  // 11 bit EO, i.e. Ikonos, QuickBird, WorldView, GeoEye.
795  theScalarType = OSSIM_USHORT11; // IKONOS probably...
796  }
797  else if (theMaxSampleValue <= 4095) // 2^12-1
798  {
800  }
801  else if (theMaxSampleValue <= 8191) // 2^13-1
802  {
804  }
805  else if (theMaxSampleValue <= 16383) // 2^14-1
806  {
808  }
809  else if (theMaxSampleValue <= 32767) // 2^15-1
810  {
812  }
813  else
814  theScalarType = OSSIM_UINT16; // Default to unsigned...
815  }
816  }
817  else if ( (theBitsPerSample == 32) &&
818  (theSampleFormatUnit == SAMPLEFORMAT_UINT) )
819  {
820  theBytesPerPixel = 4;
822  }
823  else if ( (theBitsPerSample == 32) &&
824  (theSampleFormatUnit == SAMPLEFORMAT_INT) )
825  {
826  theBytesPerPixel = 4;
828  }
829  else if ( (theBitsPerSample == 32) &&
830  (theSampleFormatUnit == SAMPLEFORMAT_IEEEFP) )
831  {
832  theBytesPerPixel = 4;
834  }
835  else if ( (theBitsPerSample == 32) &&
836  (theSampleFormatUnit == SAMPLEFORMAT_COMPLEXINT) )
837  {
838  theBytesPerPixel = 2;
840  }
841  else if(theBitsPerSample == 64 &&
842  theSampleFormatUnit == SAMPLEFORMAT_IEEEFP)
843  {
844  theBytesPerPixel = 8;
846  }
847  else if (theBitsPerSample <= 8)
848  {
849  theBytesPerPixel = 1;
851  }
852  else
853  {
855  << MODULE << " Error:\nCannot determine scalar type.\n"
856  << "Trace dump follows:\n";
858 
859  return false;
860  }
861 
862  // Sanity check for min, max and null values.
864 
865  setReadMethod();
866 
867  ossim_uint16 rasterType = state->getRasterType(theCurrentDirectory);
868 
869  if(rasterType == 1)
870  {
872  }
873  else
874  {
876  }
877  completeOpen();
878 
879  if ( isBandSelector() && theOutputBandList.size() && ( isIdentityBandList( theOutputBandList ) == false ) )
880  {
881  // This does range checking and will pass to overview if open.
883  }
884 
885  //---
886  // Note: Logic changed to leave theTile and theBuffer uninitialized until first getTile(...)
887  // request. (drb)
888  //---
889 
890  if (traceDebug())
891  {
892  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " Debug:";
894  }
895 
896  // Finished...
897  return true;
898 
899 }
900 
902 {
903  static const char MODULE[] = "ossimTiffTileSource::open";
904  bool result = false;
905  if (traceDebug())
906  {
908  << MODULE << " Entered..."
909  << "\nFile: " << theImageFile.c_str() << std::endl;
910  }
911  std::shared_ptr<std::istream> tiffStream = ossim::StreamFactoryRegistry::instance()->createIstream(theImageFile);
912 
913  if(tiffStream)
914  {
915  result = open(tiffStream, theImageFile);
916  }
917 
918  return result;
919 
920 }
921 
923 {
924  ossim_uint32 result = 0;
925  if ( theImageDirectoryList.size() && theTiffPtr && isValidRLevel(resLevel) )
926  {
927  //---
928  // If we have r0 our reslevels are the same as the callers so
929  // no adjustment necessary.
930  //---
931  if (!theStartingResLevel || theR0isFullRes) // not an overview or has r0.
932  {
933  //---
934  // If we have r0 our reslevels are the same as the callers so
935  // no adjustment necessary.
936  //---
937  if (resLevel < theImageDirectoryList.size())
938  {
939  result = theImageLength[theImageDirectoryList[resLevel]];
940  }
941  else if (theOverview.valid())
942  {
943  result = theOverview->getNumberOfLines(resLevel);
944  }
945  }
946  else // this is an overview without r0
947  {
948  if (resLevel >= theStartingResLevel)
949  {
950  //---
951  // Adjust the level to be relative to the reader using this as
952  // overview.
953  //---
954  ossim_uint32 level = resLevel - theStartingResLevel;
955  if (level < theImageDirectoryList.size())
956  {
957  result = theImageLength[theImageDirectoryList[level]];
958  }
959  }
960  }
961  }
962  return result;
963 }
964 
966 {
967  ossim_uint32 result = 0;
968  if ( theImageDirectoryList.size() && theTiffPtr && isValidRLevel(resLevel) )
969  {
970  //---
971  // If we have r0 our reslevels are the same as the callers so
972  // no adjustment necessary.
973  //---
974  if (!theStartingResLevel||theR0isFullRes) // not an overview or has r0.
975  {
976  if (resLevel < theImageDirectoryList.size())
977  {
978  result = theImageWidth[theImageDirectoryList[resLevel]];
979  }
980  else if (theOverview.valid())
981  {
982  result = theOverview->getNumberOfSamples(resLevel);
983  }
984  }
985  else // this is an overview.
986  {
987  if (resLevel >= theStartingResLevel)
988  {
989  //---
990  // Adjust the level to be relative to the reader using this as
991  // overview.
992  //---
993  ossim_uint32 level = resLevel - theStartingResLevel;
994  if (level < theImageDirectoryList.size())
995  {
996  result = theImageWidth[theImageDirectoryList[level]];
997  }
998  }
999  }
1000  }
1001  return result;
1002 }
1003 
1005 {
1006  ossim_uint32 result = theImageDirectoryList.size();
1007 
1008  // If starting res level is not 0 then this is an overview.
1010  {
1011  // Don't count r0.
1012  --result;
1013  }
1014  else if (theOverview.valid())
1015  {
1017  }
1018 
1019  return result;
1020 }
1021 
1022 //*******************************************************************
1023 // Public method:
1024 //*******************************************************************
1026 {
1027  return theScalarType;
1028 }
1029 
1031  const ossimIrect& clip_rect,
1032  ossimImageData* result)
1033 {
1034  static const char MODULE[] = "ossimTiffTileSource::loadTile";
1035 
1036  bool status = true;
1037 
1038  if ( !theBuffer )
1039  {
1040  status = allocateBuffer();
1041  }
1042 
1043  if ( status )
1044  {
1046  {
1047  case READ_TILE:
1048  status = loadFromTile(clip_rect, result);
1049  break;
1050 
1051  case READ_SCAN_LINE:
1052  status = loadFromScanLine(clip_rect, result);
1053  break;
1054 
1055  case READ_RGBA_U8_TILE:
1056  status = loadFromRgbaU8Tile(tile_rect, clip_rect, result);
1057  break;
1058 
1059  case READ_RGBA_U8_STRIP:
1060  status = loadFromRgbaU8Strip(tile_rect, clip_rect, result);
1061  break;
1062 
1063  case READ_RGBA_U8A_STRIP:
1064  status = loadFromRgbaU8aStrip(tile_rect, clip_rect, result);
1065  break;
1066 
1067  case READ_U16_STRIP:
1068  status = loadFromU16Strip(clip_rect, result);
1069  break;
1070 
1071  default:
1073  << MODULE << " Unsupported tiff type!" << endl;
1074  status = false;
1075  break;
1076  }
1077  }
1078 
1079  return status;
1080 }
1081 
1083  ossimImageData* result)
1084 {
1085 #if OSSIM_BUFFER_SCAN_LINE_READS
1086  ossimInterleaveType type =
1087  (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG) ?
1088  OSSIM_BIP : OSSIM_BIL;
1089 
1091  !clip_rect.completely_within(theBufferRect) )
1092  {
1093  //***
1094  // Must reload the buffer. Grab enough lines to fill the depth of the
1095  // clip rectangle.
1096  //***
1099  theBufferRect.set_uly(clip_rect.ul().y);
1100  theBufferRect.set_lry(clip_rect.lr().y);
1101  ossim_uint32 startLine = clip_rect.ul().y;
1102  ossim_uint32 stopLine = clip_rect.lr().y;
1103  ossim_uint8* buf = theBuffer;
1104 
1105  if (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG)
1106  {
1107  ossim_uint32 lineSizeInBytes = getNumberOfSamples(theBufferRLevel) *
1109 
1110  for (ossim_uint32 line = startLine; line <= stopLine; ++line)
1111  {
1112  TIFFReadScanline(theTiffPtr, (void*)buf, line, 0);
1113  buf += lineSizeInBytes;
1114  }
1115  }
1116  else
1117  {
1118  ossim_uint32 lineSizeInBytes = getNumberOfSamples(theBufferRLevel) *
1120 
1121  for (ossim_uint32 line = startLine; line <= stopLine; ++line)
1122  {
1123  for (ossim_uint32 band = 0; band < theSamplesPerPixel; ++band)
1124  {
1125  TIFFReadScanline(theTiffPtr, (void*)buf, line, band);
1126  buf += lineSizeInBytes;
1127  }
1128  }
1129  }
1130  }
1131 
1132  //---
1133  // Since theTile's internal rectangle is relative to any sub image offset
1134  // we must adjust both the zero based "theBufferRect" and the zero base
1135  // "clip_rect" before passing to
1136  // theTile->loadTile method.
1137  //---
1138  result->loadTile(theBuffer, theBufferRect, clip_rect, type);
1139  return true;
1140 
1141 #else
1142  ossimInterleaveType type =
1143  (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG) ? OSSIM_BIP : OSSIM_BIL;
1144 
1145  ossim_int32 startLine = clip_rect.ul().y;
1146  ossim_int32 stopLine = clip_rect.lr().y;
1147  ossim_int32 stopSamp = static_cast<ossim_int32>(getNumberOfSamples(theBufferRLevel)-1);
1148 
1149  if (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG)
1150  {
1151  for (ossim_int32 line = startLine; line <= stopLine; ++line)
1152  {
1153  TIFFReadScanline(theTiffPtr, (void*)theBuffer, line, 0);
1154  result->copyLine((void*)theBuffer, line, 0, stopSamp, type);
1155  }
1156  }
1157  else
1158  {
1160  for (ossim_int32 line = startLine; line <= stopLine; ++line)
1161  {
1162  ossim_uint8* buf = theBuffer;
1163  for (ossim_uint32 band = 0; band < theSamplesPerPixel; ++band)
1164  {
1165  TIFFReadScanline(theTiffPtr, (void*)buf, line, band);
1166  buf += lineSizeInBytes;
1167  }
1168  result->copyLine((void*)theBuffer, line, 0, stopSamp, type);
1169  }
1170  }
1171  return true;
1172 #endif /* #if OSSIM_BUFFER_SCAN_LINE_READS #else - Non buffered scan line reads. */
1173 }
1174 
1176  ossimImageData* result)
1177 {
1178  static const char MODULE[] = "ossimTiffTileSource::loadFromTile";
1179 
1180  ossim_int32 tileSizeRead = 0;
1181 
1182  //---
1183  // Shift the upper left corner of the "clip_rect" to the an even tile
1184  // boundary. Note this will shift in the upper left direction.
1185  //---
1186  ossimIpt tileOrigin = clip_rect.ul();
1187  adjustToStartOfTile(tileOrigin);
1188  ossimIpt ulTilePt = tileOrigin;
1189 // ossimIpt subImageOffset = getSubImageOffset(getCurrentTiffRLevel()+theStartingResLevel);
1190 
1191  //---
1192  // Calculate the number of tiles needed in the line/sample directions.
1193  //---
1194  ossim_uint32 tiles_in_v_dir = (clip_rect.lr().x-tileOrigin.x+1) /
1196  ossim_uint32 tiles_in_u_dir = (clip_rect.lr().y-tileOrigin.y+1) /
1198 
1199  if ( (clip_rect.lr().x-tileOrigin.x+1) %
1200  theImageTileWidth[theCurrentDirectory] ) ++tiles_in_v_dir;
1201  if ( (clip_rect.lr().y-tileOrigin.y+1) %
1202  theImageTileLength[theCurrentDirectory] ) ++tiles_in_u_dir;
1203 
1204 
1205  // Tile loop in line direction.
1206  for (ossim_uint32 u=0; u<tiles_in_u_dir; ++u)
1207  {
1208  ulTilePt.x = tileOrigin.x;
1209 
1210  // Tile loop in sample direction.
1211  for (ossim_uint32 v=0; v<tiles_in_v_dir; ++v)
1212  {
1213  ossimIrect tiff_tile_rect(ulTilePt.x,
1214  ulTilePt.y,
1215  ulTilePt.x +
1217  ulTilePt.y +
1219 
1220  if (tiff_tile_rect.intersects(clip_rect))
1221  {
1222  ossimIrect tiff_tile_clip_rect
1223  = tiff_tile_rect.clipToRect(clip_rect);
1224 
1225  //---
1226  // Since theTile's internal rectangle is relative to any sub
1227  // image offset we must adjust both the zero based
1228  // "theBufferRect" and the zero based "clip_rect" before
1229  // passing to theTile->loadTile method.
1230  //---
1231  ossimIrect bufRectWithOffset = tiff_tile_rect;// + subImageOffset;
1232  ossimIrect clipRectWithOffset = tiff_tile_clip_rect;// + subImageOffset;
1233 
1234  if (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG)
1235  {
1236  tileSizeRead = TIFFReadTile(theTiffPtr,
1237  theBuffer,
1238  ulTilePt.x,
1239  ulTilePt.y,
1240  0,
1241  0);
1242  if (tileSizeRead > 0)
1243  {
1244  result->loadTile(theBuffer,
1245  bufRectWithOffset,
1246  clipRectWithOffset,
1247  OSSIM_BIP);
1248  }
1249  else if(tileSizeRead < 0)
1250  {
1251  if(traceDebug())
1252  {
1254  << MODULE << " Read Error!"
1255  << "\nReturning error... " << endl;
1256  }
1258  return false;
1259  }
1260  }
1261  else
1262  {
1263  if ( theOutputBandList.empty() )
1264  {
1265  // This will set to identity.
1267  }
1268 
1269  // band separate tiles...
1270  std::vector<ossim_uint32>::const_iterator bandIter = theOutputBandList.begin();
1271  ossim_uint32 destinationBand = 0;
1272  while ( bandIter != theOutputBandList.end() )
1273  {
1274  tileSizeRead = TIFFReadTile( theTiffPtr,
1275  theBuffer,
1276  ulTilePt.x,
1277  ulTilePt.y,
1278  0,
1279  (*bandIter) );
1280  if(tileSizeRead > 0)
1281  {
1282  result->loadBand( theBuffer,
1283  bufRectWithOffset,
1284  clipRectWithOffset,
1285  destinationBand );
1286  }
1287  else if (tileSizeRead < 0)
1288  {
1289  if(traceDebug())
1290  {
1292  << MODULE << " Read Error!"
1293  << "\nReturning error... " << endl;
1294  }
1296  return false;
1297  }
1298  ++bandIter; // Next band...
1299  ++destinationBand;
1300  }
1301  }
1302 
1303  } // End of if (tiff_tile_rect.intersects(clip_rect))
1304 
1306 
1307  } // End of tile loop in the sample direction.
1308 
1310 
1311  } // End of tile loop in the line direction.
1312 
1313  return true;
1314 }
1315 
1317  const ossimIrect& clip_rect,
1318  ossimImageData* result)
1319 {
1320  static const char MODULE[] = "ossimTiffTileSource::loadFromRgbaTile";
1321 
1322  if (theSamplesPerPixel != 3 || theBytesPerPixel!=1)
1323  {
1325  << MODULE << " Error:"
1326  << "\nInvalid number of bands or bytes per pixel!" << endl;
1327  }
1328 
1329  //***
1330  // Shift the upper left corner of the "clip_rect" to the an even tile
1331  // boundary. Note this will shift in the upper left direction.
1332  //***
1333  ossimIpt tileOrigin = clip_rect.ul();
1334  adjustToStartOfTile(tileOrigin);
1335 
1336  //---
1337  // Calculate the number of tiles needed in the line/sample directions
1338  // to fill the tile.
1339  //---
1340  ossim_uint32 tiles_in_v_dir = (clip_rect.lr().x-tileOrigin.x+1) /
1342  ossim_uint32 tiles_in_u_dir = (clip_rect.lr().y-tileOrigin.y+1) /
1344 
1345  if ( (clip_rect.lr().x-tileOrigin.x+1) %
1346  theImageTileWidth[theCurrentDirectory] ) ++tiles_in_v_dir;
1347  if ( (clip_rect.lr().y-tileOrigin.y+1) %
1348  theImageTileLength[theCurrentDirectory] ) ++tiles_in_u_dir;
1349 
1350  ossimIpt ulTilePt = tileOrigin;
1351 
1352 #if 0
1353  if (traceDebug())
1354  {
1355  CLOG << "DEBUG:"
1356  << "\ntile_rect: " << tile_rect
1357  << "\nclip_rect: " << clip_rect
1358  << "\ntiles_in_v_dir: " << tiles_in_v_dir
1359  << "\ntiles_in_u_dir: " << tiles_in_u_dir
1360  << endl;
1361  }
1362 #endif
1363 
1364 
1365  // Tile loop in line direction.
1366  for (ossim_uint32 u=0; u<tiles_in_u_dir; u++)
1367  {
1368  ulTilePt.x = tileOrigin.x;
1369 
1370  // Tile loop in sample direction.
1371  for (ossim_uint32 v=0; v<tiles_in_v_dir; v++)
1372  {
1373  ossimIrect tiff_tile_rect
1374  = ossimIrect(ulTilePt.x,
1375  ulTilePt.y,
1376  ulTilePt.x +
1378  ulTilePt.y +
1380 
1382  tiff_tile_rect != theBufferRect)
1383  {
1384  // Need to grab a new tile.
1385  // Read a tile into the buffer.
1386  if ( !TIFFReadRGBATile(theTiffPtr,
1387  ulTilePt.x,
1388  ulTilePt.y,
1389  (uint32*)theBuffer) ) // use tiff typedef
1390  {
1392  << MODULE << " Read Error!"
1393  << "\nReturning error..." << endl;
1395  return false;
1396  }
1397 
1398  // Capture the rectangle.
1399  theBufferRect = tiff_tile_rect;
1401  }
1402 
1403  ossimIrect tile_clip_rect = clip_rect.clipToRect(theBufferRect);
1404 
1405  //***
1406  // Get the offset to the first valid pixel.
1407  //
1408  // Note: The data in the tile buffer is organized bottom up. So the
1409  // coordinate must be negated in the line direction since
1410  // the met assumes an origin of upper left.
1411  //***
1412  ossim_uint32 in_buf_offset =
1413  (tiff_tile_rect.lr().y-tile_clip_rect.ul().y)*
1415  ((tile_clip_rect.ul().x - ulTilePt.x)*4);
1416 
1417  ossim_uint32 out_buf_offset =
1418  (tile_clip_rect.ul().y - tile_rect.ul().y) *
1419  ((ossim_int32)result->getWidth()) +
1420  tile_clip_rect.ul().x - tile_rect.ul().x;
1421 
1422  //
1423  // Get a pointer positioned at the first valid pixel in buffers.
1424  //
1425  ossim_uint32* s = (ossim_uint32*)(theBuffer + in_buf_offset); // s for source...
1426 // ossim_uint8* s = theBuffer + in_buf_offset; // s for source...
1427  ossim_uint8* r = static_cast<ossim_uint8*>(result->getBuf(0))+
1428  out_buf_offset;
1429  ossim_uint8* g = static_cast<ossim_uint8*>(result->getBuf(1))+
1430  out_buf_offset;
1431  ossim_uint8* b = static_cast<ossim_uint8*>(result->getBuf(2))+
1432  out_buf_offset;
1433 
1434  ossim_uint32 lines2copy = tile_clip_rect.lr().y-tile_clip_rect.ul().y+1;
1435  ossim_uint32 samps2copy = tile_clip_rect.lr().x-tile_clip_rect.ul().x+1;
1436 
1437  // Line loop through valid portion of the tiff tile.
1438  for (ossim_uint32 line = 0; line < lines2copy; line++)
1439  {
1440  // Sample loop through the tiff tile.
1441  ossim_uint32 i=0;
1442  ossim_uint32 j=0;
1443 
1444  // note the bands from the TIFF READ are stored in a, b, g, r ordering.
1445  // we must reverse the bands and skip the first byte.
1446  for (ossim_uint32 sample = 0; sample < samps2copy; sample++)
1447  {
1448  r[i] = (ossim_uint8)OSSIM_TIFF_UNPACK_R4(s[j]);
1449  g[i] = (ossim_uint8)OSSIM_TIFF_UNPACK_G4(s[j]);
1450  b[i] = (ossim_uint8)OSSIM_TIFF_UNPACK_B4(s[j]);
1451  i++;
1452  ++j;
1453  }
1454 
1455  // Increment the pointers by one line.
1456  const ossim_uint32 OUTPUT_TILE_WIDTH = result->getWidth();
1457  r += OUTPUT_TILE_WIDTH;
1458  g += OUTPUT_TILE_WIDTH;
1459  b += OUTPUT_TILE_WIDTH;
1461  }
1462 
1464 
1465  } // End of tile loop in the sample direction.
1466 
1468 
1469  } // End of tile loop in the line direction.
1470 
1471  return true;
1472 }
1473 
1475  const ossimIrect& clip_rect,
1476  ossimImageData* result)
1477 {
1478  static const char MODULE[] = "ossimTiffTileSource::loadFromRgbaU8Strip";
1479 
1480  if (theSamplesPerPixel > 4 || theBytesPerPixel != 1)
1481  {
1483  << MODULE << " Error:"
1484  << "\nInvalid number of bands or bytes per pixel!" << endl;
1485  }
1486 
1487  //***
1488  // Calculate the number of strips to read.
1489  //***
1490  const ossim_uint32 OUTPUT_TILE_WIDTH = result->getWidth();
1491 
1492  ossim_uint32 starting_strip = clip_rect.ul().y /
1494  ossim_uint32 ending_strip = clip_rect.lr().y /
1497  ossim_uint32 output_tile_offset = (clip_rect.ul().y - tile_rect.ul().y) *
1498  OUTPUT_TILE_WIDTH + clip_rect.ul().x -
1499  tile_rect.ul().x;
1500 #if 0 /* Please keep for debug: */
1501  CLOG << "DEBUG:"
1502  << "\nsamples: " << theSamplesPerPixel
1503  << "\ntile_rect: " << tile_rect
1504  << "\nclip_rect: " << clip_rect
1505  << "\nstarting_strip: " << starting_strip
1506  << "\nending_strip: " << ending_strip
1507  << "\nstrip_width: " << strip_width
1508  << "\noutput_tile_offset: " << output_tile_offset
1509  << endl;
1510 #endif
1511 
1512  //***
1513  // Get the pointers positioned at the first valid pixel in the buffers.
1514  // s = source
1515  // d = destination
1516  //***
1517  ossim_uint32 band;
1518 
1520  for (band = 0; band < theSamplesPerPixel; band++)
1521  {
1522  d[band] = static_cast<ossim_uint8*>(result->getBuf(band))+output_tile_offset;
1523  }
1524 
1525  // Loop through strips...
1526  for (ossim_uint32 strip=starting_strip; strip<=ending_strip; strip++)
1527  {
1529  ( clip_rect.completely_within( theBufferRect ) == false ) )
1530  {
1531  if (TIFFReadRGBAStrip(theTiffPtr,
1533  (uint32*)theBuffer) == 0) // use tiff typedef
1534  {
1536  << MODULE << " Error reading strip!" <<endl;
1537  delete [] d;
1538  return false;
1539  }
1540 
1541  // Capture rect and rlevel of buffer:
1544  0,
1545  starting_strip,
1547  (ending_strip-starting_strip) ? (ending_strip-starting_strip) *
1550  }
1551 
1552  //***
1553  // If the last strip is a partial strip then the first line of the
1554  // strip will be the last line of the image.
1555  //***
1557 
1558  ossim_uint32 strip_offset
1559  = ((strip * theRowsPerStrip[theCurrentDirectory]) +
1561  last_line ? 0 :
1562  ((strip * theRowsPerStrip[theCurrentDirectory]) +
1563  theRowsPerStrip[theCurrentDirectory] - 1) - last_line;
1564 
1566  strip_offset;
1567 
1568  for (ossim_uint32 row=0; row<total_rows; row++)
1569  {
1570  // Write the line if it's in the clip rectangle.
1571  ossim_int32 current_line = strip * theRowsPerStrip[theCurrentDirectory]
1572  + row;
1573  if (current_line >= clip_rect.ul().y &&
1574  current_line <= clip_rect.lr().y)
1575  {
1576  //
1577  // Position the stip pointer to the correct spot.
1578  //
1579  // Note:
1580  // A strip is organized from bottom to top and the raster buffer is
1581  // orgainized from top to bottom so the lineBuf must be offset
1582  // accordingly.
1583  //
1585  strip_offset - 1) * strip_width + clip_rect.ul().x * 4));
1586 
1587  // Copy the data to the output buffer.
1588  ossim_uint32 i=0;
1589 
1590  for (int32 sample=clip_rect.ul().x;
1591  sample<=clip_rect.lr().x;
1592  sample++)
1593  {
1594  //We had a single band strip image that is coming into this method
1595  // Will add a sanity check on the samples per pixel. If it's == 1 for now
1596  // we will assign the value and if it has atleast the 3 samples then we will
1597  // extract as usual.
1598  //
1599  if(theSamplesPerPixel >=3)
1600  {
1601  d[0][i] = OSSIM_TIFF_UNPACK_R4(*s);
1602  d[1][i] = OSSIM_TIFF_UNPACK_G4(*s);
1603  d[2][i] = OSSIM_TIFF_UNPACK_B4(*s);
1604  }
1605  else if(theSamplesPerPixel == 1)
1606  {
1607  d[0][i] = *s;
1608  }
1609  ++i;
1610  ++s;
1611  }
1612 
1613  for (band = 0; band < theSamplesPerPixel; band++)
1614  {
1615  d[band] += OUTPUT_TILE_WIDTH;
1616  }
1617  }
1618  } // End of loop through rows in a strip.
1619 
1620  } // End of loop through strips.
1621 
1622  delete [] d;
1623 
1624  return true;
1625 }
1626 
1627 //*******************************************************************
1628 // Private Method:
1629 //*******************************************************************
1631  const ossimIrect& clip_rect,
1632  ossimImageData* result)
1633 {
1634  static const char MODULE[] = "ossimTiffTileSource::loadFromRgbaU8aStrip";
1635 
1636  //***
1637  // Specialized for one bit data to handle null values.
1638  //***
1639  const ossim_uint32 OUTPUT_TILE_WIDTH = result->getWidth();
1640  const ossim_uint8 NULL_PIX = static_cast<ossim_uint8>(result->getNullPix(0));
1641  const ossim_uint8 MIN_PIX = static_cast<ossim_uint8>(result->getMinPix(0));
1642 
1643  if (theSamplesPerPixel > 4 || theBytesPerPixel!= 1)
1644  {
1646  << MODULE << " Error:"
1647  << "\nInvalid number of bands or bytes per pixel!" << endl;
1648  }
1649 
1650  //***
1651  // Calculate the number of strips to read.
1652  //***
1653  ossim_uint32 starting_strip = clip_rect.ul().y /
1655  ossim_uint32 ending_strip = clip_rect.lr().y /
1657  ossim_uint32 output_tile_offset = (clip_rect.ul().y - tile_rect.ul().y) *
1658  OUTPUT_TILE_WIDTH + clip_rect.ul().x -
1659  tile_rect.ul().x;
1660 
1661 #if 0
1662  if (traceDebug())
1663  {
1664  CLOG << "DEBUG:"
1665  << "\ntile_rect: " << tile_rect
1666  << "\nclip_rect: " << clip_rect
1667  << "\nstarting_strip: " << starting_strip
1668  << "\nending_strip: " << ending_strip
1669  << "\nstrip_width: " << strip_width
1670  << "\noutput_tile_offset: " << output_tile_offset
1671  << "\nsamples: " << theSamplesPerPixel
1672  << endl;
1673  }
1674 #endif
1675 
1676  //***
1677  // Get the pointers positioned at the first valid pixel in the buffers.
1678  // s = source
1679  // d = destination
1680  //***
1681  ossim_uint32 band;
1682 
1684  for (band = 0; band < theSamplesPerPixel; band++)
1685  {
1686  d[band] = static_cast<ossim_uint8*>(result->getBuf(band))+output_tile_offset;
1687  }
1688 
1689  // Loop through strips...
1690  for (ossim_uint32 strip=starting_strip; strip<=ending_strip; strip++)
1691  {
1692  if (TIFFReadRGBAStrip(theTiffPtr,
1694  (uint32*)theBuffer) == 0) // use tiff typedef
1695  {
1697  << MODULE << " Error reading strip!" <<endl;
1698  delete [] d;
1699  return false;
1700  }
1701 
1702  //***
1703  // If the last strip is a partial strip then the first line of the
1704  // strip will be the last line of the image.
1705  //***
1707 
1708  ossim_uint32 strip_offset
1709  = ((strip * theRowsPerStrip[theCurrentDirectory]) +
1710  theRowsPerStrip[theCurrentDirectory] - 1) < last_line ? 0 :
1711  ((strip * theRowsPerStrip[theCurrentDirectory]) +
1712  theRowsPerStrip[theCurrentDirectory] - 1) - last_line;
1713 
1715  strip_offset;
1716 
1717  for (ossim_uint32 row=0; row<total_rows; row++)
1718  {
1719  // Write the line if it's in the clip rectangle.
1720  ossim_int32 current_line = strip * theRowsPerStrip[theCurrentDirectory]
1721  + row;
1722  if (current_line >= clip_rect.ul().y &&
1723  current_line <= clip_rect.lr().y)
1724  {
1725  //***
1726  // Position the stip pointer to the correct spot.
1727  //
1728  // Note:
1729  // A strip is organized from bottom to top and the raster buffer is
1730  // orgainized from top to bottom so the lineBuf must be offset
1731  // accordingly.
1732  //***
1733  ossim_uint8* s = theBuffer;
1734  s += (theRowsPerStrip[theCurrentDirectory] - row -
1735  strip_offset - 1) *
1737  clip_rect.ul().x * 4;
1738 
1739  // Copy the data to the output buffer.
1740  ossim_uint32 i=0;
1741  ossim_uint32 j=0;
1742  for (int32 sample=clip_rect.ul().x;
1743  sample<=clip_rect.lr().x;
1744  sample++)
1745  {
1746  for (band = 0; band < theSamplesPerPixel; band++)
1747  {
1748  ossim_uint8 pix = s[j + band];
1749  d[band][i] = pix != NULL_PIX ? pix : MIN_PIX;
1750  }
1751  ++i;
1752  j += 4;
1753  }
1754 
1755  for (band = 0; band < theSamplesPerPixel; band++)
1756  {
1757  d[band] += OUTPUT_TILE_WIDTH;
1758  }
1759  }
1760  } // End of loop through rows in a strip.
1761 
1762  } // End of loop through strips.
1763 
1764  delete [] d;
1765 
1766  return true;
1767 
1768 } // End: ossimTiffTileSource::loadFromRgbaU8aStrip( ... )
1769 
1771 {
1772  bool status = true;
1773 
1774  // Calculate the strips to read.
1775  ossim_uint32 starting_strip = clip_rect.ul().y / theRowsPerStrip[theCurrentDirectory];
1776  ossim_uint32 ending_strip = clip_rect.lr().y / theRowsPerStrip[theCurrentDirectory];
1777 
1781  {
1782  ++stripsPerBand;
1783  }
1784 
1785  // Loop through strips....
1786  for ( ossim_uint32 strip = starting_strip; strip <= ending_strip; ++strip )
1787  {
1789  !clip_rect.completely_within(theBufferRect) )
1790  {
1791  // Fill buffer block:
1792 
1794 
1795  // If last strip and not filling entirely memset it.
1796  if ( strip == ( stripsPerBand - 1 ) )
1797  {
1798  // Last strip of image. Strip may be clipped to end of image.
1799  linesInStrip = theImageLength[theCurrentDirectory] %
1801  }
1802 
1803  ossim_uint32 bytesPerStrip = linesInStrip * theImageWidth[theCurrentDirectory] * 2;
1804 
1805  // TIFFReadEncodedStrip takes signed int32 arg.
1806  ossim_int32 bytesToRead = (ossim_int32)bytesPerStrip;
1807 
1809 
1810  // Need to read in the strip data:
1811  ossim_uint32 bufferOffsetInBytes = 0;
1812 
1813  for (ossim_uint32 band = 0; band < theSamplesPerPixel; ++band)
1814  {
1815  ossim_uint32 bandStrip = strip + band * stripsPerBand;
1816 
1817  //---
1818  // TIFFReadEncodedStrip does byte swapping for us.
1819  // -1 says to read entire strip.
1820  // Return of -1 is error.
1821  //---
1822  ossim_int32 bytesRead = TIFFReadEncodedStrip( theTiffPtr,
1823  bandStrip,
1824  theBuffer+bufferOffsetInBytes,
1825  bytesToRead );
1826  if ( bytesRead != bytesToRead )
1827  {
1828  if(traceDebug())
1829  {
1831  << "ossimTiffTileSource::loadFromU16Strip Read Error!"
1832  << "\nReturning error... " << endl;
1833  }
1835  status = false;
1836  result->makeBlank();
1837  break;
1838  }
1839  bufferOffsetInBytes += bytesPerStrip;
1840  }
1841 
1842  if ( status )
1843  {
1844  // Capture rect and rlevel of buffer:
1847  startY,
1849  startY + linesInStrip - 1);
1850  }
1851 
1852  } // End: Fill buffer block.
1853 
1854  if ( status )
1855  {
1857  }
1858 
1859  } // End of strip loop.
1860 
1861  return status;
1862 
1863 } // End: ossimTiffTileSource::loadFromU16Strip( ... )
1864 
1866 {
1867  //***
1868  // Notes:
1869  // - Assumes an origin of (0,0)
1870  // - Shifts in to the upper left direction.
1871  //***
1872  ossim_int32 tw =
1874  ossim_int32 th =
1876 
1877  if (pt.x > 0)
1878  {
1879  pt.x = (pt.x/tw) * tw;
1880  }
1881  else if (pt.x < 0)
1882  {
1883  pt.x = std::abs(pt.x) < tw ? -tw : (pt.x/tw)*tw;
1884  }
1885 
1886  if (pt.y > 0)
1887  {
1888  pt.y = (pt.y/th) * th;
1889  }
1890  else if (pt.y < 0)
1891  {
1892  pt.y = std::abs(pt.y) < th ? -th : (pt.y/th)*th;
1893  }
1894 }
1895 
1897 {
1898  bool result = false;
1899 
1900  const ossim_uint32 LEVELS = getNumberOfDecimationLevels();
1901 
1902  //---
1903  // If we have r0 our reslevels are the same as the callers so
1904  // no adjustment necessary.
1905  //---
1906  if ( !theStartingResLevel || theR0isFullRes) // Not an overview or has r0.
1907  {
1908  result = (resLevel < LEVELS);
1909  }
1910  else if (resLevel >= theStartingResLevel) // Used as overview.
1911  {
1912  result = ( (resLevel - theStartingResLevel) < LEVELS);
1913  }
1914 
1915  return result;
1916 }
1917 
1919 {
1920  return theCurrentTiffRlevel;
1921 // return theCurrentDirectory;
1922 }
1923 
1925 {
1926  ossimString result = "UNKNOWN";
1927  if ( directory < theReadMethod.size() )
1928  {
1929  switch (theReadMethod[directory])
1930  {
1931  case READ_RGBA_U8_TILE:
1932  result = "READ_RGBA_U8_TILE";
1933  break;
1934  case READ_RGBA_U8_STRIP:
1935  result = "READ_RGBA_U8_STRIP";
1936  break;
1937  case READ_RGBA_U8A_STRIP:
1938  result = "READ_RGBA_U8A_STRIP";
1939  break;
1940  case READ_SCAN_LINE:
1941  result = "READ_SCAN_LINE";
1942  break;
1943  case READ_TILE:
1944  result = "READ_TILE";
1945  break;
1946  case UNKNOWN:
1947  default:
1948  break;
1949  }
1950  }
1951  return result;
1952 }
1953 
1955 {
1956  return theNumberOfDirectories;
1957 }
1958 
1960 {
1961  ossim_uint32 result = 0;
1962  if(isOpen())
1963  {
1965  {
1967  }
1968  }
1969  return result;
1970 }
1971 
1973 {
1974  ossim_uint32 result = 0;
1975  if(isOpen())
1976  {
1978  {
1980  }
1981  }
1982  return result;
1983 }
1984 
1986 {
1987  ossim_uint32 result = getImageTileWidth();
1988  if (!result)
1989  {
1990  ossimIpt tileSize;
1991  ossim::defaultTileSize(tileSize);
1992  result = tileSize.x;
1993  }
1994  return result;
1995 }
1996 
1998 {
1999  ossim_uint32 result = getImageTileHeight();
2000  if (!result)
2001  {
2002  ossimIpt tileSize;
2003  ossim::defaultTileSize(tileSize);
2004  result = tileSize.y;
2005  }
2006  return result;
2007 }
2008 
2010 {
2011  theApplyColorPaletteFlag = flag;
2012 
2013  if(isColorMapped())
2014  {
2016  {
2017  thePhotometric[0] = PHOTOMETRIC_PALETTE;
2018  theSamplesPerPixel = 3;
2019  }
2020  else
2021  {
2022  thePhotometric[0] = PHOTOMETRIC_MINISBLACK;
2023  theSamplesPerPixel = 1;
2024  }
2025 
2026  setReadMethod();
2027 
2028  theTile = 0;
2029  if (theBuffer)
2030  {
2031  delete [] theBuffer;
2032  theBuffer = 0;
2033  }
2034  }
2035 }
2036 
2038 {
2039  return theApplyColorPaletteFlag;
2040 }
2041 
2043 {
2044  return ossimString("TIFF Image Handler");
2045 }
2046 
2048 {
2049  return ossimString("ossim_tiff");
2050 }
2051 
2053 {
2054  //***
2055  // Use a keyword format.
2056  //***
2057  os << "image_file: " << theImageFile
2058  << "\nsamples_per_pixel: " << theSamplesPerPixel
2059  << "\nbits_per_sample: " << theBitsPerSample
2060  << "\nsample_format_unit: " << theSampleFormatUnit
2061  << "\nmin_sample_value: " << theMinSampleValue
2062  << "\nmax_sample_value: " << theMaxSampleValue
2063  << "\nnull_sample_value: " << theNullSampleValue
2064  << "\ntheNumberOfDirectories: " << theNumberOfDirectories
2065  << "\nr0_is_full_res: " << theR0isFullRes;
2066 
2067 
2068  for (ossim_uint32 i=0; i<theNumberOfDirectories; ++i)
2069  {
2070  os << "\ndirectory[" << i << "]"
2071  << "\nimage width: " << theImageWidth[i]
2072  << "\nimage_length: " << theImageLength[i]
2073  << "\nread method: " << getReadMethod(i).c_str()
2074  << "\nplanar: " << thePlanarConfig[i]
2075  << "\nphotometric: " << thePhotometric[i];
2076  if (theRowsPerStrip[i])
2077  {
2078  os << "\nrows per strip: " << theRowsPerStrip[i];
2079  }
2080  if (theImageTileWidth[i])
2081  {
2082  os << "\ntile_width: " << theImageTileWidth[i];
2083  }
2084  if (theImageTileLength[i])
2085  {
2086  os << "\ntile_length: " << theImageTileLength[i];
2087  }
2088  os << endl;
2089  }
2090 
2091  if (theTile.valid())
2092  {
2093  os << "\nOutput tile dump:\n" << *theTile << endl;
2094  }
2095 
2096  if (theOverview.valid())
2097  {
2098  os << "\nOverview file:\n";
2099  theOverview->print(os);
2100  }
2101 
2102  os << endl;
2103 
2104  return ossimSource::print(os);
2105 }
2106 
2108 {
2109  return theSamplesPerPixel;
2110 }
2111 
2113 {
2114  ossim_uint32 bands = theOutputBandList.size();
2115  if ( !bands )
2116  {
2117  bands = getNumberOfInputBands();
2118  }
2119  return bands;
2120 }
2121 
2123 {
2124  bool result = false;
2125  if ( isOpen() && theReadMethod.size() && ( theReadMethod.size() == thePlanarConfig.size() ) )
2126  {
2127  // Tiled band separate currently is only coded to be band selector.
2128  result = true;
2129  for ( ossim_uint32 i = 0; i < theReadMethod.size(); ++i )
2130  {
2131  if ( ( theReadMethod[i] != READ_TILE ) ||
2132  ( thePlanarConfig[i] == PLANARCONFIG_CONTIG ) )
2133  {
2134  result = false;
2135  break;
2136  }
2137  }
2138  if ( result && theOverview.valid() )
2139  {
2140  result = theOverview->isBandSelector();
2141  }
2142  }
2143  return result;
2144 }
2145 
2146 bool ossimTiffTileSource::setOutputBandList(const std::vector<ossim_uint32>& band_list)
2147 {
2148  bool result = false;
2149  if ( isBandSelector() )
2150  {
2151  // Making a copy as passed in list could be our m_outputBandList.
2152  std::vector<ossim_uint32> inputList = band_list;
2154  if ( result && theTile.valid() )
2155  {
2156  if ( theTile->getNumberOfBands() != theOutputBandList.size() )
2157  {
2158  theTile = 0; // Force a reinitialize on next getTile.
2159  }
2160  }
2161  }
2162  return result;
2163 }
2164 
2165 void ossimTiffTileSource::getOutputBandList(std::vector<ossim_uint32>& bandList) const
2166 {
2167  if ( theOutputBandList.size() )
2168  {
2169  bandList = theOutputBandList;
2170  }
2171  else
2172  {
2174  }
2175 }
2176 
2178 {
2179  return (theTiffPtr!=NULL);
2180 }
2181 
2183 {
2184  return theR0isFullRes;
2185 }
2186 
2188 {
2190  {
2192  }
2193  return theMinSampleValue;
2194 }
2195 
2197 {
2199  {
2201  }
2202  return theMaxSampleValue;
2203 }
2204 
2206 {
2208  {
2210  }
2211  return theNullSampleValue;
2212 }
2213 
2215 {
2216  bool result = false;
2217 
2218  std::shared_ptr<const ossim::TiffHandlerState> state = getStateAs<ossim::TiffHandlerState>();
2219  if(state)
2220  {
2221  result = state->exists(TIFFCurrentDirectory(theTiffPtr),
2222  "tifftag.colormap.red");
2223  }
2224 
2225  return result;
2226 }
2227 
2229 {
2230  std::shared_ptr<ossim::TiffHandlerState> state = getStateAs<ossim::TiffHandlerState>();
2231 
2232  if(state)
2233  {
2234  for (ossim_uint32 dir=0; dir<theNumberOfDirectories; ++dir)
2235  {
2236  //---
2237  // Establish how this tiff directory will be read.
2238  //---
2239  if (state->isTiled(dir))
2240  {
2241  if ( ( thePhotometric[dir] == PHOTOMETRIC_YCBCR ||
2242  thePhotometric[dir] == PHOTOMETRIC_PALETTE ) &&
2243  (theSamplesPerPixel <= 3) &&
2244  (theBitsPerSample <= 8 ))
2245  {
2247  }
2248  else
2249  {
2250  theReadMethod[dir] = READ_TILE;
2251  }
2252  }
2253  else // Not tiled...
2254  {
2255  if ( (thePhotometric[dir] == PHOTOMETRIC_PALETTE ||
2256  thePhotometric[dir] == PHOTOMETRIC_YCBCR ) &&
2257  theSamplesPerPixel <= 3 &&
2258  theBitsPerSample <= 8 )
2259  {
2261  }
2262  else if (( theBitsPerSample == 16 ) &&
2263  ( theRowsPerStrip[dir] > 1 ) &&
2264  (( thePlanarConfig[dir] == PLANARCONFIG_SEPARATE ) ||
2265  ((thePlanarConfig[dir] == PLANARCONFIG_CONTIG) && (theSamplesPerPixel==1))))
2266  {
2267  // Buffer a strip of bands.
2269  }
2270  else if (theSamplesPerPixel <= 3 && theBitsPerSample == 1)
2271  {
2272  //---
2273  // Note: One bit data expands to zeroes and 255's so run it through
2274  // a specialized method to flip zeroes to one's since zeroes
2275  // are usually reserved for null value.
2276  //---
2278  }
2279  else if((theCompressionType == COMPRESSION_NONE)||
2280  (theRowsPerStrip[dir]==1))
2281  {
2283  }
2285  (theSamplesPerPixel <= 4) &&
2286  (theBitsPerSample <= 8) )
2287  {
2289  }
2290  else
2291  {
2292  theReadMethod[dir] = UNKNOWN;
2293  }
2294  }
2295 
2296  } // End of loop through directories.
2297  }
2298  // Reset the directory back to "0".
2299 // setTiffDirectory(0);
2300 }
2301 
2303 {
2304  if(!property.valid())
2305  {
2306  return;
2307  }
2308  if(property->getName() == "apply_color_palette_flag")
2309  {
2310  // Assuming first directory...
2311  setApplyColorPaletteFlag(property->valueToString().toBool());
2312  }
2313  else
2314  {
2316  }
2317 }
2318 
2320 {
2321  if(name == "apply_color_palette_flag")
2322  {
2323  ossimBooleanProperty* property = new ossimBooleanProperty("apply_color_palette_flag",
2325  property->clearChangeType();
2326  property->setFullRefreshBit();
2327  return property;
2328  }
2329  else if(name == "file_type")
2330  {
2331  return new ossimStringProperty(name, "TIFF");
2332  }
2333 
2334  return ossimImageHandler::getProperty(name);
2335 }
2336 
2337 void ossimTiffTileSource::getPropertyNames(std::vector<ossimString>& propertyNames)const
2338 {
2339  ossimImageHandler::getPropertyNames(propertyNames);
2340  propertyNames.push_back("file_type");
2341  propertyNames.push_back("apply_color_palette_flag");
2342 }
2343 
2345 {
2346  bool status = true;
2348  if (theCurrentDirectory != directory)
2349  {
2350  status = TIFFSetDirectory(theTiffPtr, directory);
2351  if (status == true)
2352  {
2353  theCurrentDirectory = directory;
2354  }
2355  else
2356  {
2357  if(traceDebug())
2358  {
2360  << "ossimTiffTileSource::setTiffDirectory ERROR setting directory "
2361  << directory << "!" << endl;
2362  }
2363  }
2364  }
2365 
2366  ossim_uint32 idx = 0;
2367  for(idx = 0; idx<theImageDirectoryList.size();++idx)
2368  {
2369  if(theImageDirectoryList[idx] == directory)
2370  {
2371  theCurrentTiffRlevel = idx;
2372  break;
2373  }
2374  }
2375  return status;
2376 }
2377 
2379 {
2380  std:shared_ptr<ossim::TiffHandlerState> state = getStateAs<ossim::TiffHandlerState>();
2381  ossimString red;
2382  ossimString green;
2383  ossimString blue;
2384  ossim_uint32 currentDir = TIFFCurrentDirectory(theTiffPtr);
2385  if(state->getValue(red, currentDir, "tifftag.colormap.red")&&
2386  state->getValue(green, currentDir, "tifftag.colormap.green")&&
2387  state->getValue(blue, currentDir, "tifftag.colormap.blue"))
2388  {
2389  std::vector<ossim_uint16> redValues;
2390  std::vector<ossim_uint16> greenValues;
2391  std::vector<ossim_uint16> blueValues;
2392  if(ossim::toSimpleVector(redValues, red)&&
2393  ossim::toSimpleVector(greenValues, green)&&
2394  ossim::toSimpleVector(blueValues, blue))
2395  {
2396  if(((redValues.size()==greenValues.size())&&(redValues.size()==blueValues.size()))&&
2397  (redValues.size()==256||redValues.size()==65536))
2398 
2399  {
2400  ossim_uint16* r = &redValues.front();
2401  ossim_uint16* g = &greenValues.front();
2402  ossim_uint16* b = &blueValues.front();
2403  ossim_uint32 numEntries = redValues.size();
2404  ossimScalarType scalarType = OSSIM_UINT8;
2405  if(theBitsPerSample == 16)
2406  {
2407  scalarType = OSSIM_UINT16;
2408  }
2409  theLut = new ossimNBandLutDataObject(numEntries,
2410  3,
2411  scalarType,
2412  0);
2413  ossim_uint32 entryIdx = 0;
2414  for(entryIdx = 0; entryIdx < numEntries; ++entryIdx)
2415  {
2416  if(scalarType == OSSIM_UINT8)
2417  {
2418  (*theLut)[entryIdx][0] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(((*r)/65535.0)*255.0);
2419  (*theLut)[entryIdx][1] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(((*g)/65535.0)*255.0);
2420  (*theLut)[entryIdx][2] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(((*b)/65535.0)*255.0);
2421  }
2422  else
2423  {
2424  (*theLut)[entryIdx][0] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(*r);
2425  (*theLut)[entryIdx][1] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(*g);
2426  (*theLut)[entryIdx][2] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(*b);
2427  }
2428  ++r;++g;++b;
2429  }
2430 
2431  }
2432  }
2433  }
2434 }
2435 
2437 {
2441 
2442  if( (theMinSampleValue == tempNull) || ossim::isnan(theMinSampleValue) )
2443  {
2444  theMinSampleValue = tempMin;
2445  }
2446  if( (theMaxSampleValue == tempNull) || ossim::isnan(theMaxSampleValue) )
2447  {
2448  theMaxSampleValue = tempMax;
2449  }
2451  {
2452  theNullSampleValue = tempNull;
2453  }
2454 
2456  {
2457  std::ifstream inStr(theImageFile.c_str(), std::ios::in|std::ios::binary);
2458  if ( inStr.good() )
2459  {
2460  // Do a print to a memory stream in key:value format.
2461  ossimTiffInfo ti;
2462  ossimIOMemoryStream memStr;
2463  ti.print(inStr, memStr);
2464 
2465  // Make keywordlist with all the tags.
2466  ossimKeywordlist gtiffKwl;
2467  if ( gtiffKwl.parseStream(memStr) )
2468  {
2469 #if 0 /* Please keep for debug. (drb) */
2470  if ( traceDebug() )
2471  {
2473  << "ossimTiffTileSource::validateMinMaxNull kwl:\n" << gtiffKwl
2474  << endl;
2475  }
2476 #endif
2477  const char* lookup;
2478 
2479  lookup = gtiffKwl.find("tiff.image0.gdal_nodata");
2480  bool nullFound = false;
2481  if ( lookup )
2482  {
2483  ossimString os = lookup;
2485  nullFound = true;
2486  }
2487  lookup = gtiffKwl.find("tiff.image0.vertical_citation");
2488  if ( lookup )
2489  {
2490  //---
2491  // Format of string this handles:
2492  // "Null: -9999.000000, Non-Null Min: 12.428605,
2493  // Non-Null Avg: 88.944082, Non-Null Max: 165.459558|"
2494  ossimString citation = lookup;
2495  std::vector<ossimString> array;
2496  citation.split( array, ossimString(",") );
2497  if ( array.size() == 4 )
2498  {
2499  std::vector<ossimString> array2;
2500 
2501  if ( !nullFound )
2502  {
2503  // null
2504  array[0].split( array2, ossimString(":") );
2505  if ( array2.size() == 2 )
2506  {
2507  ossimString os = array2[0].downcase();
2508  if ( os.contains( ossimString("null") ) )
2509  {
2510  if ( array2[1].size() )
2511  {
2512  theNullSampleValue = array2[1].toFloat64();
2513  nullFound = true;
2514  }
2515  }
2516  }
2517  }
2518 
2519  // min
2520  array2.clear();
2521  array[1].split( array2, ossimString(":") );
2522  if ( array2.size() == 2 )
2523  {
2524  ossimString os = array2[0].downcase();
2525  if ( os.contains( ossimString("min") ) )
2526  {
2527  if ( array2[1].size() )
2528  {
2529  theMinSampleValue = array2[1].toFloat64();
2530  }
2531  }
2532  }
2533 
2534  // Skipping average.
2535 
2536  // max
2537  array2.clear();
2538  array[3].split( array2, ossimString(":") );
2539  if ( array2.size() == 2 )
2540  {
2541  ossimString os = array2[0].downcase();
2542  if ( os.contains( ossimString("max") ) )
2543  {
2544  if ( array2[1].size() )
2545  {
2546  array2[1].trim( ossimString("|") );
2547  theMaxSampleValue = array2[1].toFloat64();
2548  }
2549  }
2550  }
2551  }
2552  }
2553  }
2554  }
2555  }
2556 }
2557 
2559 {
2560  // Check size of this level against last level to see if it's half the previous.
2561  bool result = false;
2562  if ( (level > 0) && ( theImageWidth.size() > level ) && ( theImageLength.size() > level ) )
2563  {
2564  ossim_uint32 i = level-1; // previous level
2565 
2566  if ( ( ( theImageWidth[i]/2 == theImageWidth[level] ) ||
2567  ( (theImageWidth[i]+1)/2 == theImageWidth[level] ) ) &&
2568  ( ( theImageLength[i]/2 == theImageLength[level] ) ||
2569  ( (theImageLength[i]+1)/2 == theImageLength[level] ) ) )
2570  {
2571  result = true;
2572  }
2573  }
2574  return result;
2575 }
2576 
2578 {
2579  theTile = 0;
2580  ossim_uint32 bands = 0;
2581  if ( theOutputBandList.empty() )
2582  {
2583  bands = getNumberOfOutputBands();
2584  }
2585  else
2586  {
2587  bands = theOutputBandList.size();
2588  }
2589 
2590  if ( bands )
2591  {
2593  if ( theTile.valid() )
2594  {
2595  theTile->initialize();
2596 
2597  // The width and height mus be set prior to call to allocateBuffer.
2600  }
2601  }
2602 }
2603 
2605 {
2606  bool bSuccess = true;
2607  // Allocate memory for a buffer to hold data grabbed from the tiff file.
2608  ossim_uint32 buffer_size=0;
2610  {
2611  case READ_RGBA_U8_TILE:
2612  {
2613  buffer_size = theImageTileWidth[theCurrentDirectory]*
2615  break;
2616  }
2617  case READ_TILE:
2618  {
2619  if (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG)
2620  {
2621  buffer_size = theImageTileWidth[theCurrentDirectory] *
2624  }
2625  else
2626  {
2627  buffer_size = theImageTileWidth[theCurrentDirectory] *
2630  }
2631  break;
2632  }
2633  case READ_RGBA_U8_STRIP:
2634  case READ_RGBA_U8A_STRIP:
2635  {
2637  theBytesPerPixel*4;
2638  break;
2639  }
2640  case READ_U16_STRIP:
2641  {
2642  // Encountered case where it was multiple rows per strip, yet PLANARCONFIG_CONTIG. The
2643  // case was in fact single band so planar config is irrelevant. (OLK July 2015)
2644 
2645  // I put the multiplication back in for the theSamplesPerPixel. In the read method that is used for this
2646  // it populates this buffer with all bands and then uses the load method on the image data object.
2647  // so all bands has to be populated for the buffer. (GCP Sept 2015)
2650  // I commented this out for this is core dumping for one of the tiff images. (GCP Sept 2015)
2651  // if (thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG)
2652  // buffer_size *= theSamplesPerPixel;
2653  break;
2654  }
2655  case READ_SCAN_LINE:
2656  {
2657 #if OSSIM_BUFFER_SCAN_LINE_READS
2658  // Buffer a image width by tile height.
2659  buffer_size = theImageWidth[0] * theBytesPerPixel *
2661 #else
2662  buffer_size = theImageWidth[0] * theBytesPerPixel * theSamplesPerPixel;
2663 #endif
2664  break;
2665  }
2666  default:
2667  {
2669  << "Unknown read method!" << endl;
2671  bSuccess = false;
2672  }
2673  }
2674 
2675  if (traceDebug())
2676  {
2678  << "ossimTiffTileSource::allocateBuffer DEBUG:"
2679  << "\nbuffer_size: " << buffer_size
2680  << endl;
2681  }
2682 
2685 
2686  if ( bSuccess && ( buffer_size != theBufferSize ) )
2687  {
2688  theBufferSize = buffer_size;
2689  if (theBuffer)
2690  {
2691  delete [] theBuffer;
2692  }
2693 
2694  // ESH 05/2009 -- Fix for ticket #738:
2695  // image_info crashing on aerial_ortho image during ingest
2696  try
2697  {
2698  theBuffer = new ossim_uint8[buffer_size];
2699  }
2700  catch(...)
2701  {
2702  theBuffer = 0;
2703  bSuccess = false;
2704  if (traceDebug())
2705  {
2707  << "ossimTiffTileSource::allocateBuffer WARN:"
2708  << "\nNot enough memory: buffer_size: " << buffer_size
2709  << endl;
2710  }
2711  }
2712  }
2713 
2714  return bSuccess;
2715 }
16 bit unsigned integer (15 bits used)
virtual void loadBand(const void *src, const ossimIrect &src_rect, ossim_uint32 band)
void set_uly(ossim_int32 y)
Definition: ossimIrect.h:666
virtual void valueToString(ossimString &valueResult) const =0
virtual ossim_uint32 getWidth() const
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
std::vector< ossim_uint32 > theImageTileWidth
std::vector< ossim_uint32 > theOutputBandList
ossim_float64 theMaxSampleValue
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
ossim_uint32 theCurrentTiffRlevel
bool open()
Returns true if no errors initializing object.
virtual ossim_uint32 getNumberOfBands() const
ossim_uint32 theCurrentTileWidth
64 bit floating point
#define CLOG
Definition: ossimTrace.h:23
ossimFilename theImageFile
virtual void setImageRectangle(const ossimIrect &rect)
16 bit unsigned integer
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual bool isOpen() const
Derived classes must implement this method to be concrete.
Represents serializable keyword/value map.
const std::string & findKey(const std::string &key) const
Find methods that take std::string(s).
void setState(std::shared_ptr< ossim::ImageHandlerState > state)
std::basic_ifstream< char > ifstream
Class for char input file streams.
Definition: ossimIosFwd.h:44
bool valid() const
Definition: ossimRefPtr.h:75
std::shared_ptr< ossim::TiffIStreamAdaptor > m_streamAdaptor
void allocateTile()
Allocates theTile.
const char * find(const char *key) const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual ossim_float64 getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
This code was derived from https://gist.github.com/mshockwave.
Definition: Barrier.h:8
virtual ossim_uint32 getNumberOfDecimationLevels() const
Returns the number of reduced resolution data sets (rrds).
virtual ossim_uint32 getImageTileWidth() const
#define OSSIM_TIFF_UNPACK_R4(value)
ossim_uint32 height() const
Definition: ossimIrect.h:487
bool contains(char aChar) const
Definition: ossimString.h:58
std::vector< ossim_uint32 > theRowsPerStrip
virtual ossim_uint32 getTileWidth() const
Returns the width of the output tile.
OSSIM_DLL void defaultTileSize(ossimIpt &tileSize)
16 bit signed integer
void toSimpleStringList(ossimString &result, const std::vector< T > &valuesList)
This will output a vector of values inst a string.
Definition: ossimCommon.h:484
const ossimIpt & ul() const
Definition: ossimIrect.h:274
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
16 bit unsigned integer (14 bits used)
static const ossimErrorCode OSSIM_ERROR
virtual ossimString getClassName() const
Definition: ossimObject.cpp:64
ossim_uint32 toUInt32() const
16 bit unsigned integer (13 bits used)
static StreamFactoryRegistry * instance()
32 bit floating point
bool intersects(const ossimIrect &rect) const
Definition: ossimIrect.cpp:183
bool hasR0() const
Returns true if the first directory of the tiff image did not have the reduced resolution file type s...
TIFF info class.
Definition: ossimTiffInfo.h:36
unsigned short ossim_uint16
#define abs(a)
Definition: auxiliary.h:74
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual ossim_float64 getMinPixelValue(ossim_uint32 band=0) const
Retuns the min pixel value.
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
32 bit unsigned integer
ossim_uint32 theCurrentTileHeight
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
virtual ossimString getShortName() const
virtual void initialize()
Initialize the data buffer.
void ref() const
increment the reference count by one, indicating that this object has another pointer which is refere...
bool loadFromRgbaU8Tile(const ossimIrect &tile_rect, const ossimIrect &clip_rect, ossimImageData *result)
ossim_uint32 getNumberOfBands() const
ossim_uint16 theSamplesPerPixel
ossimPixelType thePixelType
bool loadFromRgbaU8Strip(const ossimIrect &tile_rect, const ossimIrect &clip_rect, ossimImageData *result)
ossim_uint16 theNumberOfDirectories
std::vector< ossim_uint32 > theImageDirectoryList
virtual ossim_uint32 getNumberOfDecimationLevels() const
This returns the total number of decimation levels.
void setApplyColorPaletteFlag(bool flag)
bool toSimpleVector(std::vector< T > &result, const ossimString &stringOfPoints)
Definition: ossimCommon.h:537
virtual ossim_uint32 getImageTileHeight() const
virtual double getMinPixelValue(ossim_uint32 band=0) const
Retuns the min pixel value.
ossim_int32 toInt32() const
bool completely_within(const ossimIrect &rect) const
Definition: ossimIrect.cpp:425
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual void loadTile(const void *src, const ossimIrect &src_rect, ossimInterleaveType il_type)
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
OSSIM_DLL double defaultMin(ossimScalarType scalarType)
Definition: ossimCommon.cpp:73
virtual void getOutputBandList(std::vector< ossim_uint32 > &bandList) const
Initializes bandList.
virtual ossimString getLongName() const
bool allocateBuffer()
Allocates theBuffer.
virtual bool getOverviewTile(ossim_uint32 resLevel, ossimImageData *result)
Method to get an overview tile.
static ossimImageDataFactory * instance()
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &rect, ossim_uint32 resLevel=0)
Returns a pointer to a tile given an origin representing the upper left corner of the tile to grab fr...
ossim_float64 theNullSampleValue
virtual ossim_uint32 getNumberOfInputBands() const
Returns the number of bands in the image.
yy_size_t size
virtual ossimDataObjectStatus validate() const
virtual ossim_uint32 getNumberOfDirectories() const
Returns the number of image file directories in the tiff image.
virtual bool isValidRLevel(ossim_uint32 resLevel) const
Determines if the passed in reslution level is valid.
std::string::size_type size() const
Definition: ossimString.h:405
32 bit signed integer
bool toBool() const
String to numeric methods.
OSSIM_DLL double defaultNull(ossimScalarType scalarType)
virtual ossim_uint32 getTileHeight() const
Returns the height of the output tile.
virtual bool isIdentityBandList(const std::vector< ossim_uint32 > &bandList) const
Convenience method to see if band list is identity.
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
ossimString trim(const ossimString &valueToTrim=ossimString(" \\)) const
this will strip lead and trailing character passed in.
virtual ossimIrect getImageRectangle() const
bool loadFromU16Strip(const ossimIrect &clip_rect, ossimImageData *result)
ossim_float32 toFloat32() const
bool isPowerOfTwoDecimation(ossim_uint32 dir) const
Checks line/samples of level for power of two decimation from the previous rlevel.
const ossimIpt & lr() const
Definition: ossimIrect.h:276
virtual void close()
Deletes the overview and clears the valid image vertices.
ossim_uint32 getCurrentTiffRLevel() const
If the tiff source has R0 then this returns the current tiff directory that the tiff pointer is point...
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
ossimInterleaveType
virtual ossimIrect getImageRectangle(ossim_uint32 resLevel=0) const
Returns zero-based bounding rectangle of the image.
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossim_float64 theMinSampleValue
ossim_uint32 width() const
Definition: ossimIrect.h:500
static const char * BANDS_KW
ossimIrect clipToRect(const ossimIrect &rect) const
Definition: ossimIrect.cpp:501
virtual void close()
Deletes the overview and clears the valid image vertices.
virtual bool isBandSelector() const
Indicates whether or not the image handler can control output band selection via the setOutputBandLis...
bool loadFromScanLine(const ossimIrect &clip_rect, ossimImageData *result)
virtual std::ostream & print(std::ostream &out) const
Print method.
std::vector< ossim_uint32 > theImageLength
ossimScalarType
void unref() const
decrement the reference count by one, indicating that a pointer to this object is referencing it...
void validateMinMaxNull()
validateMinMaxNull Checks min, max and null to make sure they are not equal to the scalar type nan or...
ossim_uint16 toUInt16() const
virtual const ossim_float64 * getMinPix() const
virtual void getOutputBandList(std::vector< ossim_uint32 > &bandList) const
Initializes bandList to the zero based order of output bands.
return status
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual void makeBlank()
Initializes data to null pixel values.
ossimScalarType theScalarType
std::vector< ossim_uint16 > thePhotometric
ossimRefPtr< ossimImageData > theTile
virtual void completeOpen()
Will complete the opening process.
16 bit unsigned integer (11 bits used)
ossimString getReadMethod(ossim_uint32 directory) const
virtual ossim_float64 getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
#define OSSIM_TIFF_UNPACK_B4(value)
bool loadFromTile(const ossimIrect &clip_rect, ossimImageData *result)
ossimImageMetaData theMetaData
OSSIM_DLL double defaultMax(ossimScalarType scalarType)
#define OSSIM_TIFF_UNPACK_G4(value)
ossimRefPtr< ossimImageHandler > theOverview
std::vector< ossim_uint16 > thePlanarConfig
This class defines an abstract Handler which all image handlers(loaders) should derive from...
void set_lry(ossim_int32 y)
Definition: ossimIrect.h:702
std::vector< ossim_uint32 > theImageTileLength
ossim_int32 y
Definition: ossimIpt.h:142
virtual bool isBandSelector() const
Indicates whether or not the image handler can control output band selection via the setOutputBandLis...
virtual void setProperty(ossimRefPtr< ossimProperty > property)
void makeNan()
Definition: ossimIrect.h:329
virtual const void * getBuf() const
virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel=0) const
Returns the number of lines in the image.
bool loadTile(const ossimIrect &tile_rect, const ossimIrect &clip_rect, ossimImageData *result)
virtual bool parseStream(ossim::istream &is, bool ignoreBinaryChars)
deprecated method
ossim_uint16 theCurrentDirectory
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
class ossimNBandLutDataObject
ossim_uint16 theSampleFormatUnit
bool loadFromRgbaU8aStrip(const ossimIrect &tile_rect, const ossimIrect &clip_rect, ossimImageData *result)
std::vector< ReadMethod > theReadMethod
bool setTiffDirectory(ossim_uint16 directory)
Change tiff directory and sets theCurrentDirectory.
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
ossim_int32 x
Definition: ossimIpt.h:141
std::vector< ossim_uint32 > theImageWidth
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
virtual std::shared_ptr< ossim::istream > createIstream(const std::string &connectionString, const ossimKeywordlist &options=ossimKeywordlist(), std::ios_base::openmode mode=std::ios_base::in|std::ios_base::binary) const
Will try to creates an istream interface to the connectionString passed in.
ossimRefPtr< ossimNBandLutDataObject > theLut
8 bit unsigned integer
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
virtual void copyLine(const void *src, ossim_int32 lineNumber, ossim_int32 lineStartSample, ossim_int32 lineStopSample, ossimInterleaveType lineInterleave)
Method to copy a single line to the tile.
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel=0) const
Returns the number of samples in the image.
virtual std::ostream & print(std::ostream &os) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
virtual bool setOutputBandList(const std::vector< ossim_uint32 > &band_list)
If the image handler "isBandSeletor()" then the band selection of the output chip can be controlled...
bool getApplyColorPaletteFlag() const
virtual double getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
void adjustToStartOfTile(ossimIpt &pt) const
Adjust point to even tile boundary.
virtual ossimScalarType getOutputScalarType() const
Returns the output pixel type of the tile source.
unsigned char ossim_uint8
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual bool setOutputBandList(const std::vector< ossim_uint32 > &band_list)
If the image handler "isBandSeletor()" then the band selection of the output chip can be controlled...
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
const ossimString & getName() const
int ossim_int32
ossim_uint32 theStartingResLevel
theStartingResLevel If set to something other than zero(default) this is indicative that the reader i...
const std::string & string() const
Definition: ossimString.h:414
16 bit unsigned integer (12 bits used)
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91