1 //*******************************************************************
2 //
3 // License:  LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author:  Mingjie Su
8 //
9 //*******************************************************************
10 //  $Id: ossim-src2src.cpp 2644 2011-05-26 15:20:11Z oscar.kramer $
11 
12 #include <ossim/base/ossimArgumentParser.h>
13 #include <ossim/base/ossimApplicationUsage.h>
14 #include <ossim/base/ossimContainerProperty.h>
15 #include <ossim/base/ossimConstants.h>
16 #include <ossim/base/ossimFilename.h>
17 #include <ossim/base/ossimKeywordlist.h>
18 #include <ossim/base/ossimKeywordNames.h>
19 #include <ossim/base/ossimNotify.h>
20 #include <ossim/base/ossimObjectFactoryRegistry.h>
21 #include <ossim/base/ossimPreferences.h>
22 #include <ossim/base/ossimRefPtr.h>
23 #include <ossim/base/ossimString.h>
24 #include <ossim/imaging/ossimImageHandler.h>
25 #include <ossim/imaging/ossimImageHandlerRegistry.h>
26 #include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
27 #include <ossim/imaging/ossimTilingPoly.h>
28 #include <ossim/init/ossimInit.h>
29 #include <ossim/plugin/ossimSharedPluginRegistry.h>
30 #include <ossim/projection/ossimMapProjection.h>
31 #include <ossim/projection/ossimMapProjectionInfo.h>
32 #include <ossim/projection/ossimProjection.h>
33 #include <ossim/projection/ossimProjectionFactoryRegistry.h>
34 #include <ossim/projection/ossimEquDistCylProjection.h>
35 #include <ossim/support_data/ossimInfoBase.h>
36 #include <ossim/support_data/ossimInfoFactoryRegistry.h>
37 #include <ossim/support_data/ossimSrcRecord.h>
38 
39 #include <iostream>
40 #include <vector>
41 using namespace std;
42 
43 
44 //**************************************************************************
45 // usage()
46 //**************************************************************************
usage()47 void usage()
48 {
49    ossimNotify(ossimNotifyLevel_INFO)
50       << " examples:\n\n"
51       << "    ossim-create-src --tiling-template ./mytemplate.template ./myfile.tif ./outdir\n"
52       << std::endl;;
53 }
54 
55 //*****************************************************************************************
56 // Centralized point to capture all program exits (aids in debugging -- please leave)
57 //*****************************************************************************************
finalize(int exit_code)58 void finalize(int exit_code)
59 {
60    exit(exit_code);
61 }
62 
parseSrcFile(const ossimFilename & srcFile,vector<ossimSrcRecord> & srcRecordFiles,ossimString & prefix)63 void parseSrcFile(const ossimFilename& srcFile, vector<ossimSrcRecord>& srcRecordFiles, ossimString& prefix)
64 {
65    if (!srcFile.isReadable())
66       return;
67 
68    ossimKeywordlist src_kwl (srcFile);
69    unsigned int image_idx = 0;
70    ossimString lookup = src_kwl.find("dem0.file");
71    if (!lookup.empty())
72    {
73       prefix = "dem";
74    }
75 
76    // Loop to read all image file entries:
77    while (true)
78    {
79       ossimSrcRecord srcRecord(src_kwl, image_idx++, prefix);
80       if (!srcRecord.valid())
81          break;
82 
83       srcRecordFiles.push_back(srcRecord);
84    }
85 }
86 
getTiling(const ossimFilename & templateFile)87 ossimRefPtr<ossimTilingPoly> getTiling(const ossimFilename& templateFile)
88 {
89    ossimKeywordlist templateKwl;
90    if (!templateKwl.addFile(templateFile))
91    {
92       return 0;
93    }
94 
95    ossimString prefix ("igen.tiling.");
96    while (1)
97    {
98       if (templateKwl.find(prefix.chars(), "tile_source"))
99       {
100          break;
101       }
102       else
103       {
104          return 0;
105       }
106 
107       // If we got here, then no matches were found in the template. Try again but without a prefix:
108       if (prefix.empty())
109          break;
110       prefix.clear();
111    }
112 
113    // Initialize the tiling object if enabled:
114    ossimRefPtr<ossimTilingPoly> tiling = new ossimTilingPoly;
115 
116    if (!tiling->loadState(templateKwl, prefix))
117    {
118       return 0;
119    }
120 
121    return tiling;
122 }
123 
getRect(ossimRefPtr<ossimMapProjection> mapProj,vector<ossimGpt> points)124 ossimDrect getRect(ossimRefPtr<ossimMapProjection> mapProj,
125    vector<ossimGpt> points)
126 {
127    std::vector<ossimDpt> rectTmp;
128    rectTmp.resize(points.size());
129 
130    for(std::vector<ossimGpt>::size_type index=0; index < points.size(); ++index)
131    {
132       mapProj->worldToLineSample(points[(int)index], rectTmp[(int)index]);
133    }
134 
135    if (rectTmp.size() > 3)
136    {
137       ossimDrect rect2 = ossimDrect(rectTmp[0],
138          rectTmp[1],
139          rectTmp[2],
140          rectTmp[3]);
141 
142       return rect2;
143    }
144    return ossimDrect();
145 }
146 
147 //**************************************************************************
148 // Main Application
149 //**************************************************************************
main(int argc,char * argv[])150 int main(int argc, char *argv[])
151 {
152    std::string tempString1;
153    ossimArgumentParser::ossimParameter stringParam1(tempString1);
154    std::string tempString2;
155    ossimArgumentParser::ossimParameter stringParam2(tempString2);
156 
157    ossimArgumentParser argumentParser(&argc, argv);
158    ossimInit::instance()->addOptions(argumentParser);
159    ossimInit::instance()->initialize(argumentParser);
160 
161    ossimApplicationUsage* appuse = argumentParser.getApplicationUsage();
162 
163    appuse->setApplicationName(argumentParser.getApplicationName());
164 
165    appuse->setDescription(argumentParser.getApplicationName()+
166       " generate src files for polygons.");
167 
168    appuse->setCommandLineUsage(argumentParser.getApplicationName()+
169       "ossim-create-src [--tiling-template] <full path to template file>");
170 
171    appuse->addCommandLineOption("--tiling-template", "Specify an external file that contains tiling information.");
172 
173    ossimFilename templateFile = "";
174 
175    if(argumentParser.read("--tiling-template", stringParam1))
176    {
177       templateFile = ossimFilename(tempString1);
178    }
179 
180    // End of arg parsing.
181    argumentParser.reportRemainingOptionsAsUnrecognized();
182    if ( argumentParser.errors() )
183    {
184       argumentParser.writeErrorMessages(ossimNotify(ossimNotifyLevel_NOTICE));
185       finalize(1);
186    }
187 
188    if (argc == 1)
189    {
190       ossimNotify(ossimNotifyLevel_WARN)<< "Must supply an input file or info option." << std::endl;
191       finalize(0);
192    }
193 
194    ossim_uint32 idx = 0;
195    ossim_uint32 last_idx = argumentParser.argc()-1;
196    ossimFilename inputSrcFile = "";
197    ossimString prefixStr = "image";
198    vector<ossimSrcRecord> inputFiles;
199    while(argumentParser.argv()[idx] && (idx < last_idx))
200    {
201       ossimString file = argumentParser.argv()[idx];
202       if (file.contains(".src"))
203       {
204          // input file spec provided via src file. Need to parse it:
205          inputSrcFile = ossimFilename(file);
206          if (!inputSrcFile.exists() )
207          {
208             ossimNotify(ossimNotifyLevel_WARN) << "ossim-src2src: file does not exist:  " << inputSrcFile
209                << std::endl;
210             finalize(1);
211          }
212          parseSrcFile(inputSrcFile, inputFiles, prefixStr);
213       }
214       ++idx;
215    }
216 
217    // The last filename left on the command line should be the product filename:
218    ossimFilename outputFileDir = argumentParser.argv()[last_idx];
219    if (!outputFileDir.isDir())
220    {
221       outputFileDir = outputFileDir.path();
222       if (!outputFileDir.exists() )
223       {
224          ossimNotify(ossimNotifyLevel_WARN) << "ossim-src2src: output directory does not exist:  " << outputFileDir
225             << std::endl;
226          finalize(1);
227       }
228    }
229 
230    if (!templateFile.exists())
231    {
232       ossimNotify(ossimNotifyLevel_WARN) << "ossim-src2src: template file does not exist::  " << templateFile
233          << std::endl;
234       finalize(1);
235    }
236 
237    ossimRefPtr<ossimTilingPoly> polyTiling = getTiling(templateFile);
238    if (!polyTiling.valid())
239    {
240       ossimNotify(ossimNotifyLevel_WARN) << "ossim-src2src: error generating tiling:  " << templateFile
241          << std::endl;
242       finalize(1);
243    }
244 
245    // Open up src file to get coordinate info from each file listed in src file.
246    ossim_float64 minLat = 90.0;
247    ossim_float64 maxLat = -90.0;
248    ossim_float64 minLon = 180.0;
249    ossim_float64 maxLon = -180.0;
250 
251    ossimString tileName;
252    ossimIrect clipRect;
253    map<ossimString, ossimSrcRecord> infos;
254    ossimRefPtr<ossimMapProjection> mapProj = 0;
255 
256    for (ossim_uint32 i = 0; i < inputFiles.size(); i++)
257    {
258       ossimFilename inputFile = inputFiles[i].getFilename();
259       vector<ossim_uint32> entryList;
260       ossimRefPtr<ossimImageHandler> ih = ossimImageHandlerRegistry::instance()->open(inputFile);
261       if (ih.valid() )
262       {
263          if(inputFiles[i].getEntryIndex() > -1 )
264          {
265             entryList.push_back(inputFiles[i].getEntryIndex());
266          }
267          else
268          {
269             ih->getEntryList(entryList);
270          }
271 
272          for(ossim_uint32 entryIdx = 0; entryIdx < entryList.size(); ++entryIdx)
273          {
274             // Establish the image handler for this particular frame. This may be just
275             // the handler already opened in the case of single image per file:
276             ossimImageHandler* img_handler = 0;
277             if (entryList.size() == 1)
278             {
279                img_handler = ih.get();
280             }
281             else
282             {
283                img_handler = (ossimImageHandler*)ih->dup();
284             }
285 
286             img_handler->setCurrentEntry(entryList[entryIdx]);
287 
288             ossimDrect outputRect = img_handler->getBoundingRect();
289 
290             ossimRefPtr<ossimImageGeometry> geom = img_handler->getImageGeometry();
291             if(geom.valid())
292             {
293                ossimGpt ulg;
294                ossimGpt llg;
295                ossimGpt lrg;
296                ossimGpt urg;
297 
298                geom->localToWorld(outputRect.ul(), ulg);
299                geom->localToWorld(outputRect.ll(), llg);
300                geom->localToWorld(outputRect.lr(), lrg);
301                geom->localToWorld(outputRect.ur(), urg);
302 
303                //find min and max lat, lon for whole src file
304                if (minLat > llg.lat)
305                {
306                   minLat = llg.lat;
307                }
308 
309                if (minLon > llg.lon)
310                {
311                   minLon = llg.lon;
312                }
313 
314                if (maxLat < urg.lat)
315                {
316                   maxLat = urg.lat;
317                }
318 
319                if (maxLon < urg.lon)
320                {
321                   maxLon = urg.lon;
322                }
323 
324                ossimString fileInfo = inputFile + "|" + ossimString::toString(entryIdx) + "|" +
325                   ossimString::toString(ulg.lon) + "," + ossimString::toString(ulg.lat) + "," +
326                   ossimString::toString(urg.lon) + "," + ossimString::toString(urg.lat) + "," +
327                   ossimString::toString(lrg.lon) + "," + ossimString::toString(lrg.lat) + "," +
328                   ossimString::toString(llg.lon) + "," + ossimString::toString(llg.lat);
329 
330                infos[fileInfo] = inputFiles[i];
331 
332                if (!mapProj.valid())
333                {
334                   ossimRefPtr<ossimProjection> proj = geom->getProjection();
335                   if (proj.valid())
336                   {
337                      mapProj = PTR_CAST(ossimMapProjection, proj->dup());
338                      if (!mapProj.valid()) //default it to ossimEquDistCylProjection
339                      {
340                         mapProj = new ossimEquDistCylProjection;
341                         mapProj->setMetersPerPixel(geom->getMetersPerPixel());
342                      }
343                   }
344                }
345             }
346             img_handler = 0;
347          }
348          ih = 0;
349       }
350       else
351       {
352          continue;
353       }
354    }
355    inputFiles.clear();
356 
357    //get bounding rect for entire image
358    vector<ossimGpt> points;
359    if (points.size() == 0)
360    {
361       points.push_back(ossimGpt(maxLat, minLon));
362       points.push_back(ossimGpt(maxLat, maxLon));
363       points.push_back(ossimGpt(minLat, maxLon));
364       points.push_back(ossimGpt(minLat, minLon));
365    }
366 
367    if(mapProj.valid())
368    {
369       ossimGpt tie(maxLat, minLon);
370       mapProj->setUlTiePoints(tie);
371       polyTiling->initialize(*(mapProj.get()), getRect(mapProj, points));
372    }
373 
374    while(polyTiling->next(mapProj, clipRect, tileName))
375    {
376       ossimFilename outSrc = outputFileDir + "/" + ossimFilename(tileName).noExtension() + ".src";
377 
378       map<ossimString, ossimSrcRecord>::iterator it = infos.begin();
379       ossim_int32 index = 0;
380       map<ossim_int32, ossimSrcRecord> srcList;
381       while (it != infos.end())
382       {
383          ossimString fileInfo = it->first;
384          vector<ossimString> fileInfos = fileInfo.split("|");
385          ossim_int32 entryId = fileInfos[1].toInt();
386          vector<ossimString> latlonInfo = fileInfos[2].split(",");
387 
388          double ulgLon = latlonInfo[0].toDouble();
389          double ulgLat = latlonInfo[1].toDouble();
390          double urgLon = latlonInfo[2].toDouble();
391          double urgLat = latlonInfo[3].toDouble();
392          double lrgLon = latlonInfo[4].toDouble();
393          double lrgLat = latlonInfo[5].toDouble();
394          double llgLon = latlonInfo[6].toDouble();
395          double llgLat = latlonInfo[7].toDouble();
396 
397          points.clear();
398          points.push_back(ossimGpt(ulgLat, ulgLon));
399          points.push_back(ossimGpt(urgLat, urgLon));
400          points.push_back(ossimGpt(lrgLat, lrgLon));
401          points.push_back(ossimGpt(llgLat, llgLon));
402 
403          //get bounding for each image listed in src file
404          ossimDrect rect = getRect(mapProj, points);
405 
406          //check if the rect of image intersect with the rect of tile
407          if (rect.intersects(clipRect))
408          {
409             ossimSrcRecord srcRecord = it->second;
410             srcRecord.setEntryIndex(entryId);
411             srcList[index] = srcRecord;
412             index++;
413          }
414          it++;
415       }
416 
417       //write image files which intersect with the tile to a new src file
418       if (srcList.size() > 0)
419       {
420          ofstream outputSrcFile(outSrc.c_str());
421          map<ossim_int32, ossimSrcRecord>::iterator srcIt = srcList.begin();
422          while (srcIt != srcList.end())
423          {
424             ossimString prefix = prefixStr + ossimString::toString(srcIt->first) + ".";
425 
426             ossimFilename newSrcFile = srcIt->second.getFilename();
427             ossim_int32 entryId = srcIt->second.getEntryIndex();
428             ossimFilename supportDir = srcIt->second.getSupportDir();
429             ossimString hisOp = srcIt->second.getHistogramOp();
430             vector<ossim_uint32> bands = srcIt->second.getBands();
431             double weight = srcIt->second.getWeight();
432             ossimFilename overviewPath = srcIt->second.getOverviewPath();
433             ossimFilename hisPath = srcIt->second.getHistogramPath();
434             ossimFilename maskPath = srcIt->second.getMaskPath();
435 
436             if (!newSrcFile.empty())
437             {
438                ossimString str = prefix + "file: " + newSrcFile;
439                outputSrcFile << str << "\n";
440             }
441 
442             if (entryId > -1)
443             {
444                ossimString str = prefix + "entry: " + ossimString::toString(entryId);
445                outputSrcFile << str << "\n";
446             }
447 
448             if (!supportDir.empty())
449             {
450                ossimString str = prefix + "support: " + supportDir;
451                outputSrcFile << str << "\n";
452             }
453 
454             if (!hisOp.empty())
455             {
456                ossimString str = prefix + "hist-op: " + hisOp;
457                outputSrcFile << str << "\n";
458             }
459 
460             if (bands.size())
461             {
462                ossimString str = "";
463                for (ossim_uint32 bandIndex = 0; bandIndex < bands.size(); bandIndex++)
464                {
465                   if (bandIndex == (bands.size()-1))
466                   {
467                      str = str + ossimString::toString(bands[bandIndex]+1);
468                   }
469                   else
470                   {
471                      str = str + ossimString::toString(bands[bandIndex]+1) + ",";
472                   }
473                }
474                str = prefix + "rgb: " + str;
475                outputSrcFile << str << "\n";
476             }
477 
478             if (weight > 0)
479             {
480                ossimString str = prefix + "opacity: " + ossimString::toString(weight);
481                outputSrcFile << str << "\n";
482             }
483 
484             if (!overviewPath.empty())
485             {
486                ossimString str = prefix + "ovr: " + overviewPath;
487                outputSrcFile << str << "\n";
488             }
489 
490             if (!hisPath.empty())
491             {
492                ossimString str = prefix + "hist: " + hisPath;
493                outputSrcFile << str << "\n";
494             }
495 
496             if (!maskPath.empty())
497             {
498                ossimString str = prefix + "mask: " + maskPath;
499                outputSrcFile << str << "\n";
500             }
501             outputSrcFile << "\n";
502             srcIt++;
503          }
504          outputSrcFile.close();
505          srcList.clear();
506       }
507    }
508 
509    if (polyTiling.valid())
510    {
511       polyTiling = 0;
512    }
513    if (mapProj.valid())
514    {
515       mapProj = 0;
516    }
517    points.clear();
518    infos.clear();
519 
520    finalize(0);
521    return 0; // Never reached, but satisfies return type
522 }
523