OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimAtbController.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // AUTHOR: Oscar Kramer (okramer@imagelinks.com)
6 //
7 // DESCRIPTION: Contains implementation of class ossimAtbController. This is the
8 // controller managing the tonal balancing process. It's product is the
9 // initialization of specialized remappers in each of the mosaic's member
10 // images that results in a tonally balanced mosaic.
11 //
12 // LIMITATIONS: None.
13 //
14 //*****************************************************************************
15 // $Id: ossimAtbController.cpp 17195 2010-04-23 17:32:18Z dburken $
16 
18 
20 
21 #include <stdio.h>
28 
29 //***
30 // Define Trace flags for use within this file:
31 //***
32 #include <ossim/base/ossimTrace.h>
33 static ossimTrace traceExec ("ossimAtbController:exec");
34 static ossimTrace traceDebug ("ossimAtbController:debug");
35 
36 static const ossimIpt DEFAULT_GRID_SPACING (64,64);
37 static const char* DEFAULT_ATB_REMAP_ENGINE = "ossimHsvGridRemapEngine";
38 
39 //*****************************************************************************
40 // CONSTRUCTOR: ossimAtbController()
41 //
42 //*****************************************************************************
44  :
45  ossimConnectableObject(NULL, 0, 0, false, true),
46  theContainer (0),
47  theGridRemapEngine (0),
48  theGridSpacing (DEFAULT_GRID_SPACING)
49 {
50  static const char MODULE[] = "ossimAtbController Default Constructor";
51  if (traceExec()) CLOG << "entering..." << endl;
52 
53  //***
54  // Instantiate a default remap engine:
55  //***
57  = ossimGridRemapEngineFactory::create(DEFAULT_ATB_REMAP_ENGINE);
58 
59  if (traceExec()) CLOG << "returning..." << endl;
60 }
61 
62 //*****************************************************************************
63 // CONSTRUCTOR: ossimAtbController()
64 //
65 //*****************************************************************************
67  ossimGridRemapEngine* engine)
68  :
69  ossimConnectableObject(NULL, 0, 0, false, true),
70  theContainer (0),
71  theGridRemapEngine (0),
72  theGridSpacing (DEFAULT_GRID_SPACING)
73 {
74  static const char MODULE[] = "ossimAtbController Constructor #1";
75  if (traceExec()) CLOG << "entering..." << endl;
76 
77  initializeWithCombiner(combiner, engine);
78 
79  if (traceExec()) CLOG << "returning..." << endl;
80 }
81 
82 //*****************************************************************************
83 // CONSTRUCTOR: ossimAtbController()
84 //
85 //*****************************************************************************
87  :
88  theContainer (0),
89  theGridRemapEngine (0),
90  theGridSpacing (DEFAULT_GRID_SPACING)
91 {
92  static const char MODULE[] = "ossimAtbController Constructor #1";
93  if (traceExec()) CLOG << "entering..." << endl;
94 
95  //***
96  // Assign default engine if non provided:
97  //***
98  if (engine)
99  {
100  theGridRemapEngine = engine;
101  }
102  else
103  {
105  = ossimGridRemapEngineFactory::create(DEFAULT_ATB_REMAP_ENGINE);
106  }
107 
108  if (traceExec()) CLOG << "returning..." << endl;
109 }
110 
111 //*****************************************************************************
112 // DESTRUCTOR: ~ossimAtbController()
113 //
114 // The remappers are left behind, owned by the combiner's container. If the
115 // combiner was owned by something other than a container (see initialize()),
116 // then this controller will assume ownership of the allocated remappers and
117 // delete them here.
118 //
119 //*****************************************************************************
121 {
122  theContainer = 0;
123  theGridRemapEngine = 0;;
124 }
125 
126 //*****************************************************************************
127 // METHOD: ossimAtbController::initializeWithCombiner()
128 //
129 //*****************************************************************************
131  ossimGridRemapEngine* engine)
132 {
133  static const char MODULE[] = "ossimAtbController::initializeWithCombiner()";
134  if (traceExec()) CLOG << "entering..." << endl;
135 
136  //***
137  // Assign default engine if non provided:
138  //***
139  if (engine)
141  else
143  = ossimGridRemapEngineFactory::create(DEFAULT_ATB_REMAP_ENGINE);
144 
145  //***
146  // This is the first combiner initializing the controller. The combiner
147  // will have all of the input sources connected already. We attach to
148  // these:
149  //***
151 
152  //***
153  // Need to scan the input connections of the combiner and insert a
154  // remapper if there is not one already at the end of the input chain:
155  //***
156  vector<ossimConnectableObject*> del_list;
157  vector<ossimConnectableObject*> add_list;
158  int numInputs = combiner->getNumberOfInputs();
159  for(int i=0; i<numInputs; i++)
160  {
162  combiner->getInput(i));
163 
164  if (input_image)
165  {
167  input_image);
168  if (remapper)
169  {
170  //***
171  // Remapper already present, set its remap engine to this
172  // controller's remap engine:
173  //***
175  }
176 
177  else
178  {
179  //***
180  // Need to instantiate remapper:
181  //***
182  remapper = new ossimGridRemapSource(input_image,
184  if (theContainer.valid())
185  theContainer->addChild(remapper);
186 
187  add_list.push_back(remapper);
188  del_list.push_back(input_image);
189  }
190 
191  connectMyInputTo(remapper);
192  }
193  }
194 
195  //***
196  // Need to delete the old inputs and add the new remappers to the
197  // combiner's input list:
198  //***
199  vector<ossimConnectableObject*>::iterator add_iter = add_list.begin();
200  vector<ossimConnectableObject*>::iterator del_iter = del_list.begin();
201  while (add_iter != add_list.end())
202  {
203  (*add_iter)->connectMyInputTo(*del_iter);
204  combiner->disconnect(*del_iter);
205  combiner->connectMyInputTo(*add_iter);
206  add_iter++;
207  del_iter++;
208  }
209  combiner->initialize();
210 
211  if (traceExec()) CLOG << "returning..." << endl;
212 }
213 
214 //*****************************************************************************
215 // METHOD: ossimAtbController::enableImage()
216 //
217 // Enable an image in the mosaic to be included the tonal balancing process.
218 //
219 //*****************************************************************************
220 bool ossimAtbController::enableImage(unsigned int index)
221 {
222  if (index >= getNumberOfInputs())
223  return false;
224 
225  ossimSource* remapper = PTR_CAST(ossimSource,
226  getInput(index));
227  if (remapper)
228  remapper->enableSource();
229 
230  return true;
231 }
232 
233 //*****************************************************************************
234 // METHOD: ossimAtbController::disableImage()
235 //
236 // Disable an image in the mosaic from the tonal balancing process.
237 //
238 //*****************************************************************************
239 bool ossimAtbController::disableImage(unsigned int index)
240 {
241  if (index >= getNumberOfInputs())
242  return false;
243 
244  ossimSource* remapper = PTR_CAST(ossimSource,
245  getInput(index));
246  if (remapper)
247  remapper->disableSource();
248 
249  return true;
250 }
251 
252 //*****************************************************************************
253 // METHOD: ossimAtbController::lockImage()
254 //
255 // Locks a particular source for adjustment. A locked image
256 // effectively defines the target values for all overlapping imagery.
257 //
258 //*****************************************************************************
259 bool ossimAtbController::lockImage(unsigned int index)
260 {
261  if (index >= getNumberOfInputs())
262  return false;
263 
265  getInput(index));
266  if (remapper)
267  remapper->lock();
268 
269  return true;
270 }
271 
272 
273 //*****************************************************************************
274 // METHOD: ossimAtbController::unlockImage()
275 //
276 // Unlocks a particular source for allowing its adjustment.
277 //
278 //*****************************************************************************
279 bool ossimAtbController::unlockImage(unsigned int index)
280 {
281  if (index >= getNumberOfInputs())
282  return false;
283 
285  getInput(index));
286  if (remapper)
287  remapper->lock();
288 
289  return true;
290 }
291 
292 
293 //*****************************************************************************
294 // METHOD: ossimAtbController::execute()
295 //
296 //*****************************************************************************
298 {
299  static const char MODULE[] = "ossimAtbController::execute()";
300  if (traceExec()) CLOG << "entering..." << endl;
301 
302  setPercentComplete(0.0);
303 
304  ossimGridRemapSource* source;
305 
306  //***
307  // First verify that all objects needed are initialized:
308  //***
309  int num_images = getNumberOfInputs();
310  if ((!theGridRemapEngine) || (num_images < 2))
311  {
312  CLOG << "WARNING: execute method was called but the controller has not "
313  << "been properly initialized. Ignoring request..." << endl;
314  if (traceExec()) CLOG << "returning..." << endl;
315  return false;
316  }
317 
318  //***
319  // establish the remap grids:
320  //***
322  setPercentComplete(10.0);
323 
324  //***
325  // Establish grid of matchpoints:
326  //***
327  int numPoints = 0;
328  ossimDpt mp_view_pt;
329  theMatchPoints.clear();
330  for (mp_view_pt.line = theBoundingRect.ul().line;
331  mp_view_pt.line <= theBoundingRect.lr().line;
332  mp_view_pt.line += theGridSpacing.line)
333  {
334  for (mp_view_pt.samp = theBoundingRect.ul().samp;
335  mp_view_pt.samp <= theBoundingRect.lr().samp;
336  mp_view_pt.samp += theGridSpacing.samp)
337  {
338  ossimAtbMatchPoint* mp = new ossimAtbMatchPoint(mp_view_pt,
340  theMatchPoints.push_back(mp);
341  numPoints++;
342  }
343  }
344 
345  //***
346  // Loop over each matchpoint to determine which images contribute statistics:
347  //***
348  setPercentComplete(20.0);
349  for (int mp=0; mp<numPoints; mp++)
350  {
351  ossimDpt view_point (theMatchPoints[mp]->viewPoint());
352 
353  //***
354  // Loop over each image source to check if point lies inside its bounding
355  // rectangle, and add its contribution to the matchpoint's collection:
356  //***
357  for (int src=0; src<num_images; src++)
358  {
359  source = PTR_CAST(ossimGridRemapSource, getInput(src));
360  if (source)
361  {
362  ossimDrect image_rect (source->getBoundingRect());
363  if (image_rect.pointWithin(view_point))
364  theMatchPoints[mp]->addImage(source);
365  }
366  }
367 
368  setPercentComplete(20.0 + 50.0*(mp/numPoints));
369  }
370 
371  //***
372  // All contributors have been included in all matchpoints' collections.
373  // Compute the target pixel value for each matchpoint and communicate it
374  // to the corresponding remappers:
375  //***
376  for (int mp=0; mp<numPoints; mp++)
377  {
378  setPercentComplete(70.0 + 30.0*(mp/numPoints));
379  theMatchPoints[mp]->assignRemapValues();
380  }
381 
382  //***
383  // Finally, enable the remappers:
384  //***
385  for (int src=0; src<num_images; src++)
386  {
387  source = PTR_CAST(ossimGridRemapSource, getInput(src));
388  if (source)
389  source->enableSource();
390  }
391  setPercentComplete(100.0);
392 
393  if (traceExec()) CLOG << "returning..." << endl;
394  return true;
395 }
396 
397 //*****************************************************************************
398 // METHOD: ossimAtbController::abort()
399 //
400 //*****************************************************************************
402 {
403  static const char MODULE[] = "ossimAtbController::abort()";
404  if (traceExec()) CLOG << "entering..." << endl;
405 
406  CLOG << "NOTICE: this method not yet implemented." << endl;
407 
408  if (traceExec()) CLOG << "returning..." << endl;
409 }
410 
411 //*****************************************************************************
412 // METHOD: ossimAtbController::saveState()
413 //
414 //*****************************************************************************
416 {
417  static const char MODULE[] = "ossimAtbController::saveState()";
418  if (traceExec()) CLOG << "entering..." << endl;
419 
420  CLOG << "NOTICE: this method not yet implemented." << endl;
421 
422  if (traceExec()) CLOG << "returning..." << endl;
423  return true;
424 }
425 
426 //*****************************************************************************
427 // METHOD: ossimAtbController::loadState()
428 //
429 //*****************************************************************************
431 {
432  static const char MODULE[] = "ossimAtbController::loadState()";
433  if (traceExec()) CLOG << "entering..." << endl;
434 
435  CLOG << "NOTICE: this method not yet implemented." << endl;
436 
437  if (traceExec()) CLOG << "returning..." << endl;
438  return true;
439 }
440 
441 
442 //*****************************************************************************
443 // METHOD: ossimAtbController::setKernelSize(N)
444 //
445 // Hook to set the size of the kernel used by all point sources in computing
446 // their mean pixel value. The kernels will be resized to NxN.
447 //
448 //*****************************************************************************
450 {
451  static const char MODULE[] = "ossimAtbController::setKernelSize(N)";
452  if (traceExec()) CLOG << "entering..." << endl;
453 
454  vector<ossimRefPtr<ossimAtbMatchPoint> >::iterator mpi = theMatchPoints.begin();
455  while (mpi != theMatchPoints.end())
456  (*mpi)->setKernelSize(side_size);
457 
458  if (traceExec()) CLOG << "returning..." << endl;
459  return;
460 }
461 
462 
463 //*****************************************************************************
464 // PRIVATE METHOD: ossimAtbController::initializeRemappers()
465 //
466 //*****************************************************************************
468 {
469  static const char MODULE[] = "ossimAtbController::initializeRemappers()";
470  if (traceExec()) CLOG << "entering..." << endl;
471 
472  int num_images = getNumberOfInputs();
473 
474  //***
475  // Fetch the overall mosaic bounding rect:
476  //***
478  getInput(0));
479  theBoundingRect = remapper->getBoundingRect();
480  for (int src=1; src<num_images; src++)
481  {
483  }
484 
485  //***
486  // Loop over each contribution image source chain to fetch each image
487  // bounding rect:
488  //***
489  double dx_ul, dy_ul, dx_lr, dy_lr;
490  double grid_ul_x, grid_ul_y, grid_lr_x, grid_lr_y;
491  for (int src=0; src<num_images; src++)
492  {
493  remapper = PTR_CAST(ossimGridRemapSource, getInput(src));
494  ossimDrect image_rect (remapper->getBoundingRect());
495 
496  //***
497  // Arrive at the number of grid posts from mosaic origin to image's grid
498  // UL and LR corners:
499  //***
500  dx_ul = (image_rect.ul().x - theBoundingRect.ul().x)/theGridSpacing.x;
501  dy_ul = (image_rect.ul().y - theBoundingRect.ul().y)/theGridSpacing.y;
502  dx_lr = (image_rect.lr().x - theBoundingRect.lr().x)/theGridSpacing.x;
503  dy_lr = (image_rect.lr().y - theBoundingRect.lr().y)/theGridSpacing.y;
504 
505  //***
506  // Establish the view coordinates for the adjusted image grid:
507  //***
508  grid_ul_x = theBoundingRect.ul().x + ceil(dx_ul)*theGridSpacing.x;
509  grid_ul_y = theBoundingRect.ul().y + ceil(dy_ul)*theGridSpacing.y;
510  grid_lr_x = theBoundingRect.lr().x + floor(dx_lr)*theGridSpacing.x;
511  grid_lr_y = theBoundingRect.lr().y + floor(dy_lr)*theGridSpacing.y;
512 
513  //***
514  // Have the remapper initialize a new grid with the given rectangle and
515  // spacing:
516  //***
517  ossimDrect grid_rect (grid_ul_x, grid_ul_y, grid_lr_x, grid_lr_y);
518  remapper->initialize(grid_rect, theGridSpacing);
519  }
520 
521  if (traceExec()) CLOG << "returning..." << endl;
522  return;
523 }
524 
525 //*****************************************************************************
526 // METHOD: ossimAtbController::setGridRemapEngine()
527 //
528 //*****************************************************************************
530 {
531  static const char MODULE[] = "ossimAtbController::setGridRemapEngine()";
532  if (traceExec()) CLOG << "entering..." << endl;
533 
534  theGridRemapEngine = engine;
535 
536  //***
537  // Communicate the new engine to all member's interested:
538  //***
539  ossimGridRemapSource* remapper;
540  ossimConnectableObject::ConnectableObjectList::iterator iter=theInputObjectList.begin();
541  while (iter != theInputObjectList.end())
542  {
543  remapper = PTR_CAST(ossimGridRemapSource, (*iter).get());
544  remapper->setRemapEngine(engine);
545  iter++;
546  }
547 
548  vector<ossimRefPtr<ossimAtbMatchPoint> >::iterator match_point = theMatchPoints.begin();
549  while (match_point != theMatchPoints.end())
550  {
551  (*match_point)->setGridRemapEngine(engine);
552  match_point++;
553  }
554 
555  if (traceExec()) CLOG << "returning..." << endl;
556  return;
557 }
558 
559 
560 //*****************************************************************************
561 // METHOD: ossimAtbController::canConnectMyInputTo()
562 //
563 //*****************************************************************************
565  const ossimConnectableObject* object) const
566 {
567  return (object&& PTR_CAST(ossimGridRemapSource, object));
568 }
static ossimGridRemapEngine * create(const char *spec)
virtual ossimObject * dup() const =0
void setRemapEngine(ossimGridRemapEngine *engine)
const ossimObject * getOwner() const
Fetches the current owner, most likely a container but not limited to one.
virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const
This will return the bounding rect of the source.
ossimGridRemapEngine * theGridRemapEngine
ossimRefPtr< ossimConnectableContainer > theContainer
#define CLOG
Definition: ossimTrace.h:23
bool disableImage(unsigned int index)
virtual void disconnect(ossimConnectableObject *object=0)
Will disconnect the object passed in.
This will be a base for all combiners.
Represents serializable keyword/value map.
bool valid() const
Definition: ossimRefPtr.h:75
virtual bool saveState(ossimKeywordlist &kwl) const
double samp
Definition: ossimDpt.h:164
virtual bool canConnectMyInputTo(ossim_int32 myInputIndex, const ossimConnectableObject *object) const
const ossimDpt & ul() const
Definition: ossimDrect.h:339
double y
Definition: ossimDpt.h:165
bool unlockImage(unsigned int index)
virtual void disableSource()
Definition: ossimSource.cpp:89
virtual void setPercentComplete(double percentComplete)
ossimDrect combine(const ossimDrect &rect) const
Definition: ossimDrect.h:826
ossimConnectableObject * getInput(ossim_uint32 index=0)
returns the object at the specified index.
void initializeWithCombiner(ossimImageCombiner *combiner, ossimGridRemapEngine *engine=0)
double line
Definition: ossimDpt.h:165
RTTI_DEF2(ossimAtbController, "ossimAtbController", ossimProcessInterface, ossimConnectableObject)
#define PTR_CAST(T, p)
Definition: ossimRtti.h:321
virtual void enableSource()
Definition: ossimSource.cpp:84
void setKernelSize(int side_size)
virtual ossim_int32 connectMyInputTo(ossimConnectableObject *inputObject, bool makeOutputConnection=true, bool createEventFlag=true)
Will try to connect this objects input to the passed in object.
ConnectableObjectList theInputObjectList
Holds a list of input objects.
virtual bool addChild(ossimConnectableObject *attachableObject)
ossim_int32 samp
Definition: ossimIpt.h:141
ossim_int32 y
Definition: ossimIpt.h:142
virtual ossim_uint32 getNumberOfInputs() const
Returns the number of input objects.
double x
Definition: ossimDpt.h:164
ossim_int32 line
Definition: ossimIpt.h:142
ossim_int32 x
Definition: ossimIpt.h:141
std::vector< ossimRefPtr< ossimAtbMatchPoint > > theMatchPoints
void setGridRemapEngine(ossimGridRemapEngine *engine)
virtual void initialize(const ossimDrect &uv_rect, const ossimDpt &grid_spacing)
const ossimDpt & lr() const
Definition: ossimDrect.h:341
virtual bool loadState(const ossimKeywordlist &kwl)
bool enableImage(unsigned int index)
bool lockImage(unsigned int index)
int ossim_int32