OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimSubImageTool.cpp
Go to the documentation of this file.
1 //**************************************************************************************************
2 //
3 // OSSIM Open Source Geospatial Data Processing Library
4 // See top level LICENSE.txt file for license information
5 //
6 //**************************************************************************************************
7 
11 #include <ossim/base/ossimNotify.h>
13 #include <ossim/base/ossimString.h>
19 #include <iostream>
20 
21 using namespace std;
22 
23 const char* ossimSubImageTool::DESCRIPTION = "Tool for extracting a sub-image from a full image."
24  " No reprojection is done. Presently, the subimage geometry is represented by an RPC "
25  "replacement model until generic models can support subimage chipping.";
26 const char* BBOX_KW = "bbox";
27 
29 : m_geomFormat (OGEOM)
30 {
31 }
32 
34 {
35 }
36 
38 {
39  // Add options.
41  ossimString usageString = ap.getApplicationName();
42  usageString += " subimage [options] <input-image> <output-image>";
43  au->setCommandLineUsage(usageString);
44 
45  // Set the command line options:
47 
48  // Base class has its own. Skip the ossimChipProcTool usage as that adds a lot of view-space
49  // specific stuff not used in this tool:
51 
53  "--bbox <ulx> <uly> <lrx> <lry>",
54  "Specify upper-left and lower-right bounds the image rect (in pixels).");
56  "-e | --entry <N> ",
57  "For multi image entries which entry do you wish to extract. For list "
58  "of entries use: \"ossim-info -i <your_image>\" ");
60  "--geom <format>", "Specifies format of the subimage RPC geometry file."
61  " Possible values are: \"OGEOM\" (OSSIM geometry, default), \"DG\" (DigitalGlobe WV/QB "
62  ".RPB format), \"JSON\" (MSP-style JSON), or \"XML\". Case insensitive.");
63 }
64 
66 {
67  if (!ossimTool::initialize(ap))
68  return false;
69  if (m_helpRequested)
70  return true;
71 
72  string tempString1;
73  ossimArgumentParser::ossimParameter stringParam1(tempString1);
74  string tempString2;
75  ossimArgumentParser::ossimParameter stringParam2(tempString2);
76  string tempString3;
77  ossimArgumentParser::ossimParameter stringParam3(tempString3);
78  string tempString4;
79  ossimArgumentParser::ossimParameter stringParam4(tempString4);
80  double tempDouble1;
81  ossimArgumentParser::ossimParameter doubleParam1(tempDouble1);
82  double tempDouble2;
83  ossimArgumentParser::ossimParameter doubleParam2(tempDouble2);
84  vector<ossimString> paramList;
85 
86  ossim_uint32 readerPropIdx = 0;
87  ossim_uint32 writerPropIdx = 0;
88  ostringstream keys;
89 
90  if ( ap.read("--bbox", stringParam1, stringParam2, stringParam3, stringParam4))
91  {
92  ostringstream ostr;
93  ostr<<tempString1<<" "<<tempString2<<" "<<tempString3<<" "<<tempString4<<ends;
94  m_kwl.addPair( string(BBOX_KW), ostr.str() );
95  }
96  if ( ap.read("-e", stringParam1) || ap.read("--entry", stringParam1) )
97  m_kwl.addPair( string(ossimKeywordNames::ENTRY_KW), tempString1 );
98 
99  if ( ap.read("--geom", stringParam1))
100  {
101  ossimString formatStr (tempString1);
102  formatStr.upcase();
103  if (formatStr == "OGEOM")
105  else if (formatStr == "DG")
106  m_geomFormat = DG;
107  else if (formatStr == "JSON")
108  m_geomFormat = JSON;
109  else if (formatStr == "XML")
110  m_geomFormat = XML;
111  else
112  {
113  ostringstream errMsg;
114  errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] Unknown geometry format <"
115  <<formatStr<<"> specified. Aborting." << endl;
116  throw ossimException( errMsg.str() );
117  }
118  }
120 
121  return true;
122 }
123 
125 {
127 
128  // Init chain with handler:
129  ostringstream key;
131  ossimFilename fname = m_kwl.findKey(key.str());
133  ossimImageHandlerRegistry::instance()->open(fname, true, false);
134  if (!handler)
135  {
136  ostringstream errMsg;
137  errMsg<<"ERROR: ossimSubImageTool ["<<__LINE__<<"] Could not open <"<<fname<<">"<<ends;
138  throw ossimException(errMsg.str());
139  }
140 
141  // Look for the entry keyand set it:
142  ossim_uint32 entryIndex = 0;
144  if (os)
145  entryIndex = os.toUInt32();
146  if (!handler->setCurrentEntry( entryIndex ))
147  {
148  ostringstream errMsg;
149  errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] Entry " << entryIndex << " out of range!" << endl;
150  throw ossimException( errMsg.str() );
151  }
152  m_procChain->add(handler.get());
153 
154  // And finally the bounding rect:
155  ossimString lookup = m_kwl.find(BBOX_KW);
156  lookup.trim();
157  vector<ossimString> substrings = lookup.split(", ", true);
158  if (substrings.size() != 4)
159  {
160  ostringstream errMsg;
161  errMsg << "ossimSubImageTool ["<<__LINE__<<"] Incorrect number of values specified for bbox!";
162  throw( ossimException(errMsg.str()) );
163  }
164 
165  int ulx = substrings[0].toInt32();
166  int uly = substrings[1].toInt32();
167  int lrx = substrings[2].toInt32();
168  int lry = substrings[3].toInt32();
169 
170  // Check for swap:
171  if ( ulx > lrx )
172  {
173  int tmpF = ulx;
174  ulx = lrx;
175  lrx = tmpF;
176  }
177  if ( uly > lry )
178  {
179  int tmpF = uly;
180  uly = lry;
181  lry = tmpF;
182  }
183 
184  // Use of view rect here is same as image space since there is no renderer:
185  m_aoiViewRect.set_ul(ossimIpt(ulx, uly));
186  m_aoiViewRect.set_lr(ossimIpt(lrx, lry));
187  m_needCutRect = true;
188 
189  finalizeChain();
190 }
191 
193 {
194  // Compute RPC representation of subimage:
196  if (!inputGeom || !inputGeom->getProjection())
197  {
198  ostringstream errMsg;
199  errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] Null projection returned for input "
200  "image!" << endl;
201  throw ossimException( errMsg.str() );
202  }
203 
204  ossimRefPtr<ossimProjection> inputProj = inputGeom->getProjection();
206  ossimRefPtr<ossimRpcSolver> solver = new ossimRpcSolver(false);
207  bool converged = false;
208 
209  // If the input projection itself is an RPC, just copy it. No solving required:
210  ossimRpcModel* inputRpc = dynamic_cast<ossimRpcModel*>(inputGeom->getProjection());
211  if (inputRpc)
212  rpc = inputRpc;
213  else
214  {
215  converged = solver->solve(m_aoiViewRect, inputGeom.get());
216  rpc = solver->getRpcModel();
217  }
218 
219  // The RPC needs to be shifted in image space so that it will work in the subimage coordinates:
221  m_geom = new ossimImageGeometry(nullptr, rpc.get());
223  ossimKeywordlist kwl;
224  m_geom->saveState(kwl);
225 
226  bool success = ossimChipProcTool::execute();
227  if (!success)
228  return false;
229 
230  // Need to save the subimage RPC data:
231  bool write_ok = false;
232  ossimFilename geomFile (m_productFilename);
233  if (m_geomFormat == OGEOM) // Default case if none specified
234  {
235  geomFile.setExtension("geom");
236  write_ok = kwl.write(geomFile);
237  }
238  else if (m_geomFormat == JSON)
239  {
240 #if OSSIM_HAS_JSONCPP
241  geomFile.setExtension("json");
242  ofstream jsonStream (geomFile.string());
243  if (!jsonStream.fail())
244  {
245  // Note that only the model/projection is saved here, not the full ossimImageGeometry that
246  // contains the subimage shift transform. So need to cheat and add the shift to the RPC
247  // line and sample offsets:
248  write_ok = rpc->toJSON(jsonStream);
249  jsonStream.close();
250  }
251 #else
252  ostringstream errMsg;
253  errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] JSON geometry output requested but JSON is not "
254  "available in this build! <" << endl;
255  throw ossimException( errMsg.str() );
256 #endif
257  }
258  else if (m_geomFormat == DG)
259  {
260  geomFile.setExtension("RPB");
261  ofstream rpbStream (geomFile.string());
262  if (!rpbStream.fail())
263  {
264  write_ok = rpc->toRPB(rpbStream);
265  rpbStream.close();
266  }
267  }
268  else if (m_geomFormat == XML)
269  {
270  geomFile.setExtension("xml");
271  ossimXmlDocument xmlDocument;
272  xmlDocument.fromKwl(kwl);
273  write_ok = xmlDocument.write(geomFile);
274  }
275 
276  if (write_ok)
277  ossimNotify(ossimNotifyLevel_INFO) << "Wrote geometry file to <"<<geomFile<<">.\n" << endl;
278  else
279  {
280  ossimNotify(ossimNotifyLevel_FATAL) << "Error encountered writing output RPC geometry file."
281  << std::endl;
282  return false;
283  }
284 
285  return true;
286 }
287 
std::string getApplicationName() const
return the application name, as specified by argv[0]
const char * BBOX_KW
void addCommandLineOption(const ossimString &option, const ossimString &explanation)
static ossimString upcase(const ossimString &aString)
Definition: ossimString.cpp:34
ossimRefPtr< ossimImageGeometry > m_geom
std::basic_ostringstream< char > ostringstream
Class for char output memory streams.
Definition: ossimIosFwd.h:35
static const char * OUTPUT_FILE_KW
virtual ossimImageHandler * open(const ossimFilename &fileName, bool trySuffixFirst=true, bool openOverview=true) const
open that takes a filename.
Represents serializable keyword/value map.
const std::string & findKey(const std::string &key) const
Find methods that take std::string(s).
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if not defined...
bool write(const ossimFilename &file)
bool m_helpRequested
Definition: ossimTool.h:150
const char * find(const char *key) const
bool read(const std::string &str)
search for an occurance of a string in the argument list, on sucess remove that occurance from the li...
ossimKeywordlist m_kwl
Definition: ossimTool.h:148
const ossimIpt & ul() const
Definition: ossimIrect.h:274
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
void addPair(const std::string &key, const std::string &value, bool overwrite=true)
ossim_uint32 toUInt32() const
void setCommandLineUsage(const ossimString &explanation)
RpcGeomFormat m_geomFormat
ossimApplicationUsage * getApplicationUsage()
void setImageSize(const ossimIpt &size)
virtual bool write(const char *file, const char *comment=0) const
Methods to dump the ossimKeywordlist to a file on disk.
ossimIpt size() const
Definition: ossimIrect.h:510
const ossimRefPtr< ossimRpcModel > getRpcModel() const
Fetches the solved-for RPC model.
ossimRefPtr< ossimImageChain > m_procChain
void set_ul(const ossimIpt &pt)
Definition: ossimIrect.h:589
bool solve(const ossimDrect &aoiBounds, ossimImageGeometry *geom, const double &pixel_tolerance=0.5)
Similar to the other solve methods except that the final grid size is established iteratively so that...
ossimFilename m_productFilename
virtual void setUsage(ossimArgumentParser &ap)
Initializes the aurgument parser with expected parameters and options.
Definition: ossimTool.cpp:41
virtual void finalizeChain()
Called after initProcessingChain() to append common items to the processing chain.
void fromKwl(const ossimKeywordlist &kwl)
unsigned int ossim_uint32
void processRemainingArgs(ossimArgumentParser &ap)
Intended to be called after derived class has picked off its own options from the parser...
ossimString trim(const ossimString &valueToTrim=ossimString(" \\)) const
this will strip lead and trailing character passed in.
virtual void setUsage(ossimArgumentParser &ap)
Initializes the aurgument parser with expected parameters and options.
static const char * DESCRIPTION
Used by ossimUtilityFactory.
virtual bool initialize(ossimArgumentParser &ap)
Initializes from command line arguments.
Definition: ossimTool.cpp:58
virtual bool add(ossimConnectableObject *source)
Will return true or false if an image source was added to the chain.
void setImageOffset(const ossimDpt &offset_to_chip_ul)
Allows setting an offset to a subimage while using the coefficients of a full-image model...
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
virtual bool execute()
Writes product to output file if applicable.
static const char * ENTRY_KW
const ossimProjection * getProjection() const
Access methods for projection (may be NULL pointer).
void set_lr(const ossimIpt &pt)
Definition: ossimIrect.h:623
void setDescription(const ossimString &desc)
bool toJSON(std::ostream &json) const
Serializes RPC to JSON format.
This currently only support Rational poilynomial B format.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Saves the transform (if any) and projection (if any) states to the KWL.
static ossimImageHandlerRegistry * instance()
std::basic_ofstream< char > ofstream
Class for char output file streams.
Definition: ossimIosFwd.h:47
static const char * IMAGE_FILE_KW
ossimFilename & setExtension(const ossimString &e)
Sets the extension of a file name.
virtual bool setCurrentEntry(ossim_uint32 entryIdx)
virtual bool initialize(ossimArgumentParser &ap)
Initializes from command line arguments.
virtual bool execute()
Performs the actual product write.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
bool toRPB(std::ostream &out) const
Serialize to WorldView-style .RPB file to the stream provided.
const std::string & string() const
Definition: ossimString.h:414