1 //*******************************************************************
2 //
3 // License: MIT
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author: Garrett Potts
8 //
9 // Description: Nitf support class
10 //
11 //********************************************************************
12 // $Id$
13 
14 #include <ossim/support_data/ossimNitfImageHeader.h>
15 #include <ossim/base/ossimContainerProperty.h>
ossimNitfImageDataMaskV2_1()16 #include <ossim/base/ossimDrect.h>
17 #include <ossim/base/ossimIrect.h>
18 #include <ossim/base/ossimNotifyContext.h>
19 
20 #include <cmath> /* for fmod */
21 #include <iomanip>
22 #include <ostream>
23 #include <sstream>
24 
25 RTTI_DEF2(ossimNitfImageHeader,
26           "ossimNitfImageHeader",
27           ossimObject,
28           ossimPropertyInterface)
29 
30 static const char* TAGS_KW = "tags";
31 
32 ossimNitfImageHeader::ossimNitfImageHeader()
33 {
34 }
35 
36 ossimNitfImageHeader::~ossimNitfImageHeader()
37 {
writeStream(std::ostream & out)38 }
39 
40 bool ossimNitfImageHeader::getTagInformation(ossimNitfTagInformation& tagInfo,
41                                              const ossimString& tagName)const
42 {
43    if(theTagList.size())
44    {
45       for(ossim_uint32 idx = 0; idx < theTagList.size(); ++idx)
46       {
47          if(theTagList[idx].getTagName() == tagName)
48          {
49             tagInfo = theTagList[idx];
50             return true;
51          }
52       }
53    }
54 
55    return false;
56 }
57 
58 bool ossimNitfImageHeader::getTagInformation(
59    ossimNitfTagInformation& tagInfo, ossim_uint32 idx) const
60 {
61    bool result = false;
62 
63    if(idx < theTagList.size())
64    {
65       tagInfo = theTagList[idx];
66       result = true;
67    }
68 
69    return result;
70 }
71 
72 ossimRefPtr<ossimNitfRegisteredTag> ossimNitfImageHeader::getTagData(
73    const ossimString& tagName)
74 {
75    if(theTagList.size())
76    {
77       for(ossim_uint32 idx = 0; idx < theTagList.size(); ++idx)
78       {
79          if(theTagList[idx].getTagName() == tagName)
80          {
81             return theTagList[idx].getTagData();
82          }
83       }
84    }
85 
86    return ossimRefPtr<ossimNitfRegisteredTag>();
87 }
88 
89 const ossimRefPtr<ossimNitfRegisteredTag> ossimNitfImageHeader::getTagData(
90    const ossimString& tagName) const
91 {
92    if(theTagList.size())
93    {
94       for(ossim_uint32 idx = 0; idx < theTagList.size(); ++idx)
95       {
96          if(theTagList[idx].getTagName() == tagName)
97          {
98             return theTagList[idx].getTagData();
99          }
100       }
101    }
102 
103    return ossimRefPtr<ossimNitfRegisteredTag>();
104 }
105 
106 void ossimNitfImageHeader::getTagData(
107    const ossimString& tagName,
108    std::vector< const ossimNitfRegisteredTag* > &tags ) const
109 {
110    tags.clear();
111    if(theTagList.size())
112    {
113       for(ossim_uint32 idx = 0; idx < theTagList.size(); ++idx)
114       {
115          if(theTagList[idx].getTagName() == tagName)
116          {
117             tags.push_back( theTagList[idx].getTagData().get() );
118          }
119       }
120    }
121 }
122 
123 ossim_uint32 ossimNitfImageHeader::getNumberOfTags()const
124 {
125    return static_cast<ossim_uint32>(theTagList.size());
126 }
127 
128 void ossimNitfImageHeader::addTag(const ossimNitfTagInformation& tag, bool unique)
129 {
130    if(unique)
131    {
132       removeTag(tag.getTagName());
133    }
134    theTagList.push_back(tag);
135 }
136 
137 void ossimNitfImageHeader::removeTag(const ossimString& tagName)
138 {
139    ossim_uint32 idx = 0;
140    for(idx = 0; idx < theTagList.size(); ++idx)
141    {
142       if(theTagList[idx].getTagName() == tagName)
143       {
144          theTagList.erase(theTagList.begin() + idx);
145          return;
146       }
147    }
148 }
149 
150 bool ossimNitfImageHeader::isSameAs(const ossimNitfImageHeader* hdr) const
151 {
152    if (!hdr) return false;
153 
154    return ( (isCompressed() == hdr->isCompressed()) &&
155             (getNumberOfRows() == hdr->getNumberOfRows()) &&
156             (getNumberOfBands() == hdr->getNumberOfBands()) &&
157             (getNumberOfCols() == hdr->getNumberOfCols()) &&
158             (getNumberOfBlocksPerRow() == hdr->getNumberOfBlocksPerRow()) &&
159             (getNumberOfBlocksPerCol() == hdr->getNumberOfBlocksPerCol()) &&
160             (getNumberOfPixelsPerBlockHoriz() ==
161              hdr->getNumberOfPixelsPerBlockHoriz()) &&
162             (getNumberOfPixelsPerBlockVert() ==
163              hdr->getNumberOfPixelsPerBlockVert()) &&
164             (getBitsPerPixelPerBand() == hdr->getBitsPerPixelPerBand()) &&
165             (getImageRect() == hdr->getImageRect()) &&
166             (getIMode() == hdr->getIMode()) &&
167             (getCoordinateSystem() == hdr->getCoordinateSystem()) &&
168             (getGeographicLocation() == hdr->getGeographicLocation()) );
169 }
170 
171 
172 void ossimNitfImageHeader::setProperty(ossimRefPtr<ossimProperty> /* property */)
173 {
174 }
175 
176 ossimRefPtr<ossimProperty> ossimNitfImageHeader::getProperty(const ossimString& name)const
177 {
178    ossimProperty* result = 0;
179 
180    if(name == TAGS_KW)
181    {
182       ossim_uint32 idxMax = getNumberOfTags();
183       if(idxMax > 0)
184       {
185          ossimContainerProperty* containerProperty = new ossimContainerProperty;
186          containerProperty->setName(name);
187          ossim_uint32 idx = 0;
188 
189          result = containerProperty;
190          for(idx = 0; idx < idxMax; ++idx)
191          {
192             ossimNitfTagInformation tagInfo;
193             getTagInformation(tagInfo, idx);
194 
195             const ossimRefPtr<ossimNitfRegisteredTag> tagData = tagInfo.getTagData();
196             if(tagData.valid())
197             {
198                ossimContainerProperty* containerPropertyTag = new ossimContainerProperty;
199                containerPropertyTag->setName(tagInfo.getTagName());
200                std::vector<ossimRefPtr<ossimProperty> > propertyList;
201                tagData->getPropertyList(propertyList);
202 
203                containerPropertyTag->addChildren(propertyList);
204                containerProperty->addChild(containerPropertyTag);
205             }
206             else
207             {
208                containerProperty->addStringProperty(tagInfo.getTagName(), "", true);
209             }
210          }
211       }
212    }
213 
214    return result;
215 }
216 
217 void ossimNitfImageHeader::getPropertyNames(std::vector<ossimString>& propertyNames)const
218 {
219    propertyNames.push_back(TAGS_KW);
220 
221 }
222 
223 ossim_uint32 ossimNitfImageHeader::getTotalTagLength()const
224 {
225    ossim_uint32 tagLength = 0;
226 
227    for(ossim_uint32 i = 0; i < theTagList.size(); ++i)
228    {
229       tagLength += theTagList[i].getTotalTagLength();
230    }
231 
232    return tagLength;
233 }
234 
235 std::ostream& ossimNitfImageHeader::printTags(std::ostream& out,
236                                               const std::string& prefix)const
237 {
238    for(ossim_uint32 i = 0; i < theTagList.size(); ++i)
239    {
240       ossimRefPtr<ossimNitfRegisteredTag> tag = theTagList[i].getTagData();
241       if (tag.valid())
242       {
243          tag->print(out, prefix);
244       }
245    }
246    return out;
247 }
248 
249 void ossimNitfImageHeader::getMetadata(ossimKeywordlist& kwl,
250                                        const char* prefix) const
251 {
252    kwl.add(prefix, "source",
253            getImageSource().c_str(),
254            false);
255    kwl.add(prefix,
256            "image_date",
257            getAcquisitionDateMonthDayYear().c_str(),
258            false);
259    kwl.add(prefix,
260            "image_title",
261            getTitle().c_str(),
262            false);
263 }
264 
265 bool ossimNitfImageHeader::hasLut() const
266 {
267    bool result = false;
268 
269    const ossim_uint32 BANDS = static_cast<ossim_uint32>(getNumberOfBands());
270    for (ossim_uint32 band = 0; band < BANDS; ++band)
271    {
272       const ossimRefPtr<ossimNitfImageBand> imgBand = getBandInformation(band);
273       if(imgBand.valid())
274       {
275          ossim_uint32 luts = imgBand->getNumberOfLuts();
276          if(luts > 0)
277          {
278             if(imgBand->getLut(0).valid())
279             {
280                result = true;
281                break;
282             }
283          }
284       }
285    }
286 
287    return result;
288 }
289 
290 ossimRefPtr<ossimNBandLutDataObject> ossimNitfImageHeader::createLut(
291    ossim_uint32 bandIdx)const
292 {
293    ossimRefPtr<ossimNBandLutDataObject> result;
294 
295    if(bandIdx < (ossim_uint32)getNumberOfBands())
296    {
297       const ossimRefPtr<ossimNitfImageBand> band = getBandInformation(bandIdx);
298       if(band.valid())
299       {
300          ossim_uint32 bands = band->getNumberOfLuts();
301          if(bands > 0)
302          {
303             if(band->getLut(0).valid())
304             {
305                ossim_uint32 entries = band->getLut(0)->getNumberOfEntries();
306 
307                result = new ossimNBandLutDataObject();
308                result->create(entries, band->getNumberOfLuts());
309                ossim_uint32 bIdx;
310                ossim_uint32 entryIdx;
311 
312                for(bIdx = 0; bIdx < bands; ++bIdx)
313                {
314                   const ossimRefPtr<ossimNitfImageLut> lut = band->getLut(bIdx);
315                   if(lut.valid())
316                   {
317                      for(entryIdx = 0; entryIdx < entries; ++entryIdx)
318                      {
319                         (*result)[entryIdx][bIdx] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(lut->getValue(entryIdx));
320                      }
321                   }
322                }
323             }
324          }
325       }
326    }
327 
328    return result;
329 }
330 
331 
332 void ossimNitfImageHeader::checkForGeographicTiePointTruncation(
333    const ossimDpt& tie) const
334 {
335    // One arc second in decimal degrees.
336    const ossim_float64 ARC_SECOND = 1.0/3600.0;
337 
338    // Very small number.
339    const ossim_float64 FUDGE_FACTOR = 0.000000001;
340 
341    // Remainder portion of latitude divided by an arc second.
342    ossim_float64 y = std::fmod(tie.y, ARC_SECOND);
343 
344    // Remainder portion of longitue divided by an arc second.
345    ossim_float64 x = std::fmod(tie.x, ARC_SECOND);
346 
347    if ( (std::fabs(y) > FUDGE_FACTOR) || (std::fabs(x) > FUDGE_FACTOR) )
348    {
349       ossimNotify(ossimNotifyLevel_WARN)
350          << "ossimNitfImageHeader WARNING:\n"
351          << "Tie point will be truncated in image header:  "
352          << tie
353          << std::endl;
354    }
355 }
356 
357 void ossimNitfImageHeader::getDecimationFactor(ossim_float64& result) const
358 {
359    //---
360    // Look for string like:
361    //
362    // "/2" = 1/2
363    // "/4  = 1/4
364    // ...
365    // "/16 = 1/16
366    //
367    // If it is full resolution it should be "1.0"
368    //
369    // or
370    //
371    // "0.5" which is the same as "/2"
372    // "0.25" which is the same as "/4"
373    //---
374    ossimString os = getImageMagnification();
375 
376    // Spec says to fill with spaces so strip them.
377    os.trim(ossimString(" "));
378 
379    if (os.size())
380    {
381       if ( os.contains("/") )
382       {
383          os = os.after("/");
384          result = os.toFloat64();
385          if (result)
386          {
387             result = 1.0 / result;
388          }
389       }
390       else
391       {
392          result = os.toFloat64();
393       }
394    }
395    else
396    {
397       result = ossim::nan();
398    }
399 }
400 
401 
402 bool ossimNitfImageHeader::saveState(ossimKeywordlist& kwl, const ossimString& prefix)const
403 {
404    if(!ossimObject::saveState(kwl, prefix)) return false;
405    ossimString tagsPrefix = prefix;
406 
407    for(ossim_uint32 i = 0; i < theTagList.size(); ++i)
408    {
409       ossimRefPtr<ossimNitfRegisteredTag> tag = theTagList[i].getTagData();
410       if (tag.valid())
411       {
412          if(!tag->saveState(kwl, tagsPrefix))
413          {
414             return false;
415          }
416       }
417    }
418    return true;
419 }
420