FunctorOp.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 FUNCTOROP_H_
32 #define FUNCTOROP_H_
33 
34 
35 #include <drain/image/ImageFile.h>
36 #include <drain/TypeUtils.h>
37 #include "drain/util/Functor.h"
38 #include "ImageOp.h"
39 
40 namespace drain
41 {
42 
43 namespace image
44 {
45 
46 // TODO: change to use functor bank, FunctorBank
47 /* *
48  * drainage image.png --functor FuzzyBell2,10,5 -o out.png
49  * drainage image.png image2.png --functor Add,10,5:FuzzyBell2,10,5 -o out.png
50  *
51  */
52 
54 template <class F>
56  F functor;
57 
58  FunctorWrapper(){};
59 
60  FunctorWrapper(const FunctorWrapper<F> & op) : functor(op.functor) {
61  //functor.getParameters().copyStruct(op.functor.getParameters(), op.functor, functor);
62  };
63 
64 };
65 
66 
68 
73 template <class F>
74 class FunctorOp : public FunctorWrapper<F>, public ImageOp
75 {
76 
77 public:
78 
79  FunctorOp() : LIMIT(false){};
80 
81  FunctorOp(const FunctorOp & op) : ImageOp(op), LIMIT(op.LIMIT){
82  this->getParameters().copyStruct(op.getParameters(), op, *this); // will add LIMIT (only)
83  };
84 
85  virtual ~FunctorOp(){};
86 
87  inline
88  void adaptParameters(bool adaptLimit = false){
89  ReferenceMap & p = this->getParameters();
90  p.append(this->functor.getParameters());
91  if (adaptLimit){
92  if (!p.empty()) // ?
93  p.link("LIMIT", this->LIMIT);
94  }
95  }
96 
97  bool LIMIT;
98 
99 protected:
100 
101  virtual
102  bool processOverlappingWithTemp(const ImageFrame & srcFrame, Image & dstImage) const {
103  return false;
104  };
105 
106  inline
107  bool processOverlappingWithTemp(const ImageTray<const Channel> & src, ImageTray<Image> & dst) const {
108  return false;
109  }
110 
115  FunctorOp(bool adaptParams = false, bool adoptLimit = false) :
116  FunctorWrapper<F>(),
117  ImageOp(this->functor.getName(), this->functor.getDescription()),
118  LIMIT(false) {
119  if (adaptParams)
120  adaptParameters(adoptLimit);
121  };
122 
123 
124 
125 };
126 
128 
133 template <class F,bool NORM=false,bool SIGN=false>
134 class UnaryFunctorOp : public FunctorOp<F>
135 {
136 public:
137 
142  //UnaryFunctorOp(bool adaptParams = false, bool adoptLimit = false) : FunctorOp<F>(adaptParams, adoptLimit) {
143  UnaryFunctorOp(bool adaptParams = true, bool adoptLimit = true) : FunctorOp<F>(adaptParams, adoptLimit) {
144  };
145 
146  inline
147  UnaryFunctorOp(const UnaryFunctorOp<F> & op) : FunctorOp<F>(false, false){
148  this->parameters.copyStruct(op.parameters, op, *this);
149  };
150 
151  virtual ~UnaryFunctorOp(){};
152 
153  void traverseChannels(const ImageTray<const Channel> & src, ImageTray<Channel> & dst) const { // = 0;
154  //drain::Logger mout(this->getName()+"(UnaryFunctorOp)", __FUNCTION__);
155  drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__);
156  mout.debug2("invoking processChannelsSeparately()" );
158  }
159 
161 
165  void traverseChannel(const Channel &src, Channel & dst) const;
166 
167 
168 protected:
169 
170  void getDstConf(const ImageConf & src, ImageConf & dst) const {
171 
172  // OLD
173  /*
174  if ((dst.getScale()==0.0) || !dst.typeIsSet())
175  dst.setEncoding(src.getEncoding());
176  */
177 
178  // New 2024, after bugs with:--physicalRange 0:1 for --iSegmentArea --iRemap --iThreshold
179  if (!dst.typeIsSet()){
180  dst.setEncoding(src.getEncoding());
181  }
182  else if (src.isScaled() && !dst.isScaled()){
183  //dst.setEncoding(src.getEncoding());
184  if (dst.getType() == src.getType()){
185  dst.setScaling(src.getScaling());
186  }
187  else {
189  }
190  }
191 
192 
193  // TODO: check if int, and unsigned, and minValue
194  if (SIGN && (dst.getMinPhys()>=0.0)){ // bug? why not leq
195  Logger mout(getImgLog(), __FILE__, __FUNCTION__);
196  mout.warn(this->functor.getName() , " would need signed type instead of : " , dst.getEncoding() );
197  }
198 
199  if (NORM){
200  if (SIGN)
201  dst.setPhysicalRange(-1.0, +1.0, true);
202  else
203  dst.setPhysicalRange( 0.0, +1.0, true);
204  }
205 
206  dst.setGeometry(src.getGeometry()); //geometry = src.geometry;
207 
208  dst.setCoordinatePolicy(src.getCoordinatePolicy());
209 
210  }
211 
212 
213  virtual
214  void initializeParameters(const ImageFrame &src, const ImageFrame &dst) const {
215 
216  Logger mout(getImgLog(), __FILE__, __FUNCTION__);
217  // mout.warn(*this );
218  this->functor.updateBean();
219 
220  }
221 
222 };
223 
224 template <class T,bool NORM,bool SIGN>
226 
227  //Logger mout(getImgLog(), __FILE__, __FUNCTION__); //REPL getImgLog(), this->name+"(UnaryFunctorOp)", __FUNCTION__);
228  Logger mout(getImgLog(), __FILE__, __FUNCTION__);
229  mout.debug("start" );
230 
231  const drain::ValueScaling & ss = src.getScaling();
232  const drain::ValueScaling & ds = dst.getScaling();
233  const bool SCALE = ss.isScaled() || ds.isScaled();
234  mout.debug("SCALE=" , (int)SCALE );
235  mout.debug("functor=" , this->functor );
236 
237  if (mout.isDebug(2)){
238  for (int i = 0; i < 256; i+=8) {
239  std::cout << __FILE__ << ':' << __FUNCTION__ << ':' << i << "\t -> " << ss.fwd(i) << "\t" << this->functor(ss.fwd(i)) << '\n';
240  }
241  }
242 
243  if (SCALE){
244  mout.debug2("ss scale:" , ss );
245  mout.debug2("ds scale:" , ds );
246  }
247 
248  Channel::const_iterator s = src.begin();
249  Channel::iterator d = dst.begin();
250 
251  if (!this->LIMIT){
252  if (!SCALE){ // Simplest first
254  while (d != dst.end()){
255  *d = this->functor(static_cast<double>(*s));
256  ++s;
257  ++d;
258  }
259  }
260  else {
261  while (d != dst.end()){
262  *d = ds.inv(this->functor(ss.fwd(static_cast<double>(*s))));
263  ++s;
264  ++d;
265  }
266  }
267  }
268  else { // LIMIT
269 
270  if (!drain::Type::call<drain::typeIsInteger>(dst.getType()))
271  mout.warn("float dst type, but LIMIT applied" , dst );
272 
273  //typedef drain::typeLimiter<double> Limiter;
274  drain::typeLimiter<double>::value_t limiter = dst.getLimiter<double>(); //Type::call<Limiter>(dst.getType());
275  if (!SCALE){
276  while (d != dst.end()){
277  *d = limiter(this->functor(static_cast<double>(*s)));
278  ++s;
279  ++d;
280  }
281  }
282  else {
283  while (d != dst.end()){
284  *d = limiter(ds.inv(this->functor(ss.fwd(static_cast<double>(*s)))));
285  ++s;
286  ++d;
287  }
288  }
289  }
290 
291 
292  //File::write(dst, "mika.png");
293 
294 }
295 
296 
297 
298 
299 
301 
304 template <class F>
305 class BinaryFunctorOp : public FunctorOp<F> //public FunctorWrapper<F>, public ChannelOp
306 {
307 public:
308 
310 
313  //BinaryFunctorOp(bool adaptParams = false, bool adoptLimit = false) : FunctorOp<F>(adaptParams, adoptLimit) {
314  BinaryFunctorOp(bool adaptParams = true, bool adoptLimit = true) : FunctorOp<F>(adaptParams, adoptLimit) { // , LIMIT(false)
315  };
316 
317  BinaryFunctorOp(const BinaryFunctorOp & op) : FunctorOp<F>(false, false){
318  this->parameters.copyStruct(op.parameters, op, *this);
319  };
320 
321  virtual
322  ~BinaryFunctorOp(){};
323 
324 
325 
326  inline
327  virtual
328  void traverseChannels(const ImageTray<const Channel> & src, ImageTray<Channel> & dst) const {
329  drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__); //REPL this->name+"(BinaryFunctorOp::)", __FUNCTION__);
330  mout.debug2("delegating to: processChannelsRepeated(src, dst)" );
331  this->traverseChannelsRepeated(src, dst);
332  }
333 
334  virtual inline
335  void traverseChannel(const Channel &src, Channel & dst) const {
336  drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__);
337  mout.debug2("delegating unary src to binary, with src2=dst: (src, dst) => (src,dst, dst) " );
338  traverseChannel(src, dst, dst);
339  }
340 
341  /*
342  virtual inline
343  void traverseChannel(const Channel & src, const Channel & srcWeight, Channel & dst, Channel & dstWeight) const {
344  drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__);
345  mout.warn("discarding alpha channels, delegating (src, srcWeight, dst, dstWeight) to plain (src, dst) " );
346  traverseChannel(src, dst);
347  }
348  */
349 
350 
351 
352  inline
353  virtual
354  void traverseChannel(const Channel &src1, const Channel &src2, Channel & dst) const {
355 
356  drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__); //REPL getImgLog(), this->name+"(BinaryFunctorOp)[ch1, ch2, chDst]", __FUNCTION__);
357  mout.debug2("start: " , *this );
358  mout.debug3("src1: " , src1 );
359  mout.debug3("src2: " , src2 );
360 
361  if ((src1.getGeometry() == src2.getGeometry()) && (src1.getGeometry() == dst.getGeometry()) ){
362  traverseSequentially(src1, src2, dst);
363  }
364  else {
365  traverseSpatially(src1, src2, dst);
366  }
367  }
368 
369  virtual
370  void traverseSequentially(const Channel &src1, const Channel &src2, Channel & dst) const;
371 
372  virtual
373  void traverseSpatially(const Channel &src1, const Channel &src2, Channel & dst) const;
374 
375 
376  virtual
377  void initializeParameters(const ImageFrame &src, const ImageFrame &dst) const {
378 
379  Logger mout(getImgLog(), __FILE__, __FUNCTION__); //REPL getImgLog(), this->name+"(BinaryFunctorOp)", __FUNCTION__);
380  mout.debug("Unary init for Binary" ); // << *this
381  //this->functor.setDstMax(dst.getMax<double>());
382  this->functor.updateBean();
383 
384  }
385 
386  virtual
387  void initializeParameters(const ImageFrame &src, const ImageFrame &src2, const ImageFrame &dst) const {
388 
389  //Logger mout(getImgLog(), __FILE__, __FUNCTION__);
390  //mout.warn("Binary init for Binary" , *this );
391  //this->functor.setDstMax(dst.getMax<double>());
392  this->functor.updateBean();
393 
394  }
395 
396 protected:
397 
399  void getDstConf(const ImageConf & src, ImageConf & dst) const {
400 
401  if ((dst.getScale()==0.0) || !dst.typeIsSet())
402  dst.setEncoding(src.getEncoding());
403 
404  if (dst.isEmpty()){
405  Logger mout(getImgLog(), __FILE__, __FUNCTION__);
406  mout.warn("2nd image empty, problems ahead" , *this );
407  dst.setGeometry(src.getGeometry());
408  dst.setCoordinatePolicy(src.getCoordinatePolicy());
409  }
410 
411  }
412 
413 
414 
415 };
416 
417 
418 template <class T>
419 void BinaryFunctorOp<T>::traverseSequentially(const Channel &src1, const Channel &src2, Channel & dst) const {
420 
421 
422  Logger mout(getImgLog(), __FILE__, __FUNCTION__); //REPL getImgLog(), this->name+"(BinaryFunctorOp)", std::string(__FUNCTION__)+"(src,src2,DST)");
423  mout.debug("start, " , this->functor );
424  //mout.warn(this->functor.scaleFinal );
425 
426  const drain::ValueScaling & s1s = src1.getScaling();
427  const drain::ValueScaling & s2s = src2.getScaling();
428  const drain::ValueScaling & ds = dst.getScaling();
429  const bool SCALE = s1s.isScaled() || s2s.isScaled() || ds.isScaled();
430  mout.debug("SCALE::" , (int)SCALE );
431  if (SCALE){
432  mout.debug("s1 scale:" , s1s );
433  mout.debug("s2 scale:" , s2s );
434  mout.debug("d scale:" , ds );
435  }
436 
437  Image::const_iterator s1 = src1.begin();
438  Image::const_iterator s2 = src2.begin();
439  Image::iterator d = dst.begin();
440 
441  if (!this->LIMIT){
442  mout.debug("LIMIT=False" );
443  if (!SCALE){
445  while (d != dst.end()){
446  *d = this->functor(*s1, *s2);
447  ++s1, ++s2;
448  ++d;
449  }
450  }
451  else {
453  while (d != dst.end()){
454  *d = ds.inv(this->functor(s1s.fwd(*s1), s2s.fwd(*s2)));
455  ++s1, ++s2;
456  ++d;
457  }
458  }
459  }
460  else {
461  mout.debug("LIMIT=True" );
462  if (!drain::Type::call<drain::typeIsInteger>(dst.getType()))
463  mout.warn("float dst type, but LIMIT applied" , dst );
464  //typedef drain::typeLimiter<double> Limiter; getEncoding().
465  drain::typeLimiter<double>::value_t limit = dst.getLimiter<double>(); //Type::call<Limiter>(dst.getType());
466  if (!SCALE){
467  while (d != dst.end()){
468  *d = limit(this->functor(*s1, *s2));
469  ++s1, ++s2;
470  ++d;
471  }
472  }
473  else {
474  while (d != dst.end()){
475  *d = limit(ds.inv(this->functor(s1s.fwd(*s1), s2s.fwd(*s2))));
476  ++s1, ++s2;
477  ++d;
478  }
479  }
480  }
481 
482 }
483 
484 template <class T>
485 void BinaryFunctorOp<T>::traverseSpatially(const Channel &src1, const Channel &src2, Channel & dst) const {
486 
487  Logger mout(getImgLog(), __FILE__, __FUNCTION__); //REPL this->name, std::string(__FUNCTION__)+"( src,src2, dst)");
488  mout.debug("start" );
489 
490  // // const double coeff1 = src1.getScaling().getScale();
491  const size_t width1 = src1.getWidth();
492  const size_t height1 = src1.getHeight();
493  CoordinateHandler2D handler1(width1, height1, src1.getCoordinatePolicy());
494 
495  // // const double coeff2 = src2.getScaling().getScale();
496  const size_t width2 = src2.getWidth();
497  const size_t height2 = src2.getHeight();
498  CoordinateHandler2D handler2(width2, height2, src2.getCoordinatePolicy());
499 
500  mout.debug2(handler1 );
501  mout.debug2(handler2 );
502 
503  const size_t width = dst.getWidth(); //std::max(width1, width2);
504  const size_t height = dst.getHeight(); // std::max(height2, height2);
505  // // const double scaleDst = dst.getScaling().getScale();
506  // // if (scaleDst == 0.0) mout.warn("zero scaling coeff for dst" );
507  // // const double coeffDst = (scaleDst != 0.0) ? 1.0/scaleDst : dst.getScaling().getMax<double>();
508  const bool SCALE = src1.getScaling().isScaled() || src2.getScaling().isScaled() || dst.getScaling().isScaled();
509 
510 
511  Point2D<int> p1;
512  Point2D<int> p2;
513 
514  if (!this->LIMIT){
515  mout.debug("LIMIT=false" );
516  if (!SCALE){
517  mout.debug("SCALE=false" );
518  for (size_t i = 0; i < width; ++i) {
519  for (size_t j = 0; j < height; ++j) {
520  handler1.handle( p1.setLocation(i,j) );
521  handler2.handle( p2.setLocation(i,j) );
522  dst.put(i,j, this->functor(src1.get<double>(p1), src2.get<double>(p2)));
523  }
524  }
525  }
526  else {
527  mout.debug("SCALE=true" );
528  for (size_t i = 0; i < width; ++i) {
529  for (size_t j = 0; j < height; ++j) {
530  handler1.handle( p1.setLocation(i,j) );
531  handler2.handle( p2.setLocation(i,j) );
532  dst.put(i,j, dst.getScaling().inv(this->functor(
533  src1.getScaling().fwd(src1.get<double>(p1)),
534  src2.getScaling().fwd(src2.get<double>(p2))
535  )));
536  //dst.put(i,j, dst.getScaling().fwd(coeffDst * this->functor(coeff1*src1.get<double>(p1), coeff2*src2.get<double>(p2))));
537  }
538  }
539  }
540  }
541  else { // LIMITED
542  mout.debug("LIMIT=true" );
543  if (!drain::Type::call<drain::typeIsInteger>(dst.getType()))
544  mout.warn("float dst type, but LIMIT applied" , dst );
545  // typedef drain::typeLimiter<double> Limiter;
546  // Limiter::value_t limiterPtr = Type::call<Limiter>(dst.getType());
547  // .getEncoding()
548  drain::typeLimiter<double>::value_t limit = dst.getLimiter<double>();
549 
550  if (!SCALE){
551  mout.debug("SCALE=false" );
552  for (size_t i = 0; i < width; ++i) {
553  for (size_t j = 0; j < height; ++j) {
554  handler1.handle( p1.setLocation(i,j) );
555  handler2.handle( p2.setLocation(i,j) );
556  dst.put(i,j, limit(this->functor(src1.get<double>(p1), src2.get<double>(p2))));
557  }
558  }
559  }
560  else {
561  mout.debug("SCALE=true" );
562  //mout.warn() << << mout.endl;
563  for (size_t i = 0; i < width; ++i) {
564  for (size_t j = 0; j < height; ++j) {
565  handler1.handle( p1.setLocation(i,j) );
566  handler2.handle( p2.setLocation(i,j) );
567  dst.put(i,j, limit(dst.getScaling().inv(this->functor(
568  src1.getScaling().fwd(src1.get<double>(p1)),
569  src2.getScaling().fwd(src2.get<double>(p2))
570  ))));
571  //dst.put(i,j, dst.getScaling().fwd(coeffDst * this->functor(coeff1*src1.get<double>(p1), coeff2*src2.get<double>(p2))));
572  }
573  }
574  }
575  }
576 
577  /*
578  if (this->LIMIT){
579  for (size_t i = 0; i < width; ++i) {
580  for (size_t j = 0; j < height; ++j) {
581  handler1.handle( p1.setLocation(i,j) );
582  handler2.handle( p2.setLocation(i,j) );
583  dst.put(i,j, dst.getScaling().limit<double>(coeffDst * this->functor(coeff1*src1.get<double>(p1), coeff2*src2.get<double>(p2))));
584  }
585  }
586  }
587  else {
588  for (size_t i = 0; i < width; ++i) {
589  for (size_t j = 0; j < height; ++j) {
590  handler1.handle( p1.setLocation(i,j) );
591  handler2.handle( p2.setLocation(i,j) );
592  dst.put(i,j, coeffDst * this->functor(coeff1*src1.get<double>(p1), coeff2*src2.get<double>(p2)));
593  }
594  }
595  }
596  */
597 
598 }
599 
600 
601 }
602 
603 }
604 
605 #endif /*FunctorOP_H_*/
606 
607 // Drain
virtual const std::string & getName() const
Return the name of an instance.
Definition: BeanLike.h:69
virtual const std::string & getDescription() const
Return a brief description.
Definition: BeanLike.h:74
Definition: CastableIterator.h:57
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
bool isDebug(level_t l=0)
Returns true, if the debug level of the monitor is at least l.
Definition: Log.h:354
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
Definition: ReferenceMap.h:207
void append(ReferenceMap &rMap, bool replace=true)
Adopts the references of r. If replace==false, only new entries are appended.
Definition: ReferenceMap.h:320
void copyStruct(const ReferenceMap &m, const T &src, T &dst, extLinkPolicy policy=RESERVE)
Experimental. Copies references and values of a structure to another.
Definition: ReferenceMap.h:399
Linear scaling and physical range for image intensities.
Definition: ValueScaling.h:64
double getMinPhys() const
Returns the minimum physical value.
Definition: ValueScaling.h:269
bool isScaled() const
Returns true, if scaling has effect ie. scale!=1.0 or offset!=0.0.
Definition: ValueScaling.h:263
double fwd(double x) const
Forward scaling: given encoded value x, returns corresponding value (possibly physically meaningful).
Definition: ValueScaling.h:295
virtual const ValueScaling & getScaling() const
Get linear scaling.
Definition: ValueScaling.h:147
const Range< double > & getPhysicalRange() const
Returns a typical or supported range for physical values.
Definition: ValueScaling.h:221
virtual void setScaling(double scale, double offset)
Set linear scaling.
Definition: ValueScaling.h:136
double inv(double y) const
Inverse scaling: given physically meaningful value y, returns the corresponding code value.
Definition: ValueScaling.h:301
double getScale() const
Returns the intensity scaling factor. See set setScale()
Definition: ValueScaling.h:252
Class for using two-parameter function objects (like std::functor) for sequential and spatial pixel i...
Definition: FunctorOp.h:306
virtual void traverseChannel(const Channel &src, Channel &dst) const
Apply to single channel.
Definition: FunctorOp.h:335
virtual void traverseSequentially(const Channel &src1, const Channel &src2, Channel &dst) const
Definition: FunctorOp.h:419
BinaryFunctorOp(bool adaptParams=true, bool adoptLimit=true)
Default constructor.
Definition: FunctorOp.h:314
virtual void initializeParameters(const ImageFrame &src, const ImageFrame &dst) const
Set applicable internal parameters before calling traverse().
Definition: FunctorOp.h:377
virtual void initializeParameters(const ImageFrame &src, const ImageFrame &src2, const ImageFrame &dst) const
Set applicable internal parameters before calling traverse().
Definition: FunctorOp.h:387
void getDstConf(const ImageConf &src, ImageConf &dst) const
Does not change dst geometry.
Definition: FunctorOp.h:399
Image with static geometry.
Definition: ImageChannel.h:60
Definition: CoordinateHandler.h:62
const Encoding & getEncoding() const
Return type and scaling.
Definition: ImageConf.h:68
bool typeIsSet() const
Get the storage type.
Definition: ImageConf.h:116
void setEncoding(const Encoding &e)
Set type and scaling.
Definition: ImageConf.h:83
const std::type_info & getType() const
Linear scaling.
Definition: ImageConf.h:110
void setPhysicalRange(const Range< double > &range, bool rescale=false)
Sets channel specific scaling instead of shared (image-level) scaling.
Definition: ImageConf.h:229
Class for using simple function objects (like std::functor) for sequential pixel iteration.
Definition: FunctorOp.h:75
FunctorOp(bool adaptParams=false, bool adoptLimit=false)
Definition: FunctorOp.h:115
Struct for image (excluding data)
Definition: ImageConf.h:333
void setCoordinatePolicy(const T &policy)
Does not set any CoordinateHandler object.
Definition: ImageConf.h:368
Image with static geometry.
Definition: ImageFrame.h:67
const iterator & begin()
Returns iterator pointing to the first image element.
Definition: ImageFrame.h:119
void put(size_t i, T x)
Sets the intensity in location i to x. See \address.
Definition: ImageFrame.h:192
const iterator & end()
Returns the iterator pointing to the element after the last element of the image buffer.
Definition: ImageFrame.h:125
T get(size_t i) const
Gets the intensity at location i. See address().
Definition: ImageFrame.h:254
const std::type_info & getType() const
Get the storage type.
Definition: ImageLike.h:100
const CoordinatePolicy & getCoordinatePolicy() const
Coord policy.
Definition: ImageLike.h:167
Base class for image processing functions.
Definition: ImageOp.h:49
void traverseChannelsRepeated(const ImageTray< const Channel > &src, ImageTray< Channel > &dst) const
Recycle channels until all dst channels completed.
Definition: ImageOp.cpp:454
ImageOp(const std::string &name=__FUNCTION__, const std::string &description="")
Definition: ImageOp.h:156
void traverseChannelsSeparately(const ImageTray< const Channel > &src, ImageTray< Channel > &dst) const
Process each (src,dst) channel pair independently. Raise error if their counts differ.
Definition: ImageOp.cpp:340
Container applicable for Channels and Images, with alpha support.
Definition: ImageTray.h:267
Class for multi-channel digital images. Supports dynamic typing with base types (char,...
Definition: Image.h:184
Class for using simple function objects (like std::functor) for sequential pixel iteration.
Definition: FunctorOp.h:135
UnaryFunctorOp(bool adaptParams=true, bool adoptLimit=true)
Definition: FunctorOp.h:143
void traverseChannel(const Channel &src, Channel &dst) const
Process the image.
Definition: FunctorOp.h:225
virtual void initializeParameters(const ImageFrame &src, const ImageFrame &dst) const
Set applicable internal parameters before calling traverse().
Definition: FunctorOp.h:214
void getDstConf(const ImageConf &src, ImageConf &dst) const
Given source image, determine respective dest image configuration.
Definition: FunctorOp.h:170
Class for ensuring that variable of type D remains within limits of type S.
Definition: TypeUtils.h:653
Definition: DataSelector.cpp:1277
Helper class that only ensures that functor is initialized before ImageOp.
Definition: FunctorOp.h:55