1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License:  See top level LICENSE.txt file.
5 //
6 // Author:  Garrett Potts
7 //
8 // Description:
9 //
10 // Contains class definition for ossimImageMetaData.
11 //
12 //*******************************************************************
13 //  $Id: ossimImageMetaData.cpp 21745 2012-09-16 15:21:53Z dburken $
14 
15 #include <ossim/support_data/ossimImageMetaData.h>
16 #include <ossim/base/ossimCommon.h>
17 #include <ossim/base/ossimKeywordlist.h>
18 #include <ossim/base/ossimKeywordNames.h>
19 #include <ossim/base/ossimString.h>
20 #include <ossim/base/ossimScalarTypeLut.h>
21 #include <ossim/base/ossimTrace.h>
22 #include <algorithm>
23 #include <iostream>
24 #include <vector>
25 
26 static ossimTrace traceDebug("ossimImageMetaData:debug");
27 
ossimImageMetaData()28 ossimImageMetaData::ossimImageMetaData()
29    :theNullPixelArray(0),
30     theMinPixelArray(0),
31     theMaxPixelArray(0),
32     theMinValuesValidFlag(false),
33     theMaxValuesValidFlag(false),
34     theNullValuesValidFlag(false),
35     theScalarType(OSSIM_SCALAR_UNKNOWN),
36     theBytesPerPixel(0),
37     theNumberOfBands(0),
38     theRgbBands()
39 {
40 }
41 
ossimImageMetaData(ossimScalarType aType,ossim_uint32 numberOfBands)42 ossimImageMetaData::ossimImageMetaData(ossimScalarType aType,
43 				       ossim_uint32 numberOfBands)
44    :theNullPixelArray(0),
45     theMinPixelArray(0),
46     theMaxPixelArray(0),
47     theMinValuesValidFlag(false),
48     theMaxValuesValidFlag(false),
49     theNullValuesValidFlag(false),
50     theScalarType(aType),
51     theBytesPerPixel(0),
52     theNumberOfBands(numberOfBands),
53     theRgbBands()
54 {
55    if(theNumberOfBands)
56    {
57       theNullPixelArray = new double[theNumberOfBands];
58       theMinPixelArray  = new double[theNumberOfBands];
59       theMaxPixelArray  = new double[theNumberOfBands];
60 
61       setDefaultsForArrays();
62    }
63    theBytesPerPixel = ossim::scalarSizeInBytes( aType );
64 }
65 
ossimImageMetaData(const ossimImageMetaData & rhs)66 ossimImageMetaData::ossimImageMetaData(const ossimImageMetaData& rhs)
67    :
68    theNullPixelArray(0),
69    theMinPixelArray(0),
70    theMaxPixelArray(0),
71    theMinValuesValidFlag(rhs.theMinValuesValidFlag),
72    theMaxValuesValidFlag(rhs.theMaxValuesValidFlag),
73    theNullValuesValidFlag(rhs.theNullValuesValidFlag),
74    theScalarType(rhs.theScalarType),
75    theBytesPerPixel(rhs.theBytesPerPixel),
76    theNumberOfBands(rhs.theNumberOfBands),
77    theRgbBands(rhs.theRgbBands)
78 {
79    if(theNumberOfBands)
80    {
81       theNullPixelArray = new double[theNumberOfBands];
82       theMinPixelArray  = new double[theNumberOfBands];
83       theMaxPixelArray  = new double[theNumberOfBands];
84 
85       std::copy(rhs.theNullPixelArray,
86                 rhs.theNullPixelArray+theNumberOfBands,
87                 theNullPixelArray);
88       std::copy(rhs.theMinPixelArray,
89                 rhs.theMinPixelArray+theNumberOfBands,
90                 theMinPixelArray);
91       std::copy(rhs.theMaxPixelArray,
92                 rhs.theMaxPixelArray+theNumberOfBands,
93                 theMaxPixelArray);
94    }
95 }
96 
operator =(const ossimImageMetaData & rhs)97 const ossimImageMetaData& ossimImageMetaData::operator=( const ossimImageMetaData& rhs )
98 {
99    if( this != &rhs )
100    {
101       clear();
102       theMinValuesValidFlag  = rhs.theMinValuesValidFlag;
103       theMaxValuesValidFlag  = rhs.theMaxValuesValidFlag;
104       theNullValuesValidFlag = rhs.theNullValuesValidFlag;
105       theNumberOfBands       = rhs.theNumberOfBands;
106       theScalarType          = rhs.theScalarType;
107       theBytesPerPixel       = rhs.theBytesPerPixel;
108       if(theNumberOfBands)
109       {
110          theNullPixelArray = new double[theNumberOfBands];
111          theMinPixelArray  = new double[theNumberOfBands];
112          theMaxPixelArray  = new double[theNumberOfBands];
113 
114          std::copy(rhs.theNullPixelArray,
115                    rhs.theNullPixelArray+theNumberOfBands,
116                    theNullPixelArray);
117          std::copy(rhs.theMinPixelArray,
118                    rhs.theMinPixelArray+theNumberOfBands,
119                    theMinPixelArray);
120          std::copy(rhs.theMaxPixelArray,
121                    rhs.theMaxPixelArray+theNumberOfBands,
122                    theMaxPixelArray);
123       }
124       theRgbBands = rhs.theRgbBands;
125    }
126    return *this;
127 }
128 
~ossimImageMetaData()129 ossimImageMetaData::~ossimImageMetaData()
130 {
131   clear();
132 }
133 
clear()134 void ossimImageMetaData::clear()
135 {
136    if(theNullPixelArray)
137    {
138       delete [] theNullPixelArray;
139       theNullPixelArray = 0;
140    }
141    if(theMinPixelArray)
142    {
143       delete [] theMinPixelArray;
144       theMinPixelArray = 0;
145    }
146    if(theMaxPixelArray)
147    {
148       delete [] theMaxPixelArray;
149       theMaxPixelArray = 0;
150    }
151    theScalarType    = OSSIM_SCALAR_UNKNOWN;
152    theBytesPerPixel = 0;
153    theNumberOfBands = 0;
154    theRgbBands.clear();
155 }
156 
setDefaultsForArrays()157 void ossimImageMetaData::setDefaultsForArrays()
158 {
159    ossim_uint32 i=0;
160 
161    for(i = 0; i < theNumberOfBands; ++i)
162    {
163       theNullPixelArray[i] = ossim::defaultNull(theScalarType);
164       theMinPixelArray[i]  = ossim::defaultMin(theScalarType);
165       theMaxPixelArray[i]  = ossim::defaultMax(theScalarType);
166    }
167 }
168 
setNumberOfBands(ossim_uint32 numberOfBands)169 void ossimImageMetaData::setNumberOfBands(ossim_uint32 numberOfBands)
170 {
171    if(theNullPixelArray)
172    {
173       delete [] theNullPixelArray;
174       theNullPixelArray = 0;
175    }
176    if(theMinPixelArray)
177    {
178       delete [] theMinPixelArray;
179       theMinPixelArray = 0;
180    }
181    if(theMaxPixelArray)
182    {
183       delete [] theMaxPixelArray;
184       theMaxPixelArray = 0;
185    }
186 
187    theNumberOfBands = numberOfBands;
188 
189    if(theNumberOfBands)
190    {
191       theNullPixelArray = new double[theNumberOfBands];
192       theMinPixelArray  = new double[theNumberOfBands];
193       theMaxPixelArray  = new double[theNumberOfBands];
194 
195       setDefaultsForArrays();
196    }
197 }
198 
loadState(const ossimKeywordlist & kwl,const char * prefix)199 bool ossimImageMetaData::loadState(const ossimKeywordlist& kwl, const char* prefix)
200 {
201    bool result = false; // return status
202 
203    // Clear the object:
204    clear();
205 
206    std::string pfx = ( prefix ? prefix : "" );
207 
208    theRgbBands = kwl.findKey( pfx, std::string("rgb_bands") );
209 
210    ossim_uint32 bands = getBandCount( kwl, pfx );
211    if ( bands )
212    {
213       result = true;
214 
215       setNumberOfBands( bands );
216 
217       theMinValuesValidFlag  = true;
218       theMaxValuesValidFlag  = true;
219       theNullValuesValidFlag = true;
220 
221       updateMetaData( kwl, pfx ); // Initializes the rest of object.
222    }
223    else
224    {
225       if (traceDebug())
226       {
227          ossimNotify(ossimNotifyLevel_WARN)
228             << " ERROR:\n"
229             << "Required keyword not found:  " << ossimKeywordNames::NUMBER_BANDS_KW << std::endl;
230       }
231    }
232 
233    if (traceDebug())
234    {
235       print( ossimNotify(ossimNotifyLevel_DEBUG) );
236    }
237 
238    return result;
239 }
240 
saveState(ossimKeywordlist & kwl,const char * prefix) const241 bool ossimImageMetaData::saveState(ossimKeywordlist& kwl,
242 				   const char* prefix)const
243 {
244    kwl.add(prefix, "type", "ossimImageMetaData", true);
245    if ( theNumberOfBands )
246    {
247       ossim_uint32 band = 0;
248 
249       for (band=0; band < theNumberOfBands; ++band)
250       {
251          ossimString kwMin = (ossimKeywordNames::BAND_KW +
252                               ossimString::toString(band+1) + "." +
253                               ossimKeywordNames::MIN_VALUE_KW);
254          ossimString kwMax = (ossimKeywordNames::BAND_KW +
255                               ossimString::toString(band+1) + "." +
256                               ossimKeywordNames::MAX_VALUE_KW);
257          ossimString kwNull = (ossimKeywordNames::BAND_KW +
258                                ossimString::toString(band+1) + "." +
259                                ossimKeywordNames::NULL_VALUE_KW);
260 
261          kwl.add(prefix,
262                  kwMin.c_str(),
263                  theMinPixelArray[band],
264                  true);
265          kwl.add(prefix,
266                  kwMax.c_str(),
267                  theMaxPixelArray[band],
268                  true);
269          kwl.add(prefix,
270                  kwNull.c_str(),
271                  theNullPixelArray[band],
272                  true);
273       }
274       // std::cout << "added bands ******************" << std::endl;
275       kwl.add(prefix,
276 	      ossimKeywordNames::NUMBER_BANDS_KW,
277 	      theNumberOfBands,
278 	      true);
279       kwl.add(prefix,
280 	      ossimKeywordNames::SCALAR_TYPE_KW,
281 	      (ossimScalarTypeLut::instance()->getEntryString(theScalarType)),
282 	      true);
283 
284       kwl.add( prefix, "bytes_per_pixel", theBytesPerPixel, true );
285    }
286 
287    if ( theRgbBands.size() )
288    {
289       kwl.add( prefix, "rgb_bands", theRgbBands.c_str(), true );
290    }
291 
292    return true;
293 }
294 
getNumberOfBands() const295 ossim_uint32 ossimImageMetaData::getNumberOfBands()const
296 {
297    return theNumberOfBands;
298 }
299 
getRgbBands() const300 const std::string& ossimImageMetaData::getRgbBands() const
301 {
302    return theRgbBands;
303 }
304 
getRgbBands(std::vector<ossim_uint32> & bandList) const305 bool ossimImageMetaData::getRgbBands(std::vector<ossim_uint32>& bandList) const
306 {
307    bool result = false;
308    if ( ( theNumberOfBands > 2) && theRgbBands.size() )
309    {
310       ossim::toSimpleVector( bandList, ossimString(theRgbBands) );
311       if ( bandList.size() == 3 )
312       {
313          result = true;
314       }
315       else
316       {
317          bandList.clear();
318       }
319    }
320    return result;
321 }
322 
setScalarType(ossimScalarType aType)323 void ossimImageMetaData::setScalarType(ossimScalarType aType)
324 {
325    theScalarType    = aType;
326    theBytesPerPixel = ossim::scalarSizeInBytes( aType );
327 }
328 
getScalarType() const329 ossimScalarType ossimImageMetaData::getScalarType()const
330 {
331    return theScalarType;
332 }
333 
getBytesPerPixel() const334 ossim_uint32 ossimImageMetaData::getBytesPerPixel() const
335 {
336    return theBytesPerPixel;
337 }
338 
setMinPix(ossim_uint32 band,double pix)339 void ossimImageMetaData::setMinPix(ossim_uint32 band, double pix)
340 {
341    if((band < theNumberOfBands)&&(theMinPixelArray))
342    {
343       theMinPixelArray[band] = pix;
344    }
345 }
346 
setMaxPix(ossim_uint32 band,double pix)347 void ossimImageMetaData::setMaxPix(ossim_uint32 band, double pix)
348 {
349    if((band < theNumberOfBands) && theMaxPixelArray)
350    {
351       theMaxPixelArray[band] = pix;
352    }
353 }
354 
setNullPix(ossim_uint32 band,double pix)355 void ossimImageMetaData::setNullPix(ossim_uint32 band, double pix)
356 {
357    if((band < theNumberOfBands)&&(theNullPixelArray))
358    {
359       theNullPixelArray[band] = pix;
360    }
361 }
362 
getMinPix(ossim_uint32 band) const363 double ossimImageMetaData::getMinPix(ossim_uint32 band)const
364 {
365    if(theNumberOfBands&&theMinPixelArray)
366    {
367       ossim_uint32 i = ossim::min(band, (ossim_uint32)(theNumberOfBands-1));
368 
369       return theMinPixelArray[i];
370    }
371    return ossim::defaultMin(theScalarType);
372 }
373 
getMaxPix(ossim_uint32 band) const374 double ossimImageMetaData::getMaxPix(ossim_uint32 band)const
375 {
376    if(theNumberOfBands&&theMaxPixelArray)
377    {
378       ossim_uint32 i = ossim::min(band, (ossim_uint32)(theNumberOfBands-1));
379 
380       return theMaxPixelArray[i];
381    }
382    return ossim::defaultMax(theScalarType);
383 }
384 
getNullPix(ossim_uint32 band) const385 double ossimImageMetaData::getNullPix(ossim_uint32 band)const
386 {
387    if(theNumberOfBands&&theNullPixelArray)
388    {
389       ossim_uint32 i = ossim::min(band, (ossim_uint32)(theNumberOfBands-1));
390 
391       return theNullPixelArray[i];
392    }
393    return ossim::defaultNull(theScalarType);
394 }
395 
getMinPixelArray() const396 const double* ossimImageMetaData::getMinPixelArray()const
397 {
398    return theMinPixelArray;
399 }
getMaxPixelArray() const400 const double* ossimImageMetaData::getMaxPixelArray()const
401 {
402    return theMaxPixelArray;
403 }
404 
getNullPixelArray() const405 const double* ossimImageMetaData::getNullPixelArray()const
406 {
407    return theNullPixelArray;
408 }
409 
setMinValuesValid(bool flag)410 void ossimImageMetaData::setMinValuesValid(bool flag)
411 {
412    theMinValuesValidFlag = flag;
413 }
414 
setMaxValuesValid(bool flag)415 void ossimImageMetaData::setMaxValuesValid(bool flag)
416 {
417    theMaxValuesValidFlag = flag;
418 }
419 
setNullValuesValid(bool flag)420 void ossimImageMetaData::setNullValuesValid(bool flag)
421 {
422    theNullValuesValidFlag = flag;
423 }
424 
getMinValuesValidFlag() const425 bool ossimImageMetaData::getMinValuesValidFlag()const
426 {
427    return theMinValuesValidFlag;
428 }
429 
getMaxValuesValidFlag() const430 bool ossimImageMetaData::getMaxValuesValidFlag()const
431 {
432    return theMaxValuesValidFlag;
433 }
434 
getNullValuesValidFlag() const435 bool ossimImageMetaData::getNullValuesValidFlag()const
436 {
437    return theNullValuesValidFlag;
438 }
439 
isValid() const440 bool ossimImageMetaData::isValid()const
441 {
442    return (theNumberOfBands > 0);
443 //    return ((theNumberOfBands>0)&&
444 //            (theScalarType != OSSIM_SCALAR_UNKNOWN));
445 }
446 
updateMetaData(const ossimKeywordlist & kwl,const std::string & prefix)447 void ossimImageMetaData::updateMetaData(
448    const ossimKeywordlist& kwl, const std::string& prefix )
449 {
450    ossimString value;
451    std::string key;
452 
453    // Get the bands:
454    if ( !theNumberOfBands )
455    {
456       ossim_uint32 bands = getBandCount( kwl, prefix );
457       if ( bands )
458       {
459          setNumberOfBands( bands );
460       }
461    }
462 
463    if ( theNumberOfBands )
464    {
465       //---
466       // See if bands are zero or one based.  Bands are ONE based in the "omd"
467       // file! If band0 is present assume zero based.
468       //---
469 
470       ossimString regExpression = std::string("^(") + prefix + std::string("band0+.)");
471       std::vector<ossimString> keys = kwl.getSubstringKeyList( regExpression );
472 
473       ossim_uint32 startBand = (keys.size() ? 0 : 1);
474 
475       ossim_uint32 limit = theNumberOfBands+startBand; // For for loop:
476 
477       std::string bs = "band"; // band sting
478       std::string base;
479 
480       for ( ossim_uint32 band = startBand; band < limit; ++band )
481       {
482          base = bs + ossimString::toString( band ).string() + std::string(".") ;
483 
484          // Min:
485          key = base + std::string(ossimKeywordNames::MIN_VALUE_KW);
486          value =  kwl.findKey( prefix, key );
487 
488          if ( value.size() )
489          {
490             theMinPixelArray[ band - startBand  ] = value.toFloat64();
491          }
492 
493          // Max:
494          key = base + std::string(ossimKeywordNames::MAX_VALUE_KW);
495          value =  kwl.findKey( prefix, key );
496          if ( value.size() )
497          {
498             theMaxPixelArray[ band - startBand ] = value.toFloat64();
499          }
500 
501          // Null:
502          key = base + std::string(ossimKeywordNames::NULL_VALUE_KW);
503          value =  kwl.findKey( prefix, key );
504          if ( value.size() )
505          {
506             theNullPixelArray[ band - startBand ] = value.toFloat64();
507          }
508       }
509    }
510 
511 
512    // Scalar, only look for if not set.
513    if ( theScalarType == OSSIM_SCALAR_UNKNOWN )
514    {
515       key = ossimKeywordNames::SCALAR_TYPE_KW; // "scalar_type"
516       value.string() = kwl.findKey( prefix, key );
517       if ( value.empty() )
518       {
519          key = "radiometry";
520          value.string() = kwl.findKey( prefix, key );
521       }
522       if ( value.size() )
523       {
524          theScalarType = ossimScalarTypeLut::instance()->getScalarTypeFromString( value );
525       }
526 
527       if ( theScalarType != OSSIM_SCALAR_UNKNOWN )
528       {
529          theBytesPerPixel = ossim::scalarSizeInBytes( theScalarType );
530       }
531    }
532 
533    if (traceDebug())
534    {
535       ossimNotify(ossimNotifyLevel_DEBUG)
536          << "ossimImageMetaData::updateMetaData DEBUG"
537          << *this << std::endl;
538    }
539 }
540 
print(std::ostream & out) const541 std::ostream& ossimImageMetaData::print(std::ostream& out) const
542 {
543    ossimKeywordlist kwl;
544    saveState( kwl, 0 );
545    out << kwl << std::endl;
546    return out;
547 }
548 
operator <<(std::ostream & out,const ossimImageMetaData & obj)549 std::ostream& operator<<(std::ostream& out, const ossimImageMetaData& obj)
550 {
551    return obj.print( out );
552 }
553 
getBandCount(const ossimKeywordlist & kwl,const std::string & prefix) const554 ossim_uint32 ossimImageMetaData::getBandCount(const ossimKeywordlist& kwl,
555                                               const std::string& prefix) const
556 {
557    ossim_uint32 result = 0;
558 
559    ossimString value;
560    value.string() = kwl.findKey( prefix, std::string(ossimKeywordNames::NUMBER_BANDS_KW) );
561    if ( value.size() )
562    {
563       result = value.toUInt32();
564    }
565    else
566    {
567       value.string() = std::string("^(") + prefix + std::string("band[0-9]+.)");
568       std::vector<ossimString> keys = kwl.getSubstringKeyList( value );
569       result = static_cast<ossim_uint32>( keys.size() );
570    }
571    return result;
572 }
573