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 //
9 // Description:
10 //
11 // This class defines an abstract image handler which all loaders should
12 // derive from.
13 //
14 //*******************************************************************
15 //  $Id: ossimImageHandler.cpp 23013 2014-12-02 19:21:56Z okramer $
16 
17 #include <ossim/imaging/ossimImageHandler.h>
18 #include <ossim/base/ossimBooleanProperty.h>
19 #include <ossim/base/ossimCommon.h>
20 #include <ossim/base/ossimException.h>
21 #include <ossim/base/ossimContainerEvent.h>
22 #include <ossim/base/ossimEventIds.h>
23 #include <ossim/base/ossimFilenameProperty.h>
24 #include <ossim/base/ossimNumericProperty.h>
25 #include <ossim/base/ossimStringProperty.h>
26 #include <ossim/base/ossimKeywordlist.h>
27 #include <ossim/base/ossimKeywordNames.h>
28 #include <ossim/base/ossimNotify.h>
29 #include <ossim/base/ossimPolygon.h>
30 #include <ossim/base/ossimPreferences.h>
31 #include <ossim/base/ossimStdOutProgress.h>
32 #include <ossim/base/ossimTrace.h>
33 #include <ossim/base/ossimScalarTypeLut.h>
34 #include <ossim/imaging/ossimHistogramWriter.h>
35 #include <ossim/imaging/ossimImageGeometryRegistry.h>
36 #include <ossim/imaging/ossimImageHandlerRegistry.h>
37 #include <ossim/imaging/ossimImageHistogramSource.h>
38 #include <ossim/imaging/ossimTiffTileSource.h>
39 #include <ossim/imaging/ossimTiffOverviewBuilder.h>
40 #include <ossim/projection/ossimProjection.h>
41 #include <ossim/projection/ossimProjectionFactoryRegistry.h>
42 #include <algorithm>
43 
44 using namespace std;
45 
46 RTTI_DEF1(ossimImageHandler, "ossimImageHandler", ossimImageSource)
47 
48 // Static trace for debugging
49 static ossimTrace traceDebug("ossimImageHandler:debug");
50 
51 // Property keywords.
52 static const char HAS_LUT_KW[]                 = "has_lut";
53 static const char OPEN_OVERVIEW_FLAG_KW[]      = "open_overview_flag";
54 static const char START_RES_LEVEL_KW[]         = "start_res_level";
55 static const char SUPPLEMENTARY_DIRECTORY_KW[] = "supplementary_directory";
56 static const char VALID_VERTICES_FILE_KW[]     = "valid_vertices_file";
57 
58 #ifdef OSSIM_ID_ENABLED
59 static const char OSSIM_ID[] = "$Id: ossimImageHandler.cpp 23013 2014-12-02 19:21:56Z okramer $";
60 #endif
61 
62 // GARRETT! All of the decimation factors are scattered throughout. We want to fold that into
63 // the image geometry object. The code is ready in ossimImageGeometry for this (more or less), but
64 // the ossimImageGeometry::m_decimationFactors is not being set nor referenced. Can you do this?
65 // I'm a little foggy on how we want to incorporate R-level scaling into the geometry object.
66 
ossimImageHandler()67 ossimImageHandler::ossimImageHandler()
68 :
69 ossimImageSource(0, 0, 0, true, false /* output list is not fixed */ ),
70 theImageFile(ossimFilename::NIL),
71 theOverviewFile(ossimFilename::NIL),
72 theSupplementaryDirectory(ossimFilename::NIL),
73 theOverview(0),
74 theValidImageVertices(0),
75 theMetaData(),
76 theGeometry(),
77 theLut(0),
78 theDecimationFactors(0),
79 theImageID(""),
80 theStartingResLevel(0),
81 theOpenOverviewFlag(true),
82 thePixelType(OSSIM_PIXEL_IS_POINT)
83 {
84    if (traceDebug())
85    {
86       ossimNotify(ossimNotifyLevel_DEBUG)
87          << "ossimImageHandler::ossimImageHandler() DEBUG:" << std::endl;
88 #ifdef OSSIM_ID_ENABLED
89       ossimNotify(ossimNotifyLevel_DEBUG)
90          << "OSSIM_ID:  "
91          << OSSIM_ID
92          << std::endl;
93 #endif
94    }
95 
96    // Check for global preference supplementary dir.
97    theSupplementaryDirectory.string() = ossimPreferences::instance()->
98       preferencesKWL().findKey( std::string("ossim_supplementary_directory") );
99 }
100 
~ossimImageHandler()101 ossimImageHandler::~ossimImageHandler()
102 {
103    theOverview = 0;
104 }
105 
initialize()106 void ossimImageHandler::initialize()
107 {
108 }
109 
110 //*******************************************************************
111 // Public method:
112 //*******************************************************************
saveState(ossimKeywordlist & kwl,const char * prefix) const113 bool ossimImageHandler::saveState(ossimKeywordlist& kwl,
114                                   const char* prefix) const
115 {
116    static const char MODULE[] = "ossimImageHandler::saveState";
117 
118    ossimImageSource::saveState(kwl, prefix);
119    if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR)
120    {
121       ossimNotify(ossimNotifyLevel_WARN)
122          << MODULE
123          << " ERROR detected in keyword list!  State not saved."
124          << std::endl;
125       return false;
126    }
127 
128    kwl.add(prefix, ossimKeywordNames::FILENAME_KW, theImageFile.c_str(), true);
129    kwl.add(prefix, HAS_LUT_KW, (theLut.valid()?"true":"false"), true);
130    kwl.add(prefix, ossimKeywordNames::IMAGE_ID_KW, theImageID, true);
131    kwl.add(prefix, ossimKeywordNames::OVERVIEW_FILE_KW, theOverviewFile.c_str(), true);
132    kwl.add(prefix, SUPPLEMENTARY_DIRECTORY_KW, theSupplementaryDirectory.c_str(), true);
133    kwl.add(prefix, START_RES_LEVEL_KW, theStartingResLevel, true);
134    kwl.add(prefix, OPEN_OVERVIEW_FLAG_KW, (theOpenOverviewFlag?"1":"0"), true);
135    kwl.add(prefix, ossimKeywordNames::PIXEL_TYPE_KW, (ossim_uint16) thePixelType, true);
136 
137    return true;
138 }
139 
140 //*******************************************************************
141 // Public method:
142 //*******************************************************************
loadState(const ossimKeywordlist & kwl,const char * prefix)143 bool ossimImageHandler::loadState(const ossimKeywordlist& kwl,
144                                   const char* prefix)
145 {
146    static const char MODULE[] = "ossimImageHandler::loadState(kwl, prefix)";
147    theDecimationFactors.clear();
148    if(traceDebug())
149    {
150       ossimNotify(ossimNotifyLevel_DEBUG)
151          << MODULE << " DEBUG: entered ..."
152          << std::endl;
153    }
154 
155    ossimImageSource::loadState(kwl, prefix);
156 
157    if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_ERROR)
158    {
159       ossimNotify(ossimNotifyLevel_WARN)
160          << MODULE
161          << "WARNING: error detected in keyword list!  State not load."
162          << std::endl;
163 
164       if(traceDebug())
165       {
166          ossimNotify(ossimNotifyLevel_DEBUG)
167             << MODULE << " DEBUG: "
168             << "leaving with error in kwl ..." << std::endl;
169       }
170       return false;
171    }
172 
173    const char* lookup = kwl.find(prefix, ossimKeywordNames::FILENAME_KW);
174    if (!lookup)
175    {
176       // Deprecated...
177       lookup = kwl.find(prefix, ossimKeywordNames::IMAGE_FILE_KW);
178    }
179 
180    if (lookup)
181    {
182       theImageFile = lookup;
183    }
184 
185    lookup = kwl.find(prefix, ossimKeywordNames::OVERVIEW_FILE_KW);
186    if(lookup)
187    {
188       theOverviewFile = ossimFilename(lookup);
189    }
190    if(traceDebug())
191    {
192       ossimNotify(ossimNotifyLevel_DEBUG)
193          << MODULE << " DEBUG:\n"
194          << "filename = " << theImageFile << std::endl;
195    }
196 
197    // Check for an external geometry file to initialize our image geometry object:
198    lookup = kwl.find(prefix, ossimKeywordNames::GEOM_FILE_KW);
199    if (lookup)
200    {
201       ossimKeywordlist geomKwl;
202       if (geomKwl.addFile(lookup) == true)
203       {
204          theGeometry = new ossimImageGeometry;
205          theGeometry->loadState(geomKwl);
206          if(traceDebug())
207          {
208             ossimNotify(ossimNotifyLevel_DEBUG)
209                << MODULE << " DEBUG:"
210                << "Loaded external geometry file:  "
211                << lookup
212                << "\n" << geomKwl << std::endl;
213          }
214       }
215    }
216 
217    // Check for an valid image vetices file.
218    lookup = kwl.find(prefix, VALID_VERTICES_FILE_KW);
219    if (lookup)
220    {
221       initVertices(lookup);
222    }
223 
224    // Starting resolution level.
225    lookup = kwl.find(prefix, START_RES_LEVEL_KW);
226    if (lookup)
227    {
228       theStartingResLevel = ossimString(lookup).toUInt32();
229    }
230 
231    // Open overview flag.
232    lookup = kwl.find(prefix, OPEN_OVERVIEW_FLAG_KW);
233    if (lookup)
234    {
235       setOpenOverviewFlag( ossimString(lookup).toBool() );
236    }
237 
238    // The supplementary directory for finding the overview
239    lookup = kwl.find(prefix, SUPPLEMENTARY_DIRECTORY_KW);
240    if (lookup)
241    {
242       theSupplementaryDirectory = ossimFilename(lookup);
243    }
244 
245    if(getNumberOfInputs())
246    {
247       theInputObjectList.clear();
248    }
249    theInputListIsFixedFlag = true;
250 
251    // Read image id if present:
252    theImageID = kwl.find(prefix, ossimKeywordNames::IMAGE_ID_KW);
253 
254    lookup = kwl.find(prefix, ossimKeywordNames::PIXEL_TYPE_KW);
255    if (lookup)
256    {
257       thePixelType = (ossimPixelType) atoi(lookup);
258    }
259 
260    if(traceDebug())
261    {
262       ossimNotify(ossimNotifyLevel_DEBUG)
263          << MODULE << " DEBUG: Leaving Ok ..."
264          << std::endl;
265    }
266    return true;
267 }
268 
initVertices(const char * file)269 bool ossimImageHandler::initVertices(const char* file)
270 {
271    static const char MODULE[] = "ossimImageHandler::initVertices";
272    bool loadFromFileFlag = true;
273    std::shared_ptr<ossimKeywordlist> kwl;
274    if(m_state)
275    {
276       bool validVerticesFlag = false;
277       if(m_state->getValidVertices())
278       {
279          loadFromFileFlag = false;
280          kwl = m_state->getValidVertices();
281          if(kwl)
282          {
283             ossimString connectionString = kwl->find("connection_string");
284             if(connectionString != file)
285             {
286                loadFromFileFlag = true;
287             }
288             else if(kwl->getSize()<=0)
289             {
290                return false;
291             }
292          }
293       }
294       else
295       {
296          loadFromFileFlag = true;
297       }
298    }
299    if(!kwl) kwl = std::make_shared<ossimKeywordlist>();
300 
301    if(loadFromFileFlag)
302    {
303       kwl = std::make_shared<ossimKeywordlist>();
304       std::shared_ptr<ossim::istream> instream = ossim::StreamFactoryRegistry::instance()->createIstream(file);
305       kwl->add("connection_string", file, true);
306       if (!instream)
307       {
308          //if(m_state)
309          //   m_state->setValidVertices(kwl);
310          return false;
311       }
312 
313       kwl->parseStream(*instream);
314       if(m_state && kwl->getSize())
315          m_state->setValidVertices(kwl);
316    }
317 
318    if (kwl->getErrorStatus() != ossimErrorCodes::OSSIM_OK)
319    {
320       if (traceDebug())
321       {
322          ossimNotify(ossimNotifyLevel_DEBUG)
323             << "ossimImageHandler::initVertices NOTICE:"
324             << "\nError reading valid vertice file:  " << file << std::endl;
325       }
326       return false;
327    }
328 
329    // Clean out any old vertices...
330    theValidImageVertices.clear();
331    std::vector<ossimString> indexedPrefixes;
332    kwl->getSortedList(indexedPrefixes, "point");
333    ossim_uint32 number_of_points = indexedPrefixes.size();
334    for (ossim_uint32 i=0; i<number_of_points; i++)
335    {
336       ossimIpt pt;
337       const char* lookup;
338       lookup = kwl->find(indexedPrefixes[i], ".x");
339       if (lookup)
340       {
341          pt.x = atoi(lookup);
342          lookup = kwl->find(indexedPrefixes[i], ".y");
343          if (lookup)
344             pt.y = atoi(lookup);
345       }
346 
347       if (!lookup)
348       {
349          if (traceDebug())
350             CLOG << " ERROR: lookup failed for: " << indexedPrefixes[i] << std::endl;
351          return false;
352       }
353 
354       theValidImageVertices.push_back(pt);
355    }
356 
357 
358    if (traceDebug())
359    {
360       CLOG << " DEBUG:"
361            << "\nVertices file:  " << file
362            << "\nValid image vertices:"
363            << std::endl;
364       for (ossim_uint32 i=0; i<theValidImageVertices.size(); ++i)
365       {
366          ossimNotify(ossimNotifyLevel_DEBUG)
367             << "\npoint[" << i << "]:  " << theValidImageVertices[i];
368       }
369       ossimNotify(ossimNotifyLevel_DEBUG) << std::endl;
370    }
371 
372    return true;
373 }
374 
getNumberOfDecimationLevels() const375 ossim_uint32 ossimImageHandler::getNumberOfDecimationLevels() const
376 {
377    ossim_uint32 result = 1; // Add r0
378    if (theOverview.valid())
379    {
380       result += theOverview->getNumberOfDecimationLevels();
381    }
382    return result;
383 }
384 
getNumberOfReducedResSets() const385 ossim_uint32 ossimImageHandler::getNumberOfReducedResSets() const
386 {
387    return getNumberOfDecimationLevels();
388 }
389 
getImageRectangle(ossim_uint32 resLevel) const390 ossimIrect ossimImageHandler::getImageRectangle(ossim_uint32 resLevel) const
391 {
392    ossimIrect result;
393 
394    if( isOpen() && isValidRLevel(resLevel) )
395    {
396       ossim_int32 lines   = getNumberOfLines(resLevel);
397       ossim_int32 samples = getNumberOfSamples(resLevel);
398       if( !lines || !samples )
399       {
400          result.makeNan();
401       }
402       else
403       {
404          result = ossimIrect(0, 0, samples-1, lines-1);
405       }
406    }
407    else
408    {
409       result.makeNan();
410    }
411 
412    return result;
413 }
414 
getBoundingRect(ossim_uint32 resLevel) const415 ossimIrect ossimImageHandler::getBoundingRect(ossim_uint32 resLevel) const
416 {
417    return getImageRectangle(resLevel);
418 }
419 
420 
getDecimationFactor(ossim_uint32 resLevel,ossimDpt & result) const421 void ossimImageHandler::getDecimationFactor(ossim_uint32 resLevel, ossimDpt& result) const
422 {
423    if (resLevel < theDecimationFactors.size())
424       result = theDecimationFactors[resLevel];
425    else
426       result.makeNan();
427 }
428 
getDecimationFactors(vector<ossimDpt> & decimations) const429 void ossimImageHandler::getDecimationFactors(vector<ossimDpt>& decimations) const
430 {
431    decimations = theDecimationFactors;
432 }
433 
434 //*************************************************************************************************
435 // Method determines the decimation factors at each resolution level. This
436 // base class implementation computes the decimation by considering the ratios in image size
437 // between resolution levels, with fuzzy logic for rounding ratios to the nearest power of 2
438 // if possible. Derived classes need to override this method if the decimations are provided
439 // as part of the image metadata. In some cases (cf. ossimNitfTileSource), the derived class can
440 // set the first R-level (R0) decimation in the case that it is not unity, and then invoke this
441 // base class implementation to compute remaining R-levels, respecting the R0 decimation previously
442 // set by derived class.
443 //*************************************************************************************************
establishDecimationFactors()444 void ossimImageHandler::establishDecimationFactors()
445 {
446    double line_decimation, samp_decimation, decimation, ratio;
447    ossim_uint32 num_lines, num_samps;
448 
449    // The error margin here is effectively the percent error tolerated between ideal number of
450    // pixels for given power-of-2 decimation, and the actual number of pixels found at this
451    // decimation level. Typically, the last level will have fewer pixels than expected, hence the
452    // need for this logic...
453    static const double ERROR_MARGIN = 1.1;  // 10% allowance
454 
455    // NOTE -- Until the end of this method, all decimation values are actually inverse quantities,
456    // i.e., a decimation of 0.5 typical for rlevel 1 is represented here as 2. This facilitates the
457    // fuzzy logic for recognizing powers of 2 (as integers)
458 
459    // Default implementation assumes R0 is not decimated. Check for R0 defined by derived class
460    // however, in case this is not the case:
461    ossimDpt decimation_r0 (1.0, 1.0);
462    if (theDecimationFactors.size() > 0)
463    {
464       decimation_r0.x = 1.0/theDecimationFactors[0].x; // note use of inverse decimation
465       decimation_r0.y = 1.0/theDecimationFactors[0].y;
466    }
467    else
468       theDecimationFactors.push_back(decimation_r0);
469 
470    // Variables used in loop below:
471    ossim_uint32 num_lines_r0 = getNumberOfLines(0);
472    ossim_uint32 num_samps_r0 = getNumberOfSamples(0);
473    ossim_uint32 power_of_2_decimation = (ossim_uint32) decimation_r0.x;
474 
475    // Remaining res levels are computed as a ratio of image size at R0 to image size at Rn:
476    ossim_uint32 nRlevels = getNumberOfDecimationLevels();
477    for(ossim_uint32 res_level = 1; res_level < nRlevels; ++res_level)
478    {
479       num_lines = getNumberOfLines(res_level);
480       num_samps = getNumberOfSamples(res_level);
481 
482       if ((num_lines < 2) || (num_samps < 2))
483          break;
484 
485       line_decimation = decimation_r0.y * num_lines_r0 / (double)num_lines;
486       samp_decimation = decimation_r0.x * num_samps_r0 / (double)num_samps;
487       decimation = line_decimation<samp_decimation ? line_decimation:samp_decimation;
488 
489       // Check for possible error due to inexact ratios.
490       // Loop until reasonable effort was made to establish the corresponding power-of-2 decimation.
491       // If close match is found, the exact integer value is assigned:
492       do
493       {
494          power_of_2_decimation *= 2;
495          ratio = (double)power_of_2_decimation / decimation;
496          if (ratio < 1.0)
497             ratio = 1.0/ratio;
498          if (ratio < ERROR_MARGIN)
499             decimation = (double) power_of_2_decimation;
500 
501       } while ((double) power_of_2_decimation < decimation);
502 
503       // Convert the computed decimation back to fractional form before saving in the factors list:
504       decimation = 1.0/decimation;
505       theDecimationFactors.push_back(ossimDpt(decimation, decimation));
506    }
507 }
508 
buildHistogram(int numberOfRLevels,ossimHistogramMode mode)509 bool ossimImageHandler::buildHistogram( int numberOfRLevels,
510                                         ossimHistogramMode mode )
511 {
512    if(isOpen())
513    {
514       ossimFilename file =
515          getFilenameWithThisExtension(ossimString(".his"));
516 
517       ossimRefPtr<ossimImageHistogramSource> histoSource = new ossimImageHistogramSource;
518       ossimRefPtr<ossimHistogramWriter> writer = new ossimHistogramWriter;
519 
520       if(numberOfRLevels)
521       {
522          histoSource->setMaxNumberOfRLevels(numberOfRLevels);
523       }
524       else
525       {
526          histoSource->setMaxNumberOfRLevels(getNumberOfDecimationLevels());
527       }
528 
529       //---
530       // Note if mode==OSSIM_HISTO_MODE_UNKNOWN the histoSource defaults to
531       // normal mode.
532       //---
533       histoSource->setComputationMode( mode );
534 
535       histoSource->connectMyInputTo(0, this);
536       histoSource->enableSource();
537       writer->connectMyInputTo(0, histoSource.get());
538       writer->setFilename(file);
539       writer->addListener(&theStdOutProgress);
540       writer->execute();
541       histoSource->disconnect();
542       writer->disconnect();
543       histoSource = 0;
544       writer = 0;
545    }
546    else
547    {
548       return false;
549    }
550 
551    return true;
552 }
553 
buildAllHistograms(int numberOfRLevels,ossimHistogramMode mode)554 bool ossimImageHandler::buildAllHistograms( int numberOfRLevels,
555                                             ossimHistogramMode mode )
556 {
557    ossim_uint32 currentEntry = getCurrentEntry();
558    std::vector<ossim_uint32> entryList;
559    getEntryList(entryList);
560    ossim_uint32 idx = 0;
561    for(idx = 0; idx < entryList.size(); ++idx)
562    {
563       setCurrentEntry(entryList[idx]);
564       if(!buildHistogram( numberOfRLevels, mode ))
565       {
566          setCurrentEntry(currentEntry);
567          return false;
568       }
569    }
570 
571    setCurrentEntry(currentEntry);
572    return true;
573 }
574 
buildOverview(ossimImageHandlerOverviewCompressionType compressionType,ossim_uint32 quality,ossimFilterResampler::ossimFilterResamplerType resampleType,bool includeFullResFlag)575 bool ossimImageHandler::buildOverview(ossimImageHandlerOverviewCompressionType compressionType,
576                                       ossim_uint32 quality,
577                                       ossimFilterResampler::ossimFilterResamplerType resampleType,
578                                       bool includeFullResFlag)
579 {
580    ossimFilename file = getFilenameWithThisExtension(ossimString(".ovr"));
581 
582    theOverviewFile = file;
583    if(buildOverview(file, compressionType, quality, resampleType, includeFullResFlag))
584    {
585       openOverview();
586    }
587 
588    return true;
589 }
590 
buildAllOverviews(ossimImageHandlerOverviewCompressionType compressionType,ossim_uint32 quality,ossimFilterResampler::ossimFilterResamplerType resampleType,bool includeFullResFlag)591 bool ossimImageHandler::buildAllOverviews(ossimImageHandlerOverviewCompressionType compressionType,
592                                           ossim_uint32 quality,
593                                           ossimFilterResampler::ossimFilterResamplerType resampleType,
594                                           bool includeFullResFlag)
595 {
596    ossim_uint32 currentEntry = getCurrentEntry();
597    std::vector<ossim_uint32> entryList;
598    getEntryList(entryList);
599    ossim_uint32 idx = 0;
600    for(idx = 0; idx < entryList.size(); ++idx)
601    {
602       setCurrentEntry(entryList[idx]);
603       if(!buildOverview(compressionType, quality, resampleType, includeFullResFlag))
604       {
605          setCurrentEntry(currentEntry);
606          return false;
607       }
608    }
609 
610    setCurrentEntry(currentEntry);
611    return true;
612 }
613 
614 
buildOverview(const ossimFilename & filename,ossimImageHandlerOverviewCompressionType compressionType,ossim_uint32 quality,ossimFilterResampler::ossimFilterResamplerType resampleType,bool includeFullResFlag)615 bool ossimImageHandler::buildOverview(const ossimFilename& filename,
616                                       ossimImageHandlerOverviewCompressionType compressionType,
617                                       ossim_uint32 quality,
618                                       ossimFilterResampler::ossimFilterResamplerType resampleType,
619                                       bool includeFullResFlag)
620 {
621    closeOverview();
622    if(!isOpen())
623    {
624       return false;
625    }
626 
627    theOverviewFile = filename;
628    ossimTiffOverviewBuilder tiffBuilder;
629    if ( tiffBuilder.setInputSource(this) == false )
630    {
631       return false;
632    }
633 
634    ossim_uint16 cType = COMPRESSION_NONE;
635    switch(compressionType)
636    {
637       case OSSIM_OVERVIEW_COMPRESSION_NONE:
638       {
639          cType = COMPRESSION_NONE;
640          break;
641       }
642       case OSSIM_OVERVIEW_COMPRESSION_JPEG:
643       {
644          cType = COMPRESSION_JPEG;
645          break;
646       }
647       case OSSIM_OVERVIEW_COMPRESSION_LZW:
648       {
649          cType = COMPRESSION_LZW;
650          break;
651       }
652       case OSSIM_OVERVIEW_COMPRESSION_DEFLATE:
653       {
654 
655          cType = COMPRESSION_DEFLATE;
656          break;
657       }
658       case OSSIM_OVERVIEW_COMPRESSION_PACKBITS:
659       {
660          cType = COMPRESSION_PACKBITS;
661          break;
662       }
663    }
664    tiffBuilder.setJpegCompressionQuality(quality);
665    tiffBuilder.setCompressionType(cType);
666    tiffBuilder.setResampleType(resampleType);
667    tiffBuilder.buildOverview(filename, includeFullResFlag);
668 
669    return true;
670 }
671 
getImageHistogram() const672 ossimRefPtr<ossimMultiResLevelHistogram> ossimImageHandler::getImageHistogram() const
673 {
674    ossimRefPtr<ossimMultiResLevelHistogram> histogram = 0;
675    if ( isOpen() )
676    {
677       ossimFilename histoFile = getFilenameWithThisExtension(ossimString(".his"));
678       histogram = new ossimMultiResLevelHistogram();
679       if ( histogram->importHistogram(histoFile) == false )
680       {
681          histogram = 0;
682       }
683    }
684    return histogram;
685 }
686 
getImageGeometry()687 ossimRefPtr<ossimImageGeometry> ossimImageHandler::getImageGeometry()
688 {
689    if ( !theGeometry )
690    {
691       //---
692       // Check factory for external geom:
693       //---
694       theGeometry = getExternalImageGeometry();
695 
696       if ( !theGeometry )
697       {
698          //---
699          // WARNING:
700          // Must create/set the geometry at this point or the next call to
701          // ossimImageGeometryRegistry::extendGeometry will put us in an infinite loop
702          // as it does a recursive call back to ossimImageHandler::getImageGeometry().
703          //---
704          theGeometry = new ossimImageGeometry();
705          initImageParameters( theGeometry.get() );
706 
707          //---
708          // And finally allow factories to extend the internal geometry.
709          // This allows plugins for tagged formats with tags not know in the base
710          // to extend the internal geometry.
711          //
712          // Plugins can do handler->getImageGeometry() then modify/extend.
713          //---
714          if(!ossimImageGeometryRegistry::instance()->extendGeometry( this ))
715          {
716             //---
717             // Check for internal, for geotiff, nitf and so on as last resort for getting some
718             // kind of geometry loaded
719             //---
720             theGeometry = getInternalImageGeometry();
721             initImageParameters( theGeometry.get() );
722          }
723       }
724    }
725    return theGeometry;
726 }
727 
getExternalImageGeometry() const728 ossimRefPtr<ossimImageGeometry> ossimImageHandler::getExternalImageGeometry() const
729 {
730    ossimRefPtr<ossimImageGeometry> geom = 0;
731    // No geometry object has been set up yet. Check for external geometry file.
732    // Try "foo.geom" if image is "foo.tif":
733    ossimFilename filename;
734    getFilenameWithThisExt( ossimString(".geom"), filename );
735 
736    if(!filename.exists())
737    {
738       // Try "foo_e0.tif" if image is "foo.tif" where "e0" is entry index.
739       filename = getFilenameWithThisExtension(ossimString(".geom"), true);
740    }
741 
742 #if 0
743 /* getgetFilenameWithThisExt... methods tack on sup dir if set. drb */
744    if(!filename.exists())
745    {
746       // Try supplementary data directory for remote geometry:
747       filename = getFilenameWithThisExtension(ossimString(".geom"), false);
748       filename = theSupplementaryDirectory.dirCat(filename.file());
749    }
750    if(!filename.exists())
751    {
752       // Try supplementary data directory for remote geometry with entry index:
753       filename = getFilenameWithThisExtension(ossimString(".geom"), true);
754       filename = theSupplementaryDirectory.dirCat(filename.file());
755    }
756 #endif
757 
758    if(filename.exists())
759    {
760       // Open the geom file as a KWL and initialize our geometry object:
761       filename = filename.expand();
762       ossimKeywordlist geomKwl(filename);
763 
764       // Try loadState with no prefix.
765       std::string prefix = "";
766       std::string key = ossimKeywordNames::TYPE_KW;
767       std::string value = geomKwl.findKey(prefix, key);
768 
769       if ( value.empty() || (value != "ossimImageGeometry") )
770       {
771          // Try with "image0." type prefix.
772          prefix += std::string("image") + ossimString::toString(getCurrentEntry()).string() +
773             std::string(".");
774          value = geomKwl.findKey(prefix, key);
775 
776          if ( value.empty() || (value != "ossimImageGeometry") )
777          {
778             // Try with "image0.geometry." prefix.
779             prefix += std::string( "geometry." );
780             value = geomKwl.findKey(prefix, key);
781 
782             if ( value.empty() || (value != "ossimImageGeometry") )
783             {
784                // Try with "geometry." prefix.
785                prefix = std::string( "geometry." );
786                value = geomKwl.findKey(prefix, key);
787             }
788          }
789       }
790 
791       if ( value == "ossimImageGeometry" )
792       {
793          geom = new ossimImageGeometry;
794          if( !geom->loadState(geomKwl, prefix.c_str()) )
795          {
796             geom = 0;
797          }
798       }
799    }
800 
801    return geom;
802 }
803 
getInternalImageGeometry() const804 ossimRefPtr<ossimImageGeometry> ossimImageHandler::getInternalImageGeometry() const
805 {
806    // Default, derived classes should override.
807    ossimRefPtr<ossimImageGeometry> geom = new ossimImageGeometry();
808    return geom;
809 }
810 
setImageGeometry(ossimImageGeometry * geom)811 void ossimImageHandler::setImageGeometry( ossimImageGeometry* geom)
812 {
813    theGeometry = geom;
814 }
815 
saveImageGeometry() const816 void ossimImageHandler::saveImageGeometry() const
817 {
818    ossimFilename geometryFile = getFilenameWithThisExtension(ossimString(".geom"));
819    saveImageGeometry(geometryFile);
820 }
821 
saveImageGeometry(const ossimFilename & geometry_file) const822 void ossimImageHandler::saveImageGeometry(const ossimFilename& geometry_file) const
823 {
824    if (theGeometry.valid())
825    {
826       ossimKeywordlist kwl;
827       theGeometry->saveState(kwl);
828       kwl.write(geometry_file.chars());
829    }
830 }
831 
closeOverview()832 void ossimImageHandler::closeOverview()
833 {
834    theOverview = 0;
835 }
836 
getOverview() const837 const ossimImageHandler* ossimImageHandler::getOverview() const
838 {
839    return theOverview.get();
840 }
841 
hasOverviews() const842 bool ossimImageHandler::hasOverviews() const
843 {
844    return (getNumberOfDecimationLevels() > 1);
845 }
846 
openOverview(const ossimFilename & overview_file)847 bool ossimImageHandler::openOverview(const ossimFilename& overview_file)
848 {
849    bool result = false;
850    if (traceDebug())
851    {
852       ossimNotify(ossimNotifyLevel_DEBUG)
853          << "ossimImageHandler::openOverview(overview_file): ...entered!";
854    }
855    closeOverview();
856 
857    if (overview_file != theImageFile) // Make sure we don't open ourselves.
858    {
859       //---
860       // Get the number of level before the call to opening the overview so
861       // the overview can be told what it's starting res level is.
862       //---
863       ossim_uint32 overviewStartingResLevel = getNumberOfDecimationLevels();
864 
865 
866       // Try to open:
867       theOverview = ossimImageHandlerRegistry::instance()->openOverview( overview_file );
868       if (theOverview.valid())
869       {
870          result = true;
871 
872          //---
873          // Set the owner in case the overview reader needs to get something
874          // from the it like min/max/null.
875          //---
876          theOverview->changeOwner(this);
877 
878          // Set the starting res level of the overview.
879          theOverview->setStartingResLevel(overviewStartingResLevel);
880 
881          // Capture the file name.
882          theOverviewFile = overview_file;
883 
884          //---
885          // Some overview handlers cannot store what the null is.  Like dted
886          // null is -32767 not default -32768 so this allows passing this to the
887          // overview reader provided it overrides setMin/Max/NullPixel value
888          // methods. (drb)
889          //---
890          const ossim_uint32 BANDS = getNumberOfOutputBands();
891          for (ossim_uint32 band = 0; band < BANDS; ++band)
892          {
893             theOverview->setMinPixelValue(band, getMinPixelValue(band));
894             theOverview->setMaxPixelValue(band, getMaxPixelValue(band));
895             theOverview->setNullPixelValue(band, getNullPixelValue(band));
896          }
897          if(m_state)
898          {
899             m_state->setOverviewState(theOverview->getState());
900          }
901          if (traceDebug())
902          {
903             ossimNotify(ossimNotifyLevel_DEBUG)
904                << "overview starting res level: " << overviewStartingResLevel
905                << "\noverview levels: "
906                << theOverview->getNumberOfDecimationLevels()
907                << "\nlevels: " << getNumberOfDecimationLevels()
908                << endl;
909          }
910 
911          //---
912          // This is not really a container event; however, using for now.
913          //---
914          ossimContainerEvent event(this,
915                                    OSSIM_EVENT_ADD_OBJECT_ID);
916          event.setObjectList(theOverview.get());
917          fireEvent(event);
918       }
919    }
920    if (traceDebug())
921    {
922       ossimNotify(ossimNotifyLevel_DEBUG)
923          << "ossimImageHandler::openOverview(overview_file): ...leaving!";
924    }
925 
926    return result;
927 }
928 
openOverview()929 bool ossimImageHandler::openOverview()
930 {
931    static const char MODULE[] = "ossimImageHandler::openOverview()";
932    if (traceDebug())
933    {
934       ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
935    }
936 
937    bool result = false;
938 
939    closeOverview();
940 
941    if(m_state)
942    {
943       // check if we have an overview state
944       std::shared_ptr<ossim::ImageHandlerState> overviewState = m_state->getOverviewState();
945       if(overviewState)
946       {
947          // check to see if the overvies state was cached
948          // to mark has checked but no overview
949          if(overviewState->getConnectionString().empty())
950          {
951             return false;
952          }
953          ossim_uint32 overviewStartingResLevel = getNumberOfDecimationLevels();
954          theOverview = ossimImageHandlerRegistry::instance()->open( overviewState );
955          if(theOverview)
956          {
957             result = true;
958             //---
959             // Set the owner in case the overview reader needs to get something
960             // from the it like min/max/null.
961             //---
962             theOverview->changeOwner(this);
963 
964             // Set the starting res level of the overview.
965             theOverview->setStartingResLevel(overviewStartingResLevel);
966 
967             // Capture the file name.
968             theOverviewFile = overviewState->getConnectionString();
969 
970             //---
971             // Some overview handlers cannot store what the null is.  Like dted
972             // null is -32767 not default -32768 so this allows passing this to the
973             // overview reader provided it overrides setMin/Max/NullPixel value
974             // methods. (drb)
975             //---
976             const ossim_uint32 BANDS = getNumberOfOutputBands();
977             for (ossim_uint32 band = 0; band < BANDS; ++band)
978             {
979                theOverview->setMinPixelValue(band, getMinPixelValue(band));
980                theOverview->setMaxPixelValue(band, getMaxPixelValue(band));
981                theOverview->setNullPixelValue(band, getNullPixelValue(band));
982             }
983             if (traceDebug())
984             {
985                ossimNotify(ossimNotifyLevel_DEBUG)
986                   << "overview starting res level: " << overviewStartingResLevel
987                   << "\noverview levels: "
988                   << theOverview->getNumberOfDecimationLevels()
989                   << "\nlevels: " << getNumberOfDecimationLevels()
990                   << endl;
991             }
992 
993             //---
994             // This is not really a container event; however, using for now.
995             //---
996             ossimContainerEvent event(this,
997                                       OSSIM_EVENT_ADD_OBJECT_ID);
998             event.setObjectList(theOverview.get());
999             fireEvent(event);
1000             return result;
1001          }
1002       }
1003    }
1004    // 1) ESH 03/2009 -- Use the overview file set e.g. using a .spec file.
1005    ossimFilename overviewFilename = getOverviewFile();
1006 
1007    // ossimFilename::exists() currently does not work with s3 url's.
1008    if ( overviewFilename.empty() ) // || (overviewFilename.exists() == false) )
1009    {
1010       // 2) Generate the name from image name.
1011       overviewFilename = createDefaultOverviewFilename();
1012    }
1013 
1014    // ossimFilename::exists() currently does not work with s3 url's.
1015    if ( overviewFilename.size() )
1016    {
1017       result = openOverview( overviewFilename );
1018 
1019       if (traceDebug())
1020       {
1021          ossimNotify(ossimNotifyLevel_DEBUG)
1022             << (result?"Opened ":"Could not open ") << "overview: " << overviewFilename
1023             << "\n";
1024       }
1025    }
1026    if ( !result )
1027    {
1028       if (overviewFilename.empty() || (overviewFilename.exists() == false) )
1029       {
1030          // 3) For backward compatibility check if single entry and _e0.ovr
1031          overviewFilename = getFilenameWithThisExtension(ossimString(".ovr"), true);
1032 
1033          if (overviewFilename.empty() || (overviewFilename.exists() == false) )
1034          {
1035             //---
1036             // 4) For overviews built with gdal.
1037             // Examples:
1038             // Single entry: foo.tif.ovr
1039             // Multi-entry: foo.tif.x.ovr where "x" == one based entry number.
1040             //
1041             // Note: Take into account a supplementary dir if any.
1042             //---
1043             if ( theSupplementaryDirectory.empty() )
1044             {
1045                overviewFilename = getFilename();
1046             }
1047             else
1048             {
1049                overviewFilename = theSupplementaryDirectory;
1050                overviewFilename = overviewFilename.dirCat( getFilename().file() );
1051 
1052             }
1053 
1054             if ( getNumberOfEntries() > 1 )
1055             {
1056                overviewFilename += ".";
1057                // Sample multi-entry data "one" based; hence, the + 1.
1058                overviewFilename += ossimString::toString( getCurrentEntry()+1 );
1059             }
1060             overviewFilename += ".ovr";
1061          }
1062       }
1063 
1064       if ( overviewFilename.exists() )
1065       {
1066          result = openOverview( overviewFilename );
1067 
1068          if (traceDebug())
1069          {
1070             ossimNotify(ossimNotifyLevel_DEBUG)
1071                << (result?"Opened ":"Could not open ") << "overview: " << overviewFilename
1072                << "\n";
1073          }
1074       }
1075    }
1076 
1077    if (traceDebug())
1078    {
1079       ossimNotify(ossimNotifyLevel_DEBUG)
1080          << MODULE << " exit result: " << (result?"true":"false") << "\n";
1081    }
1082 
1083    return result;
1084 }
1085 
1086 
writeValidImageVertices(const std::vector<ossimIpt> & vertices,const ossimFilename & file)1087 bool ossimImageHandler::writeValidImageVertices(const std::vector<ossimIpt>& vertices, const ossimFilename& file)
1088 {
1089    ossimFilename tempFile = file;
1090    if(tempFile == "")
1091    {
1092       tempFile = createDefaultValidVerticesFilename();
1093    }
1094    ossim_uint32 i = 0;
1095    ossimKeywordlist tempKwl;
1096    ossimPolygon poly(vertices);
1097 
1098    poly.checkOrdering();
1099 
1100    // Capture the vertices.
1101    theValidImageVertices = vertices;
1102 
1103    if(poly.getOrdering() == OSSIM_COUNTERCLOCKWISE_ORDER)
1104    {
1105       std::reverse(theValidImageVertices.begin(), theValidImageVertices.end());
1106    }
1107 
1108    if(theValidImageVertices.size())
1109    {
1110       for(i = 0; i < theValidImageVertices.size(); ++i)
1111       {
1112          ossimString prefix = ossimString("point") + ossimString::toString(i) + ".";
1113          tempKwl.add(prefix.c_str(),
1114                      "x",
1115                      theValidImageVertices[i].x,
1116                      true);
1117 	      tempKwl.add(prefix.c_str(),
1118                      "y",
1119                      theValidImageVertices[i].y,
1120                      true);
1121       }
1122 
1123       tempKwl.write(tempFile.c_str());
1124    }
1125 
1126    if ( tempFile.exists() )
1127    {
1128       return true;
1129    }
1130 
1131    return false; // Write of file failed.
1132 }
1133 
openValidVertices(const ossimFilename & vertices_file)1134 bool ossimImageHandler::openValidVertices(const ossimFilename& vertices_file)
1135 {
1136    return initVertices(vertices_file);
1137 }
1138 
openValidVertices()1139 bool ossimImageHandler::openValidVertices()
1140 {
1141    ossimFilename vertices_file;
1142    vertices_file = theImageFile.path();
1143    vertices_file = vertices_file.dirCat(theImageFile.fileNoExtension());
1144    if(getNumberOfEntries() > 1)
1145    {
1146       vertices_file += ossimString("_vertices") + "_e" + ossimString::toString(getCurrentEntry()) + ".kwl";
1147    }
1148    else
1149    {
1150       vertices_file += "_vertices.kwl";
1151    }
1152 
1153    if (traceDebug())
1154    {
1155       ossimNotify(ossimNotifyLevel_DEBUG)
1156          << "Looking for " << vertices_file
1157          << " vertices file..." << std::endl;
1158    }
1159 
1160    return openValidVertices(vertices_file);
1161 }
1162 
open(const ossimFilename & imageFile)1163 bool ossimImageHandler::open(const ossimFilename& imageFile)
1164 {
1165    if(isOpen())
1166    {
1167       close();
1168    }
1169 
1170    setFilename(imageFile);
1171 
1172    return open();
1173 }
1174 
open(const ossimFilename & imageFile,ossim_uint32 entryIndex)1175 bool ossimImageHandler::open(const ossimFilename& imageFile,
1176                              ossim_uint32 entryIndex)
1177 {
1178    if(isOpen())
1179    {
1180       close();
1181    }
1182    setFilename(imageFile);
1183 
1184    bool result = open();
1185 
1186    if(result)
1187    {
1188       return setCurrentEntry(entryIndex);
1189    }
1190 
1191    return result;
1192 }
1193 
open(std::shared_ptr<ossim::ImageHandlerState> state)1194 bool ossimImageHandler::open(std::shared_ptr<ossim::ImageHandlerState> state)
1195 {
1196    bool result = false;
1197    if(isOpen())
1198    {
1199       close();
1200    }
1201    setFilename(state->getConnectionString());
1202    setState(state);
1203    result = open();
1204 
1205    return result;
1206 }
1207 
1208 
isValidRLevel(ossim_uint32 resLevel) const1209 bool ossimImageHandler::isValidRLevel(ossim_uint32 resLevel) const
1210 {
1211    bool result = false;
1212 
1213    const ossim_uint32 LEVELS = getNumberOfDecimationLevels();
1214 
1215    if ( !theStartingResLevel) // Not an overview.
1216    {
1217       result = (resLevel < LEVELS);
1218    }
1219    else  // Used as overview.
1220    {
1221       if (resLevel >= theStartingResLevel)
1222       {
1223          //---
1224          // Adjust the res level to be zero based for this overview before
1225          // checking.
1226          //---
1227          result = ( (resLevel - theStartingResLevel) < LEVELS);
1228       }
1229    }
1230 
1231    return result;
1232 }
1233 
getValidImageVertices(vector<ossimIpt> & validVertices,ossimVertexOrdering ordering,ossim_uint32 resLevel) const1234 void ossimImageHandler::getValidImageVertices(vector<ossimIpt>& validVertices,
1235                                               ossimVertexOrdering ordering,
1236                                               ossim_uint32 resLevel) const
1237 {
1238    ossimDpt decimation;
1239    getDecimationFactor(resLevel, decimation);
1240    if(decimation.hasNans())
1241    {
1242       return;
1243    }
1244    if (theValidImageVertices.size() != 0)
1245    {
1246       validVertices.clear();
1247       for (ossim_uint32 i=0; i<theValidImageVertices.size(); ++i)
1248       {
1249          ossimIpt pt(ossim::round<int>(theValidImageVertices[i].x*decimation.x),
1250                      ossim::round<int>(theValidImageVertices[i].y*decimation.y));
1251          validVertices.push_back(pt);
1252       }
1253 
1254       if(ordering == OSSIM_COUNTERCLOCKWISE_ORDER)
1255       {
1256          std::reverse(validVertices.begin()+1, validVertices.end());
1257       }
1258    }
1259    else
1260    {
1261       // Call the base class method which will set to bounding rectangle.
1262       ossimImageSource::getValidImageVertices(validVertices, ordering, resLevel);
1263    }
1264 }
1265 
close()1266 void ossimImageHandler::close()
1267 {
1268    theOverview = 0;
1269    theGeometry = 0;
1270    theValidImageVertices.clear();
1271    theDecimationFactors.clear();
1272    setState(0);
1273 }
1274 
isBandSelector() const1275 bool ossimImageHandler::isBandSelector() const
1276 {
1277    return false;
1278 }
1279 
setOutputBandList(const std::vector<ossim_uint32> &)1280 bool ossimImageHandler::setOutputBandList(const std::vector<ossim_uint32>& /* band_list */)
1281 {
1282    return false;
1283 }
1284 
getRgbBandList(std::vector<ossim_uint32> & bandList) const1285 bool ossimImageHandler::getRgbBandList( std::vector<ossim_uint32>& bandList ) const
1286 {
1287    // Looks for "rgb_bands" key in dot omd file.  E.g. "rgb_bands: (2,1,0)"
1288    return theMetaData.getRgbBands( bandList );
1289 }
1290 
setOutputToInputBandList()1291 bool ossimImageHandler::setOutputToInputBandList()
1292 {
1293    bool result = false;
1294    if ( isBandSelector() )
1295    {
1296       std::vector<ossim_uint32> bandList;
1297       ossimImageSource::getOutputBandList( bandList );
1298       result = setOutputBandList( bandList );
1299    }
1300    return result;
1301 }
1302 
isIdentityBandList(const std::vector<ossim_uint32> & bandList) const1303 bool ossimImageHandler::isIdentityBandList( const std::vector<ossim_uint32>& bandList ) const
1304 {
1305    bool result = false;
1306    const ossim_uint32 BANDS = (ossim_uint32)bandList.size();
1307    if ( BANDS )
1308    {
1309       std::vector<ossim_uint32> inputList;
1310       ossimImageSource::getOutputBandList( inputList ); // This populates an identity band list.
1311 
1312       if ( inputList.size() == BANDS )
1313       {
1314          ossim_uint32 band = 0;
1315          while ( band < BANDS )
1316          {
1317             if ( inputList[band] != bandList[band] )
1318             {
1319                break;
1320             }
1321             ++band;
1322          }
1323          if ( band == BANDS )
1324          {
1325             result = true;
1326          }
1327       }
1328    }
1329    return result;
1330 }
1331 
1332 // Protected convenience method:
setOutputBandList(const std::vector<ossim_uint32> & inBandList,std::vector<ossim_uint32> & outBandList)1333 bool ossimImageHandler::setOutputBandList(const std::vector<ossim_uint32>& inBandList,
1334                                           std::vector<ossim_uint32>& outBandList)
1335 {
1336    bool result = false;
1337 
1338    const ossim_uint32 INPUT_BANDS  = getNumberOfInputBands();
1339    const ossim_uint32 OUTPUT_BANDS = (ossim_uint32)inBandList.size();
1340 
1341    if ( INPUT_BANDS && OUTPUT_BANDS )
1342    {
1343       result = true;
1344       outBandList.resize( OUTPUT_BANDS );
1345       for ( ossim_uint32 band = 0; band < OUTPUT_BANDS; ++band )
1346       {
1347          if ( inBandList[band] < INPUT_BANDS )
1348          {
1349             outBandList[band] = inBandList[band];
1350          }
1351          else // Out of range...
1352          {
1353             result = false;
1354             break;
1355          }
1356       }
1357       if ( result && theOverview.valid() )
1358       {
1359          result = theOverview->setOutputBandList( inBandList );
1360       }
1361    }
1362 
1363    if ( result == false )
1364    {
1365       ossimImageSource::getOutputBandList( outBandList ); // Set to identity.
1366    }
1367 
1368    return result;
1369 }
1370 
isImageTiled() const1371 bool ossimImageHandler::isImageTiled() const
1372 {
1373    return (getImageTileWidth() && getImageTileHeight());
1374 }
1375 
loadMetaData()1376 void ossimImageHandler::loadMetaData()
1377 {
1378 
1379    if(m_state&&m_state->getMetaData())
1380    {
1381       theMetaData = *m_state->getMetaData();
1382    }
1383    else
1384    {
1385       ossimFilename filename = getFilenameWithThisExtension(ossimString(".omd"), false);
1386       theMetaData.clear();
1387 
1388       std::shared_ptr<ossim::istream> instream = ossim::StreamFactoryRegistry::instance()->createIstream(filename.c_str());
1389 
1390       if(!instream)
1391       {
1392          filename = getFilenameWithThisExtension(ossimString(".omd"), true);
1393          instream = ossim::StreamFactoryRegistry::instance()->createIstream(filename.c_str());
1394       }
1395 
1396       if(instream)
1397       {
1398         ossimKeywordlist kwl;
1399 
1400         kwl.parseStream(*instream);
1401 
1402         theMetaData.loadState(kwl);
1403       }
1404       else
1405       {
1406         theMetaData.setScalarType(getOutputScalarType());
1407       }
1408       if(m_state)
1409       {
1410          m_state->setMetaData(std::make_shared<ossimImageMetaData>(theMetaData));
1411       }
1412 
1413    }
1414 
1415 }
1416 
getMinPixelValue(ossim_uint32 band) const1417 double ossimImageHandler::getMinPixelValue(ossim_uint32 band)const
1418 {
1419    if(theMetaData.getNumberOfBands())
1420    {
1421       return theMetaData.getMinPix(band);
1422    }
1423    return ossim::defaultMin(getOutputScalarType());
1424 }
1425 
getMaxPixelValue(ossim_uint32 band) const1426 double ossimImageHandler::getMaxPixelValue(ossim_uint32 band)const
1427 {
1428    if(theMetaData.getNumberOfBands())
1429    {
1430       return theMetaData.getMaxPix(band);
1431    }
1432    return ossim::defaultMax(getOutputScalarType());
1433 }
1434 
getNullPixelValue(ossim_uint32 band) const1435 double ossimImageHandler::getNullPixelValue(ossim_uint32 band)const
1436 {
1437    if(theMetaData.getNumberOfBands())
1438    {
1439       return theMetaData.getNullPix(band);
1440    }
1441 
1442    return ossim::defaultNull(getOutputScalarType());
1443 }
1444 
setMinPixelValue(ossim_uint32 band,const ossim_float64 & pix)1445 void ossimImageHandler::setMinPixelValue(ossim_uint32 band,
1446                                          const ossim_float64& pix)
1447 {
1448    theMetaData.setMinPix(band, pix);
1449 }
1450 
setMaxPixelValue(ossim_uint32 band,const ossim_float64 & pix)1451 void ossimImageHandler::setMaxPixelValue(ossim_uint32 band,
1452                                          const ossim_float64& pix)
1453 {
1454    theMetaData.setMaxPix(band, pix);
1455 }
1456 
setNullPixelValue(ossim_uint32 band,const ossim_float64 & pix)1457 void ossimImageHandler::setNullPixelValue(ossim_uint32 band,
1458                                           const ossim_float64& pix)
1459 {
1460    theMetaData.setNullPix(band, pix);
1461 }
1462 
getCurrentEntry() const1463 ossim_uint32 ossimImageHandler::getCurrentEntry()const
1464 {
1465    return 0;
1466 }
1467 
setCurrentEntry(ossim_uint32 entryIdx)1468 bool ossimImageHandler::setCurrentEntry(ossim_uint32  entryIdx )
1469 {
1470    return true;
1471 }
1472 
getOverviewFile() const1473 ossimFilename ossimImageHandler::getOverviewFile()const
1474 {
1475    return theOverviewFile;
1476 }
1477 
getEntryList(std::vector<ossim_uint32> & entryList) const1478 void ossimImageHandler::getEntryList(std::vector<ossim_uint32>& entryList)const
1479 {
1480    entryList.push_back(0);
1481 }
1482 
useEntryIndex() const1483 bool ossimImageHandler::useEntryIndex() const
1484 {
1485    bool result = false;
1486    if ( isOpen() )
1487    {
1488       std::vector<ossim_uint32> entryList;
1489       getEntryList(entryList);
1490 
1491       if ( entryList.size() )
1492       {
1493          if ( (entryList.size() > 1) || (entryList[0] != 0) ) result = true;
1494       }
1495    }
1496    return result;
1497 }
1498 
getNumberOfEntries() const1499 ossim_uint32 ossimImageHandler::getNumberOfEntries()const
1500 {
1501    std::vector<ossim_uint32> tempList;
1502    getEntryList(tempList);
1503 
1504    return (ossim_uint32)tempList.size();
1505 }
1506 
getEntryNames(std::vector<ossimString> & entryStringList) const1507 void ossimImageHandler::getEntryNames(std::vector<ossimString>& entryStringList) const
1508 {
1509    entryStringList.clear();
1510 }
1511 
getEntryName(ossim_uint32 entryIdx,std::string & name) const1512 void ossimImageHandler::getEntryName( ossim_uint32 entryIdx, std::string& name ) const
1513 {
1514    name = "";
1515    std::vector<ossimString> entryNames;
1516    getEntryNames(entryNames);
1517    if (entryIdx < entryNames.size())
1518       name = entryNames[entryIdx].string();
1519 }
1520 
completeOpen()1521 void ossimImageHandler::completeOpen()
1522 {
1523    if(traceDebug())
1524    {
1525       ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageHandler::completeOpen(): Entered........" << std::endl;
1526    }
1527    loadMetaData();
1528    if ( theOpenOverviewFlag )
1529    {
1530       openOverview();
1531    }
1532    establishDecimationFactors();
1533    if(traceDebug())
1534    {
1535       ossimNotify(ossimNotifyLevel_DEBUG) << "ossimImageHandler::completeOpen(): Leaving......." << std::endl;
1536    }
1537    openValidVertices();
1538 }
1539 
canConnectMyInputTo(ossim_int32,const ossimConnectableObject *) const1540 bool ossimImageHandler::canConnectMyInputTo(ossim_int32 /* inputIndex */,
1541                                             const ossimConnectableObject* /* object */)const
1542 {
1543    return false;
1544 }
1545 
hasMetaData() const1546 bool ossimImageHandler::hasMetaData()const
1547 {
1548    return theMetaData.isValid();
1549 }
1550 
setFilename(const ossimFilename & filename)1551 void ossimImageHandler::setFilename(const ossimFilename& filename)
1552 {
1553    theImageFile = filename;
1554 }
1555 
getFilename() const1556 const ossimFilename& ossimImageHandler::getFilename()const
1557 {
1558    return theImageFile;
1559 }
1560 
setSupplementaryDirectory(const ossimFilename & dir)1561 void ossimImageHandler::setSupplementaryDirectory(const ossimFilename& dir)
1562 {
1563    if (dir.isDir())
1564       theSupplementaryDirectory = dir;
1565    else
1566       theSupplementaryDirectory = dir.path();
1567    // A change in supplementary directory presents an opportunity to find the OVR that could not be
1568    // opened previously, as well as other support data items:
1569    if (!theOverview.valid())
1570    {
1571       if (theDecimationFactors.size() > 0)
1572       {
1573         theDecimationFactors.clear();
1574       }
1575       completeOpen();
1576    }
1577 }
1578 
getSupplementaryDirectory() const1579 const ossimFilename& ossimImageHandler::getSupplementaryDirectory()const
1580 {
1581    return theSupplementaryDirectory;
1582 }
1583 
setProperty(ossimRefPtr<ossimProperty> property)1584 void ossimImageHandler::setProperty(ossimRefPtr<ossimProperty> property)
1585 {
1586    if ( property.valid() )
1587    {
1588       if(property->getName() == ossimKeywordNames::ENTRY_KW)
1589       {
1590          setCurrentEntry(property->valueToString().toUInt32());
1591       }
1592       else if ( property->getName() == OPEN_OVERVIEW_FLAG_KW )
1593       {
1594          setOpenOverviewFlag( property->valueToString().toBool() );
1595       }
1596       else
1597       {
1598          ossimImageSource::setProperty(property);
1599       }
1600    }
1601 }
1602 
getProperty(const ossimString & name) const1603 ossimRefPtr<ossimProperty> ossimImageHandler::getProperty(const ossimString& name)const
1604 {
1605 
1606    if(name == ossimKeywordNames::ENTRY_KW)
1607    {
1608       std::vector<ossim_uint32> entryList;
1609       getEntryList(entryList);
1610 
1611       ossimStringProperty* stringProperty = new ossimStringProperty(name,
1612                                                                     ossimString::toString(getCurrentEntry()));
1613       ossim_uint32 idx = 0;
1614       for(idx = 0; idx < entryList.size(); ++idx)
1615       {
1616          stringProperty->addConstraint(ossimString::toString(entryList[idx]));
1617       }
1618       stringProperty->setFullRefreshBit();
1619       stringProperty->setEditableFlag(false);
1620 
1621       return stringProperty;
1622    }
1623    else if(name == ossimKeywordNames::NUMBER_SAMPLES_KW)
1624    {
1625       ossimNumericProperty* prop = new ossimNumericProperty(name, ossimString::toString(getNumberOfSamples()));
1626       prop->setReadOnlyFlag(true);
1627 
1628       return prop;
1629    }
1630    else if(name == ossimKeywordNames::NUMBER_LINES_KW)
1631    {
1632       ossimNumericProperty* prop = new ossimNumericProperty(name, ossimString::toString(getNumberOfLines()));
1633       prop->setReadOnlyFlag(true);
1634 
1635       return prop;
1636    }
1637    else if(name == ossimKeywordNames::NUMBER_BANDS_KW)
1638    {
1639       ossimNumericProperty* prop = new ossimNumericProperty(name, ossimString::toString(getNumberOfInputBands()));
1640       prop->setReadOnlyFlag(true);
1641 
1642       return prop;
1643    }
1644    else if(name == ossimKeywordNames::NUMBER_REDUCED_RES_SETS_KW)
1645    {
1646       ossimNumericProperty* prop = new ossimNumericProperty(name, ossimString::toString(getNumberOfDecimationLevels()));
1647       prop->setReadOnlyFlag(true);
1648 
1649       return prop;
1650    }
1651    else if(name == ossimKeywordNames::SCALAR_TYPE_KW)
1652    {
1653       ossimStringProperty* prop = new ossimStringProperty(name, ossimScalarTypeLut::instance()->getEntryString(getOutputScalarType()));
1654       prop->setReadOnlyFlag(true);
1655 
1656       return prop;
1657    }
1658    else if(name == "histogram_filename")
1659    {
1660       ossimFilenameProperty* filenameProp =
1661          new ossimFilenameProperty(name, createDefaultHistogramFilename());
1662 
1663       filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT);
1664       filenameProp->setCacheRefreshBit();
1665 
1666       return filenameProp;
1667 
1668    }
1669    else if(name == "geometry_filename")
1670    {
1671       ossimFilenameProperty* filenameProp =
1672          new ossimFilenameProperty(name, createDefaultGeometryFilename());
1673 
1674       filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT);
1675       filenameProp->setCacheRefreshBit();
1676 
1677       return filenameProp;
1678 
1679    }
1680    else if(name == "valid_vertices_filename")
1681    {
1682       ossimFilenameProperty* filenameProp =
1683          new ossimFilenameProperty(name, createDefaultValidVerticesFilename());
1684 
1685       filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT);
1686       filenameProp->setCacheRefreshBit();
1687 
1688       return filenameProp;
1689    }
1690    else if(name == "metadata_filename")
1691    {
1692       ossimFilenameProperty* filenameProp =
1693          new ossimFilenameProperty(name, createDefaultMetadataFilename());
1694 
1695       filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT);
1696       filenameProp->setCacheRefreshBit();
1697 
1698       return filenameProp;
1699    }
1700    else if(name == "overview_filename")
1701    {
1702       ossimFilenameProperty* filenameProp =
1703          new ossimFilenameProperty(name, createDefaultOverviewFilename());
1704 
1705       filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT);
1706       filenameProp->setCacheRefreshBit();
1707 
1708       return filenameProp;
1709    }
1710    else if(name == "filename")
1711    {
1712       ossimFilenameProperty* filenameProp =
1713          new ossimFilenameProperty(name, getFilename());
1714 
1715       filenameProp->setIoType(ossimFilenameProperty::ossimFilenamePropertyIoType_INPUT);
1716       filenameProp->setFullRefreshBit();
1717 
1718       return filenameProp;
1719    }
1720    else if ( name == OPEN_OVERVIEW_FLAG_KW)
1721    {
1722       ossimRefPtr<ossimProperty> result =
1723          new ossimBooleanProperty(ossimString(OPEN_OVERVIEW_FLAG_KW), theOpenOverviewFlag);
1724       return result;
1725    }
1726 
1727    return ossimImageSource::getProperty(name);
1728 }
1729 
getPropertyNames(std::vector<ossimString> & propertyNames) const1730 void ossimImageHandler::getPropertyNames(std::vector<ossimString>& propertyNames)const
1731 {
1732    ossimImageSource::getPropertyNames(propertyNames);
1733    propertyNames.push_back(ossimKeywordNames::ENTRY_KW);
1734    propertyNames.push_back(ossimKeywordNames::NUMBER_SAMPLES_KW);
1735    propertyNames.push_back(ossimKeywordNames::NUMBER_LINES_KW);
1736    propertyNames.push_back(ossimKeywordNames::NUMBER_BANDS_KW);
1737    propertyNames.push_back(ossimKeywordNames::NUMBER_REDUCED_RES_SETS_KW);
1738    propertyNames.push_back(ossimKeywordNames::SCALAR_TYPE_KW);
1739    propertyNames.push_back(OPEN_OVERVIEW_FLAG_KW);
1740 }
1741 
getFilenameWithThisExtension(const ossimString & ext,bool set_e0_prefix) const1742 ossimFilename ossimImageHandler::getFilenameWithThisExtension(
1743    const ossimString& ext,
1744    bool set_e0_prefix) const
1745 {
1746    // Get the image file.
1747    ossimFilename f = getFilename();
1748 
1749    getFilenameWithNoExtension( f );
1750 
1751    if (set_e0_prefix || (getNumberOfEntries() > 1))
1752    {
1753       f += "_e";
1754       f += ossimString::toString(getCurrentEntry());
1755    }
1756 
1757    if (ext.size())
1758    {
1759       if (ext.string()[0] != '.')
1760       {
1761          f += ".";
1762       }
1763       f += ext;
1764    }
1765    return f;
1766 }
1767 
getFilenameWithThisExt(const ossimString & ext,ossimFilename & f) const1768 void ossimImageHandler::getFilenameWithThisExt( const ossimString& ext,
1769                                                 ossimFilename& f ) const
1770 {
1771    // Get the image file.
1772    f = getFilename();
1773 
1774    getFilenameWithNoExtension( f );
1775 
1776    if (ext.size())
1777    {
1778       if (ext.string()[0] != '.')
1779       {
1780          f += ".";
1781       }
1782       f += ext;
1783    }
1784 }
1785 
getFilenameWithNoExtension(ossimFilename & f) const1786 void ossimImageHandler::getFilenameWithNoExtension( ossimFilename& f ) const
1787 {
1788    //---
1789    // If the supplementary directory is set, find the extension at that
1790    // location instead of at the default.
1791    //---
1792    if ( theSupplementaryDirectory.size() )
1793    {
1794       ossimString drivePart;
1795       ossimString pathPart;
1796       ossimString filePart;
1797       ossimString extPart;
1798 
1799       f.split(drivePart,
1800               pathPart,
1801               filePart,
1802               extPart);
1803 
1804       ossimFilename newDrivePart = theSupplementaryDirectory.drive();
1805       ossimFilename newPathPart  = theSupplementaryDirectory.after(newDrivePart);
1806 
1807       f.merge( newDrivePart, newPathPart, filePart, extPart );
1808    }
1809 
1810    // Wipe out the extension.
1811    f.setExtension("");
1812 }
1813 
getOverviewTile(ossim_uint32 resLevel,ossimImageData * result)1814 bool ossimImageHandler::getOverviewTile(ossim_uint32 resLevel,
1815                                         ossimImageData* result)
1816 {
1817    bool status = false;
1818 
1819    if (theOverview.valid())
1820    {
1821       if (theOverview->isValidRLevel(resLevel) && result &&
1822           (result->getNumberOfBands() == getNumberOfOutputBands()) )
1823       {
1824          status = theOverview->getTile(result, resLevel);
1825       }
1826    }
1827 
1828    return status;
1829 }
1830 
getLut() const1831 ossimRefPtr<ossimNBandLutDataObject> ossimImageHandler::getLut()const
1832 {
1833    return theLut;
1834 }
1835 
hasLut() const1836 bool ossimImageHandler::hasLut() const
1837 {
1838    return theLut.valid();
1839 }
1840 
createDefaultOverviewFilename() const1841 ossimFilename ossimImageHandler::createDefaultOverviewFilename() const
1842 {
1843    return getFilenameWithThisExtension("ovr");
1844 }
1845 
createDefaultGeometryFilename() const1846 ossimFilename ossimImageHandler::createDefaultGeometryFilename() const
1847 {
1848    return getFilenameWithThisExtension("geom");
1849 }
1850 
createDefaultMetadataFilename() const1851 ossimFilename ossimImageHandler::createDefaultMetadataFilename() const
1852 {
1853    return getFilenameWithThisExtension("omd");
1854 }
1855 
createDefaultHistogramFilename() const1856 ossimFilename ossimImageHandler::createDefaultHistogramFilename() const
1857 {
1858    return getFilenameWithThisExtension("his");
1859 }
1860 
createDefaultValidVerticesFilename() const1861 ossimFilename ossimImageHandler::createDefaultValidVerticesFilename() const
1862 {
1863    ossimFilename result;
1864 
1865    result = theImageFile.path();
1866    result = result.dirCat(theImageFile.fileNoExtension());
1867    result += "_vertices";
1868    if(getNumberOfEntries() > 1)
1869    {
1870       result += "_e";
1871       result += ossimString::toString(getCurrentEntry());
1872    }
1873    result += ".kwl";
1874 
1875    return result;
1876 }
1877 
getStartingResLevel() const1878 ossim_uint32 ossimImageHandler::getStartingResLevel() const
1879 {
1880    return theStartingResLevel;
1881 }
1882 
setStartingResLevel(ossim_uint32 level)1883 void ossimImageHandler::setStartingResLevel(ossim_uint32 level)
1884 {
1885    theStartingResLevel = level;
1886 }
1887 
getOpenOverviewFlag() const1888 bool ossimImageHandler::getOpenOverviewFlag() const
1889 {
1890    return theOpenOverviewFlag;
1891 }
1892 
setOpenOverviewFlag(bool flag)1893 void ossimImageHandler::setOpenOverviewFlag(bool flag)
1894 {
1895    theOpenOverviewFlag = flag;
1896 
1897    // If false close overview if open??? (drb)
1898 }
1899 
initImageParameters(ossimImageGeometry * geom) const1900 void ossimImageHandler::initImageParameters(ossimImageGeometry* geom) const
1901 {
1902    if ( geom )
1903    {
1904       // Set decimation levels
1905       ossim_uint32 num_levels = getNumberOfDecimationLevels();
1906       if ((num_levels > 0) && (num_levels != geom->getNumberOfDecimations()))
1907       {
1908          geom->setDiscreteDecimation(theDecimationFactors);
1909       }
1910 
1911       // Set image size.
1912       if(geom->getImageSize().hasNans())
1913       {
1914          ossimIrect rect = getBoundingRect();
1915          geom->setImageSize(ossimIpt(rect.width(), rect.height()));
1916       }
1917    }
1918 }
1919