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: Utility class for global nitf methods.
10 //
11 //----------------------------------------------------------------------------
12 // $Id: ossimNitfCommon.cpp 17978 2010-08-24 16:17:00Z dburken $
13 
14 #include <cstring> /* for memcpy */
15 #include <sstream>
16 #include <iomanip>
17 #include <sstream>
18 #include <stdexcept>
19 #include <iostream>
20 #include <ossim/support_data/ossimNitfCommon.h>
21 #include <ossim/base/ossimDms.h>
22 #include <ossim/base/ossimDpt.h>
23 #include <ossim/base/ossimIrect.h>
24 #include <ossim/base/ossimNotify.h>
25 #include <ossim/base/ossimTrace.h>
26 
27 static const ossimTrace traceDebug(ossimString("ossimNitfCommon:debug"));
28 
29 
ossimNitfCommon()30 ossimNitfCommon::ossimNitfCommon(){}
31 
~ossimNitfCommon()32 ossimNitfCommon::~ossimNitfCommon(){}
33 
convertToScientificString(const ossim_float64 & aValue,ossim_uint32 size)34 ossimString ossimNitfCommon::convertToScientificString(
35    const ossim_float64& aValue,
36    ossim_uint32 size)
37 {
38    // Precision cannot hit 0 for this to work...
39    if ( ((aValue < 0.0) && (size < 8)) ||
40         ((aValue >= 0.0) && (size < 7)) )
41    {
42       if (traceDebug())
43       {
44          ossimNotify(ossimNotifyLevel_DEBUG)
45             << "ossimNitfCommon::convertToScientificString DEBUG:"
46             << "\nsize range error!"
47             << std::endl;
48       }
49       return ossimString();
50    }
51 
52    //--
53    // Set the precision to account for size with 1.xxxxxE+01
54    //---
55    ossim_uint32 precision = size - 6;
56 
57    if (aValue < 0.0)
58    {
59       --precision;
60    }
61 
62    std::ostringstream s1;
63    s1 << std::setiosflags(std::ios_base::scientific|std::ios_base::internal)
64       << std::setfill('0')
65       // << setw(size)
66       << std::setprecision(precision)
67       << aValue;
68 
69    ossimString result = s1.str();
70 
71    // Upcase the "e".
72    result.upcase();
73 
74    if (traceDebug())
75    {
76       if (result.size() != size)
77       {
78          ossimNotify(ossimNotifyLevel_DEBUG)
79             << "ossimNitfCommon::convertToScientificString DEBUG:"
80             << "\nIncorrect output size!"
81             << "\nValue:  " << aValue
82             << "\nString: " << result
83             << std::endl;
84       }
85    }
86    return result;
87 }
88 
convertToDoubleString(const ossim_float64 & aValue,ossim_uint32 precision,ossim_uint32 size)89 ossimString ossimNitfCommon::convertToDoubleString(
90    const ossim_float64& aValue,
91    ossim_uint32 precision,
92    ossim_uint32 size)
93 {
94    ossim_uint32 width = size;
95 
96    std::ostringstream s1;
97    s1 << std::setiosflags(std::ios_base::fixed|
98                      std::ios_base::internal)
99       << std::setprecision(precision)
100       << std::setfill('0')
101       << std::setw(width)
102       << aValue;
103 
104    ossimString result = s1.str();
105 
106    if (traceDebug())
107    {
108       ossimNotify(ossimNotifyLevel_DEBUG)
109          << "ossimNitfCommon::convertToDoubleString DEBUG:"
110          << "\nresult: " << result << std::endl;
111 
112       if (result.size() != size)
113       {
114          ossimNotify(ossimNotifyLevel_DEBUG)
115             << "ossimNitfCommon::convertToDoubleString DEBUG:"
116             << "\nIncorrect output size!"
117             << std::endl;
118       }
119    }
120    return result;
121 }
122 
convertToUIntString(ossim_uint32 aValue,ossim_uint32 size)123 ossimString ossimNitfCommon::convertToUIntString(ossim_uint32 aValue,
124                                                 ossim_uint32 size)
125 {
126    ossim_uint32 width = size;
127 
128    std::ostringstream s1;
129    s1 << std::setiosflags(std::ios_base::fixed|
130                      std::ios_base::internal)
131       << std::setfill('0')
132       << std::setw(width)
133       << aValue;
134 
135    ossimString result = s1.str();
136 
137    if (traceDebug())
138    {
139       if (result.size() != size)
140       {
141          ossimNotify(ossimNotifyLevel_DEBUG)
142             << "ossimNitfCommon::convertToUIntString DEBUG:"
143             << "\nIncorrect output size!"
144             << "\nValue:  " << aValue
145             << "\nString: " << result
146             << std::endl;
147       }
148    }
149    return result;
150 }
151 
convertToIntString(ossim_int32 aValue,ossim_uint32 size)152 ossimString ossimNitfCommon::convertToIntString(ossim_int32 aValue,
153                                                 ossim_uint32 size)
154 {
155    ossim_uint32 width = size;
156 
157    std::ostringstream s1;
158    s1 << std::setiosflags(std::ios_base::fixed|
159                      std::ios_base::internal)
160       << std::setfill('0')
161       << std::setw(width)
162       << aValue;
163 
164    ossimString result = s1.str();
165 
166    if (traceDebug())
167    {
168       if (result.size() != size)
169       {
170          ossimNotify(ossimNotifyLevel_DEBUG)
171             << "ossimNitfCommon::convertToIntString DEBUG:"
172             << "\nIncorrect output size!"
173             << "\nValue:  " << aValue
174             << "\nString: " << result
175             << std::endl;
176       }
177    }
178    return result;
179 }
180 
convertToDdLatLonLocString(const ossimDpt & pt,ossim_uint32 precision)181 ossimString ossimNitfCommon::convertToDdLatLonLocString(const ossimDpt& pt,
182                                                         ossim_uint32 precision)
183 {
184    ossimString lat;
185    ossimString lon;
186    ossim_uint32 latSize = precision+4; // size = precision + "-33."
187    ossim_uint32 lonSize = precision+5; // size = precision + "-122."
188 
189    if (pt.y >= 0.0)
190    {
191       lat = "+";
192       --latSize;
193    }
194    if (pt.x >= 0.0)
195    {
196       lon = "+";
197       --lonSize;
198    }
199    lat += convertToDoubleString(pt.y,
200                                 precision,
201                                 latSize);
202    lon += convertToDoubleString(pt.x,
203                                 precision,
204                                 lonSize);
205    ossimString result = lat+lon;
206 
207    if (traceDebug())
208    {
209       ossimNotify(ossimNotifyLevel_DEBUG)
210          << "ossimNitfCommon::convertToDdLatLonLocString DEBUG:"
211          << "\nresult: " << result
212          << std::endl;
213    }
214 
215    return result;
216 }
217 
setField(void * fieldDestination,const ossimString & src,std::streamsize width,std::ios_base::fmtflags ioflags,char fill)218 void ossimNitfCommon::setField(void* fieldDestination,
219                                const ossimString& src,
220                                std::streamsize width,
221                                std::ios_base::fmtflags ioflags,
222                                char fill)
223 {
224    std::ostringstream out;
225    out << std::setw(width)
226        << std::setfill(fill)
227        << std::setiosflags(ioflags)
228        << src.trim().c_str();
229 
230    memcpy(fieldDestination, out.str().c_str(), width);
231 }
232 
encodeUtm(ossim_uint32 zone,const ossimDpt & ul,const ossimDpt & ur,const ossimDpt & lr,const ossimDpt & ll)233 ossimString ossimNitfCommon::encodeUtm(
234                                        ossim_uint32 zone,
235                                        const ossimDpt& ul,
236                                        const ossimDpt& ur,
237                                        const ossimDpt& lr,
238                                        const ossimDpt& ll)
239 {
240    std::ostringstream out;
241 
242    if(zone > 60)
243    {
244       std::string s = "ossimNitfImageHeaderV2_1::encodeUtm: ERROR\nUTM zone greate than 60!";
245       if (traceDebug())
246       {
247          ossimNotify(ossimNotifyLevel_WARN) << s << std::endl;
248       }
249       throw std::out_of_range(s);
250    }
251 
252    ossim_float64 east  = ul.x;
253    ossim_float64 north = ul.y;
254 
255    if((ossim_uint32)(east+.5) > 999999)
256    {
257       std::string s = "ossimNitfImageHeaderV2_1::encodeUtm: ERROR\nUpper left easting too large for NITF field!";
258       if (traceDebug())
259       {
260          ossimNotify(ossimNotifyLevel_WARN) << s << std::endl;
261       }
262       throw std::out_of_range(s);
263    }
264 
265    if((ossim_uint32)(north+.5) > 9999999)
266    {
267       std::string s = "ossimNitfImageHeaderV2_1::encodeUtm: ERROR\nUpper left northing too large for NITF field!";
268       if (traceDebug())
269       {
270          ossimNotify(ossimNotifyLevel_WARN) << s << std::endl;
271       }
272       throw std::out_of_range(s);
273    }
274 
275    out << std::setw(2)
276    << std::setfill('0')
277    << zone
278    << std::setw(6)
279    << std::setfill('0')
280    <<(ossim_uint32)(east+.5)
281    << std::setw(7)
282    << std::setfill('0')
283    <<(ossim_uint32)(north+.5);
284 
285 
286    east  = ur.x;
287    north = ur.y;
288 
289    if((ossim_uint32)(east+.5) > 999999)
290    {
291       std::string s = "ossimNitfImageHeaderV2_1::encodeUtm: ERROR\nUpper right easting too large for NITF field!";
292       if (traceDebug())
293       {
294          ossimNotify(ossimNotifyLevel_WARN) << s << std::endl;
295       }
296       throw std::out_of_range(s);
297    }
298 
299    if((ossim_uint32)(north+.5) > 9999999)
300    {
301       std::string s = "ossimNitfImageHeaderV2_1::encodeUtm: ERROR\nUpper right northing too large for NITF field!";
302       if (traceDebug())
303       {
304          ossimNotify(ossimNotifyLevel_WARN) << s << std::endl;
305       }
306       throw std::out_of_range(s);
307    }
308 
309    out << std::setw(2)
310    << std::setfill('0')
311    << zone
312    << std::setw(6)
313    << std::setfill('0')
314    <<(ossim_uint32)(east+.5)
315    << std::setw(7)
316    << std::setfill('0')
317    <<(ossim_uint32)(north+.5);
318    east  = lr.x;
319    north = lr.y;
320 
321    if((ossim_uint32)(east+.5) > 999999)
322    {
323       std::string s = "ossimNitfImageHeaderV2_1::encodeUtm: ERROR\nLower right easting too large for NITF field!";
324       if (traceDebug())
325       {
326          ossimNotify(ossimNotifyLevel_WARN) << s << std::endl;
327       }
328       throw std::out_of_range(s);
329    }
330 
331    if((ossim_uint32)(north+.5) > 9999999)
332    {
333       std::string s = "ossimNitfImageHeaderV2_1::encodeUtm: ERROR\nLower right northing too large for NITF field!";
334       if (traceDebug())
335       {
336          ossimNotify(ossimNotifyLevel_WARN) << s << std::endl;
337       }
338       throw std::out_of_range(s);
339    }
340 
341    out << std::setw(2)
342    << std::setfill('0')
343    << zone
344    << std::setw(6)
345    << std::setfill('0')
346    <<(ossim_uint32)(east+.5)
347    << std::setw(7)
348    << std::setfill('0')
349    <<(ossim_uint32)(north+.5);
350 
351    east  = ll.x;
352    north = ll.y;
353 
354    if((ossim_uint32)(east+.5) > 999999)
355    {
356       std::string s = "ossimNitfImageHeaderV2_1::encodeUtm: ERROR\nLower left easting too large for NITF field!";
357       if (traceDebug())
358       {
359          ossimNotify(ossimNotifyLevel_WARN) << s << std::endl;
360       }
361       throw std::out_of_range(s);
362    }
363 
364    if((ossim_uint32)(north+.5) > 9999999)
365    {
366       std::string s = "ossimNitfImageHeaderV2_1::encodeUtm: ERROR\nLower left northing too large for NITF field!";
367       if (traceDebug())
368       {
369          ossimNotify(ossimNotifyLevel_WARN) << s << std::endl;
370       }
371       throw std::out_of_range(s);
372    }
373 
374    out << std::setw(2)
375    << std::setfill('0')
376    << zone
377    << std::setw(6)
378    << std::setfill('0')
379    <<(ossim_uint32)(east+.5)
380    << std::setw(7)
381    << std::setfill('0')
382    <<(ossim_uint32)(north+.5);
383 
384    return out.str().c_str();
385 }
386 
encodeGeographicDms(const ossimDpt & ul,const ossimDpt & ur,const ossimDpt & lr,const ossimDpt & ll)387 ossimString ossimNitfCommon::encodeGeographicDms(const ossimDpt& ul,
388                                                  const ossimDpt& ur,
389                                                  const ossimDpt& lr,
390                                                  const ossimDpt& ll)
391 {
392    std::ostringstream out;
393 
394    out << ossimDms(ul.y, true).toString("ddmmssC").c_str();
395    out << ossimDms(ul.x, false).toString("dddmmssC").c_str();
396    out << ossimDms(ur.y, true).toString("ddmmssC").c_str();
397    out << ossimDms(ur.x, false).toString("dddmmssC").c_str();
398    out << ossimDms(lr.y, true).toString("ddmmssC").c_str();
399    out << ossimDms(lr.x, false).toString("dddmmssC").c_str();
400    out << ossimDms(ll.y, true).toString("ddmmssC").c_str();
401    out << ossimDms(ll.x, false).toString("dddmmssC").c_str();
402 
403    return ossimString(out.str());
404 }
405 
encodeGeographicDecimalDegrees(const ossimDpt & ul,const ossimDpt & ur,const ossimDpt & lr,const ossimDpt & ll)406 ossimString ossimNitfCommon::encodeGeographicDecimalDegrees(const ossimDpt& ul,
407                                                             const ossimDpt& ur,
408                                                             const ossimDpt& lr,
409                                                             const ossimDpt& ll)
410 {
411    std::ostringstream out;
412 
413    out << (ul.lat >= 0.0?"+":"")
414    << std::setw(6)
415    << std::setfill('0')
416    << std::setprecision(3)
417    << std::setiosflags(std::ios::fixed)
418    << ul.lat
419    << (ul.lon >= 0.0?"+":"")
420    << std::setw(7)
421    << std::setfill('0')
422    << std::setprecision(3)
423    << std::setiosflags(std::ios::fixed)
424    << ul.lon;
425    out << (ur.lat >= 0.0?"+":"")
426    << std::setw(6)
427    << std::setfill('0')
428    << std::setprecision(3)
429    << std::setiosflags(std::ios::fixed)
430    << ur.lat
431    << (ur.lon >= 0.0?"+":"")
432    << std::setw(7)
433    << std::setfill('0')
434    << std::setprecision(3)
435    << std::setiosflags(std::ios::fixed)
436    << ur.lon;
437    out << (lr.lat >= 0.0?"+":"")
438    << std::setw(6)
439    << std::setfill('0')
440    << std::setprecision(3)
441    << std::setiosflags(std::ios::fixed)
442    << lr.lat
443    << (lr.lon >= 0.0?"+":"")
444    << std::setw(7)
445    << std::setfill('0')
446    << std::setprecision(3)
447    << std::setiosflags(std::ios::fixed)
448    << lr.lon;
449    out << (ll.lat >= 0.0?"+":"")
450    << std::setw(6)
451    << std::setfill('0')
452    << std::setprecision(3)
453    << std::setiosflags(std::ios::fixed)
454    << ll.lat
455    << (ll.lon >= 0.0?"+":"")
456    << std::setw(7)
457    << std::setfill('0')
458    << std::setprecision(3)
459    << std::setiosflags(std::ios::fixed)
460    << ll.lon;
461 
462    return ossimString(out.str());
463 }
464 
getNitfPixelType(ossimScalarType scalarType)465 ossimString ossimNitfCommon::getNitfPixelType(ossimScalarType scalarType)
466 {
467    ossimString pixelType;
468    switch(scalarType)
469    {
470       case OSSIM_UINT8:
471       case OSSIM_USHORT11:
472       case OSSIM_USHORT12:
473       case OSSIM_USHORT13:
474       case OSSIM_USHORT14:
475       case OSSIM_USHORT15:
476       case OSSIM_UINT16:
477       case OSSIM_UINT32:
478       {
479          pixelType = "INT";
480          break;
481       }
482       case OSSIM_SINT16:
483       case OSSIM_SINT32:
484       {
485          pixelType    = "SI";
486          break;
487       }
488       case OSSIM_FLOAT:
489       case OSSIM_NORMALIZED_FLOAT:
490       case OSSIM_DOUBLE:
491       case OSSIM_NORMALIZED_DOUBLE:
492       {
493          pixelType    = "R";
494          break;
495       }
496       default:
497       {
498          ossimNotify(ossimNotifyLevel_DEBUG)
499             << __FILE__ << ":" << __LINE__
500             << "\nUnhandled scalar type:  " << scalarType << std::endl;
501          break;
502       }
503    }
504    return pixelType;
505 }
506 
getCompressionRate(const ossimIrect & rect,ossim_uint32 bands,ossimScalarType scalar,ossim_uint64 lengthInBytes)507 ossimString ossimNitfCommon::getCompressionRate(const ossimIrect& rect,
508                                                 ossim_uint32 bands,
509                                                 ossimScalarType scalar,
510                                                 ossim_uint64 lengthInBytes)
511 {
512    ossimString result("");
513 
514    ossim_float64 uncompressedSize =
515       ossim::scalarSizeInBytes(scalar) * rect.width() * rect.height() * bands;
516    ossim_float64 bitsPerPix = ossim::getBitsPerPixel(scalar);
517    ossim_float64 rate = ( bitsPerPix *
518                           (static_cast<ossim_float64>(lengthInBytes) /
519                            uncompressedSize) );
520 
521    // Multiply by 100 as there is an implied decimal point.
522    rate *= 100.0;
523 
524    // Convert to string with zero precision.
525    ossimString s = ossimString::toString(rate, 0, 4);
526 
527    if (s.size())
528    {
529       if (s.size() <= 3)
530       {
531          result = "N";
532          if (s.size() == 3)
533          {
534             result = "0";
535          }
536          else if (s.size() == 2)
537          {
538             result = "00";
539          }
540          result += s;
541       }
542    }
543    return result;
544 }
545 
546