Window.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 #ifndef DRAIN_WINDOW_H_
32 #define DRAIN_WINDOW_H_
33 
34 #include "drain/util/Frame.h"
35 #include "drain/util/Functor.h"
36 #include "drain/util/FunctorBank.h"
37 #include "drain/util/Static.h"
38 #include "ImageView.h"
39 #include "ImageTray.h"
40 #include "CoordinateHandler.h"
41 
42 
43 namespace drain
44 {
45 
46 namespace image
47 {
48 
50 
56 class WindowConfig { //: public BeanLike { // { // TODO:
57 
58 public:
59 
60  template <class FT=IdentityFunctor>
61  inline
62  WindowConfig(int width=1, int height=0, const FT & functor = FT()) : frame(width,height ? height : width){
63  key = functor.getName();
64  functorParameters.importCastableMap(functor.getParameters());
65  };
66 
67  inline
68  WindowConfig(const WindowConfig & conf) :
69  // BeanLike(conf),
70  frame(conf.frame),
71  key(conf.key)
72  //clonerBase(conf.clonerBase)
73  {
74  //ftorMapEntry = getFunctorBank().find2<IdentityFunctor>(); // .getMap().begin();
75  functorParameters.importCastableMap(conf.functorParameters); // maybe different from cloned ones!
76  //parameters.copyStruct(conf.parameters, conf, *this);
77  };
78 
79 
80  // Width and height of the window, in pixels.
81  Frame2D<int> frame;
82 
83  // Return width of the window, in pixels.
84  inline
85  int getWidth() const {
86  return frame.width;
87  };
88 
89  // Return height of the window, in pixels.
90  inline
91  int getHeight() const {
92  return frame.height;
93  };
94 
95  typedef typename FunctorBank::map_t fmap_t;
96  typedef typename fmap_t::const_iterator ftor_entry_t;
97 
98  VariableMap functorParameters;
99 
101 
103 
107  inline
108  void setFunctor(const std::string & ftorKey){
109 
110  FunctorBank & functorBank = getFunctorBank();
111  const std::string k = functorBank.resolve(ftorKey); // empty ok, idFtor!
112 
113  const fmap_t & m = functorBank.getMap();
114  ftor_entry_t it = m.find(k);
115  if (it != m.end()){
116  key = it->first;
117  }
118  else {
119  throw std::runtime_error(ftorKey + '[' + k + "]: no such entry, using IdentityFunctor");
120  }
121  };
122 
123 
124  // Needed?
125  inline
126  const fmap_t::key_type & getFunctorName() const {
127  return key;
128  };
129 
130 
131 
133  inline
134  const VariableMap & getFunctorParams() const{
135  return functorParameters;
136  };
137 
138 
139 protected:
140 
141  std::string key;
142 
143 
144 };
145 
146 std::ostream & operator<<(std::ostream & ostr, const WindowConfig & conf);
147 
148 
149 DRAIN_TYPENAME(WindowConfig);
150 
151 
153 
157 
158 public:
159 
160  virtual inline
161  ~WindowCoreBase(){};
162 
163  virtual inline
164  void setSrcFrame(const ImageFrame & src){
165  ImageTray<const Channel> srcTray; //(src);
166  srcTray.setChannels(src);
167  setSrcFrames(srcTray);
168  }
169 
170  virtual
171  void setSrcFrames(const ImageTray<const Channel> & srcTray) = 0;
172 
173 
174 
175  virtual inline
176  void setDstFrame(ImageFrame & dst){
177  ImageTray<Channel> dstTray; //(dst);
178  dstTray.setChannels(dst);
179  setDstFrames(dstTray);
180  }
181 
182  virtual
183  void setDstFrames(ImageTray<Channel> & dstTray) = 0;
184 
185 
186 };
187 
188 
190 
194 class WindowCore : public WindowCoreBase { // rename BasicWindow
195 
196 public:
197 
198  ImageView src;
199  ImageView dst;
200 
202  virtual inline
203  void setSrcFrames(const ImageTray<const Channel> & srcTray){
204 
205  Logger mout(getImgLog(), "WindowCore", __FUNCTION__);
206 
207  if (srcTray.empty()){
208  mout.error("src: no channels" );
209  return;
210  }
211 
212  if (srcTray.size() > 1){
213  mout.warn("src: multiple channels" );
214  }
215 
216  //mout.warn("scale:" , srcTray.get(0).getScaling() );
217  //mout.note("scale:" , srcTray.get(0).getChannel(0).getScaling() );
218  src.setView(srcTray.get(0));
219  //mout.warn("scale:" , src.getScaling() );
220 
221  if (!srcTray.alpha.empty()){
222  setSrcFrameWeight(srcTray.getAlpha(0));
223  }
224 
225  };
226 
227 
229  virtual inline
230  void setDstFrames(ImageTray<Channel> & dstTray){
231 
232  Logger mout(getImgLog(), "WindowCore", __FUNCTION__);
233 
234  if (dstTray.empty()){
235  mout.error("dst: no channels" );
236  return;
237  }
238 
239  if (dstTray.size() > 1){
240  mout.warn("dst: multiple channels" );
241  }
242 
243  dst.setView(dstTray.get(0));
244 
245  if (!dstTray.alpha.empty()){
246  setDstFrameWeight(dstTray.getAlpha(0));
247  }
248 
249  };
250 
251  // Optional
252  virtual inline
253  void setSrcFrameWeight(const ImageFrame & srcW){
254  Logger mout(getImgLog(), "WindowCore", __FUNCTION__);
255  mout.warn("Not implemented" );
256  };
257 
258  virtual inline
259  void setDstFrameWeight(ImageFrame & dstW){
260  Logger mout(getImgLog(), "WindowCore", __FUNCTION__);
261  mout.warn("Not implemented" );
262  };
263 
264 };
265 
266 DRAIN_TYPENAME(WindowCore);
267 
269 
270 public:
271 
272  WeightedWindowCore(){};
273 
274  virtual
275  ~WeightedWindowCore(){};
276 
277 
278  virtual inline
279  void setSrcFrameWeight(const ImageFrame & srcW){
280  srcWeight.setView(srcW);
281  };
282 
283  virtual inline
284  void setDstFrameWeight(ImageFrame & dstW){
285  dstWeight.setView(dstW);
286  };
287 
288  // toOStr() ?
289 
290 // protected:
291 
292  ImageView srcWeight;
293 
294  ImageView dstWeight;
295 
296 
297 };
298 
299 DRAIN_TYPENAME(WeightedWindowCore);
300 
301 
303 
304 public:
305 
307 
308  virtual
310 
311  ImageTray<const Channel> srcTray;
312  ImageTray<Channel> dstTray;
313 
314  virtual inline
315  void setSrcFrame(const Channel & srcChannel){// ALERT! Unintentional Shadow (arg: ImageFrame -> Channel)
316  ImageTray<const Channel> srcChannels;
317  srcChannels.set(srcChannel);
318  setSrcFrames(srcChannels);
319  }
320 
321  virtual inline
322  void setDstFrame(Channel & dstChannel){ // ALERT! Unintentional Shadow (arg: ImageFrame -> Channel)
323  ImageTray<Channel> dstChannels;
324  dstChannels.set(dstChannel);
325  setDstFrames(dstChannels);
326  }
327 
329  void setSrcFrames(const ImageTray<const Channel> & srcTray){
330 
331  drain::Logger mout(getImgLog(), "MultiChannelWindowCore", __FUNCTION__);
332 
333  mout.debug("setting srcTray" );
334 
335  //this->srcTray.clear();
336  this->srcTray.copy(srcTray);
337  if (!srcTray.empty()){
338  this->src.setView(srcTray.get());
339  }
340  else {
341  mout.warn("setting empty srcTray" );
342  }
343 
344 
345  if (!srcTray.alpha.empty()){
346  this->srcWeight.setView(srcTray.alpha.get());
347  }
348  else {
349  mout.debug("no srcTray.alpha" );
350  }
351 
352  mout.debug2(this->srcTray );
353 
354  };
355 
358 
359  drain::Logger mout(getImgLog(), "MultiChannelWindowCore", __FUNCTION__);
360 
361  mout.debug("setting dstTray" );
362 
363  //this->dstTray.clear();
364  this->dstTray.copy(dstTray);
365  if (!dstTray.empty()){
366  this->dst.setView(this->dstTray.get());
367  }
368  else {
369  mout.warn("setting empty dstTray" );
370  }
371 
372 
373  if (!dstTray.alpha.empty()){
374  this->dstWeight.setView(this->dstTray.alpha.get());
375  }
376  else {
377  mout.debug("no srcTray.alpha" );
378  // mout.warn("setting empty srcTray" );
379  }
380 
381  mout.debug2(this->dstTray );
382 
383  /*
384  if (dstTray.size() != 2){
385  mout.note(dstTray );
386  mout.error("dst should have exactly 2 image channels" );
387  }
388  */
389 
390  };
391 
392 
393 
394 };
395 
396 
397 
399 
403 template <class C = WindowConfig, class R = WindowCore>
404 class Window : public R { // consider : public BeanLike ?
405 
406 public:
407 
408  typedef C conf_t;
409 
410  conf_t conf;
411 
412  UniCloner<UnaryFunctor> unicloner;
413 
414  // Final function, set upon instantiation
415  drain::UnaryFunctor & myFunctor;
416 
418  Window(size_t width=1, size_t height=0) :
419  //conf(width, height),
420  unicloner(getFunctorBank()),
421  myFunctor(unicloner.getCloned(conf.getFunctorName())), //
422  //myFunctor(this->conf.getFunctor()),
423  resetAtEdges(false),
424  SCALE(true),
425  iRange(0,0),
426  jRange(0,0)
427  {
428  setSize(width, height==0 ? width : height);
429  myFunctor.setParameters(conf.functorParameters);
430  location.setLocation(0, 0);
431  };
432 
434  Window(const C & conf) :
435  conf(conf),
436  unicloner(getFunctorBank()),
437  myFunctor(unicloner.getCloned(conf.getFunctorName())), //
438  // myFunctor(this->conf.getFunctor(conf.getFunctorName())), //
439  resetAtEdges(false),
440  SCALE(true),
441  iRange(0,0),
442  jRange(0,0)
443  {
444  setSize(conf.frame.width, conf.frame.height);
445  myFunctor.setParameters(conf.functorParameters);
446  location.setLocation(0, 0);
447  }
448 
449  Window(const Window & window) :
450  conf(window.conf),
451  myFunctor(this->conf.getFunctor(window.conf.getFunctorName())),
452  resetAtEdges(window.resetAtEdges),
453  SCALE(window.SCALE),
454  iRange(window.iRange),
455  jRange(window.jRange)
456  {
457  setSize(conf.frame.width, conf.frame.height);
458  myFunctor.setParameters(window.conf.functorParameters);
459  location.setLocation(0, 0);
460  }
461  // Future option...
462  /*
463  Window(const R & core, size_t width=1, size_t height=0) : R(core), resetAtEdges(false){
464  setSize(width, height==0 ? width : height);
465  location.setLocation(0, 0);
466  };
467  */
468 
470  virtual
472  // << this->conf.getFunctorCloner().size() <<
473  //std::cerr << "Erasing: myFunctor " << std::endl;
474  };
475 
477  // Not final, because some derived classes like SlidingStripe's need to redefine this
478  virtual inline
479  void setSize(size_t width, size_t height){
480  conf.frame.set(width, height);
481  }
482 
483 
485  inline
486  size_t getArea(){
487  return conf.frame.getArea();
488  };
489 
491  inline
492  size_t getSamplingArea(){ return samplingArea;};
493 
494 
495 
497 
503  virtual
504  void run();
505 
509  virtual
510  void toStream(std::ostream & ostr) const;
511 
512 
513 protected:
514 
516 
519  virtual inline
520  bool isHorizontal() const { return (this->conf.frame.width > this->conf.frame.height); };
521 
524 
526  int samplingArea = 0;
527 
529  bool resetAtEdges = false; // NEW
530 
532  bool SCALE = true; // NEW
533 
541  virtual inline
542  void initialize(){
543  //setScaling();
544  setImageLimits();
545  setLoopLimits();
546  this->location.setLocation(0,0);
547  };
548 
550  virtual
551  void update(){};
552 
554 
558  virtual
559  void write() = 0; // {};
560 
561 
562 
564 
569  virtual inline
570  bool reset(){
571  return true;
572  };
573 
574 
576  /*
577  virtual
578  void se t S caling() const {
579  // SCALE = src.scaling.isScaled() || dst.scaling.isScaled();
580  };
581  */
582 
583  // Window limits, not image limits
585  mutable Range<int> jRange;
586 
588 
592  virtual
593  void setImageLimits() const = 0;
594 
595 
597  virtual inline
598  void setLoopLimits(int width, int height){
599  samplingArea = width * height;
600  iRange.min = -(static_cast<int>(width)-1)/2; // note unsigned risk!
601  iRange.max = width/2;
602  jRange.min = -(static_cast<int>(height)-1)/2;
603  jRange.max = height/2;
604  }
605 
607  inline
609  setLoopLimits(conf.frame.width, conf.frame.height);
610  }
611 
612 
613  // This is like a global member, useful for update(int) functions.
614  mutable CoordinateHandler2D coordinateHandler;
615 
616  // Debugging utility. Returns true on every (2^bit)'th diagonal location (x==y).
617  inline
618  bool debugDiag(int bit = 4){
619  return (this->location.x == this->location.y) && ((this->location.x&((1<<bit)-1)) == 0);
620  };
621 };
622 
623 
624 
625 template <class C, class R>
626 void Window<C,R>::toStream(std::ostream &ostr) const {
627  ostr << "Window: " << conf.frame << ' ';
628  ostr << '[' << iRange << '|' << jRange << ']';
629  //ostr << " in (" << srcWidth << 'x' << srcHeight << ") ";
630  ostr << '@' << location << ',' << coordinateHandler << ' ';
631  ostr << "functor: " << this->myFunctor << '\n';
632  /*
633  ostr << "src: " << src << " scaling:" << (int)SCALE << '\n';
634  ostr << "dst: " << dst << '\n';
635  ostr << "srcW:" << srcWeight << '\n';
636  ostr << "dstW:" << dstWeight << '\n';
637  */
638 }
639 
640 
641 template <class P, class R>
643 
644  initialize();
645 
646  int &i = location.x;
647  int &j = location.y;
648 
649  const Range<int> & horzRange = coordinateHandler.getXRange();
650  const Range<int> & vertRange = coordinateHandler.getYRange();
651 
652 
653  if (isHorizontal()){
654  for (j = 0; j <= vertRange.max; ++j) {
655  for (i = 0; i <= horzRange.max; ++i) {
656  update();
657  write();
658  }
659  if (resetAtEdges){
660  if (!reset())
661  return; // ?
662  }
663  }
664  }
665  else {
666  for (i = 0; i <= horzRange.max; ++i) {
667  for (j = 0; j <= vertRange.max; ++j) {
668  update();
669  write();
670  }
671  if (resetAtEdges){
672  if (!reset())
673  return;// ?
674  }
675  }
676  }
677 
678 }
679 
680 
681 template <class P, class R>
682 inline
683 std::ostream & operator<<(std::ostream &ostr, const drain::image::Window<P,R> &w){
684  w.toStream(ostr);
685  return ostr;
686 }
687 
688 
689 } // image
690 
691 template <class P, class R>
692 struct TypeName<image::Window<P,R> > {
693 
694  static const std::string & str(){
695  static const std::string name = std::string("Window<") + drain::TypeName<P>::str() + ',' + drain::TypeName<R>::str() + '>'; // todo: develop
696  return name;
697  }
698 
699 };
700 
701 } // drain
702 
703 
704 
705 #endif /* Drain_WINDOWOP_H_*/
706 
A Bank with additional support for brief, single char keys.
Definition: Bank.h:314
virtual const std::string & resolve(const key_t &value) const
Given brief or long key, returns the long key .
Definition: Bank.h:432
std::map< std::string, cloner_t * > map_t
Base class.
Definition: Bank.h:78
void setParameters(std::initializer_list< Variable::init_pair_t > args)
Grants access to (if above hidden)
Definition: BeanLike.h:131
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
Logger & error(const TT &... args)
Echoes.
Definition: Log.h:412
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:426
Logger & debug(const TT &... args)
Public, yet typically used "internally", when TIMING=true.
Definition: Log.h:676
Logger & debug2(const TT &... args)
Debug information.
Definition: Log.h:686
void importCastableMap(const drain::SmartMap< T2 > &m)
Assign values from a map, possibly extending the map.
Definition: SmartMap.h:271
Creates an entry of desired type and destroys it upon exit.
Definition: Bank.h:476
A map of Variables.
Definition: VariableMap.h:61
Image with static geometry.
Definition: ImageChannel.h:60
Definition: CoordinateHandler.h:62
Image with static geometry.
Definition: ImageFrame.h:67
Container applicable for Channels and Images, with alpha support.
Definition: ImageTray.h:267
void setChannels(T2 &img)
Splits.
Definition: ImageTray.h:402
void copy(const Tray< T2 > &t)
Add image sequence.
Definition: ImageTray.h:346
const image_t & getAlpha(size_t i=0) const
Returns the i'th alpha image.
Definition: ImageTray.h:329
ImageFrame that also has channels.
Definition: ImageView.h:52
void setView(const ImageFrame &src)
Views the whole image.
Definition: ImageView.h:65
Definition: Window.h:302
void setDstFrames(ImageTray< Channel > &dstTray)
virtual inline
Definition: Window.h:357
void setSrcFrames(const ImageTray< const Channel > &srcTray)
virtual inline
Definition: Window.h:329
const image_t & get(size_t i=0) const
Returns the i'th image.
Definition: ImageTray.h:81
void set(image_t &img, size_t i=0)
Replace image in position i.
Definition: ImageTray.h:103
Definition: Window.h:268
Base class for configurations applied in image processing windows, e.g. for operators of type WindowO...
Definition: Window.h:56
const VariableMap & getFunctorParams() const
Return the parameters to be set for proceeding getFunctor() calls.
Definition: Window.h:134
void setFunctor(const std::string &ftorKey)
Get the cloner of the current functor type.
Definition: Window.h:108
Container for source and target images, and their setters.
Definition: Window.h:156
Container for source and target images, and their setters.
Definition: Window.h:194
Base class for windows applied by WindowOp's.
Definition: Window.h:404
virtual void toStream(std::ostream &ostr) const
Definition: Window.h:626
bool resetAtEdges
To avoid accumulated numerical errors esp. with floats, reset the statistics at row/cols ends....
Definition: Window.h:529
virtual void run()
Main loop: traverses the source image and writes result to dst image.
Definition: Window.h:642
Window(const C &conf)
Constructor adapting given configuration.
Definition: Window.h:434
Point2D< int > location
Current location of this window.
Definition: Window.h:520
int samplingArea
Number of pixels in the window (frame width*height?).
Definition: Window.h:526
virtual void initialize()
Definition: Window.h:542
size_t getSamplingArea()
Returns the area which has eventually been scaled (in a non-linear coordinate system)
Definition: Window.h:492
virtual void setSize(size_t width, size_t height)
Sets the window size.
Definition: Window.h:479
virtual void setLoopLimits(int width, int height)
Sets the actual traversal range inside the window. Sometimes applied dynamically by reset().
Definition: Window.h:598
virtual void setImageLimits() const =0
Sets internal limits corresponding to image geometries. Typically using coordHandler.
virtual void write()=0
At each location, the result of computation to dst image(s).
virtual bool isHorizontal() const
Tells if the window should be moved (traversed of slided) row-by-row (horizontally) or column-by-colu...
Definition: Window.h:520
void setLoopLimits()
Sets the actual traversal range inside the window. Sometimes applied dynamically by reset().
Definition: Window.h:608
Window(size_t width=1, size_t height=0)
Constructor with geometry setting option.
Definition: Window.h:418
virtual bool reset()
Function determining whether array should be cleared at the edge(s). Needed for 1) cleaning numerical...
Definition: Window.h:570
virtual void update()
At each location, this is called to calculate and store something in members.
Definition: Window.h:551
virtual ~Window()
Destructor.
Definition: Window.h:471
Range< int > iRange
Studies source and destination images and decides whether scaling (SCALE=true) should be set.
Definition: Window.h:572
bool SCALE
If set, scaling is applied, potentially slowering the computation.
Definition: Window.h:532
size_t getArea()
Returns the nominal area in pixels.
Definition: Window.h:486
Definition: DataSelector.cpp:1277
UnaryFunctor & getFunctor(const std::string &nameAndParams, char separator)
Returns functor the parameters of which have been set.
Definition: FunctorBank.cpp:81
FunctorBank & getFunctorBank()
Definition: FunctorBank.cpp:51
Definition: Type.h:542
static const std::string name
Default implementation: name returned by std::type_info::name()
Definition: Type.h:558
Definition: Functor.h:116