ImageTray.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 
32 #ifndef DRAIN_IMAGE_TRAY
33 #define DRAIN_IMAGE_TRAY
34 
35 
36 #include <stdexcept>
37 
38 #include "Image.h"
39 #include "ImageView.h"
40 
41 namespace drain {
42 
43 namespace image {
44 
45 // Under construction. To be introduced.
46 
48 
51 template <class T>
52 class Tray : public std::map<size_t, T &> {
53 
54 public:
55 
56  typedef T image_t;
57  typedef std::map<size_t, image_t &> map_t;
58 
59  // todo getImageFrames, getAlphaFrames
60  Tray(){};
61 
62  Tray(const Tray<image_t> &t){}; // copy?
63 
64  //Tray(std::vector<image_t> & v){
65  // append(v);
66  //};
67 
68  /*
69  Tray(image_t & image){
70  append(image);
71  };
72  */
73 
74  virtual
75  ~Tray(){};
76 
77 
78 
80  inline
81  const image_t & get(size_t i = 0) const {
82  typename map_t::const_iterator it = this->find(i);
83  if (it == this->end()){
84  throw std::runtime_error("Tray::get(i): find failed");
85  }
86  return it->second;
87  }
88 
90  inline
91  image_t & get(size_t i = 0){
92  typename map_t::iterator it = this->find(i);
93  if (it == this->end()){
94  throw std::runtime_error("Tray::get(i): find failed");
95  }
96  return it->second;
97  }
98 
99 
101  // TODO: consider swapping parameter order
102  inline
103  void set(image_t & img, size_t i=0){
104  this->insert(typename map_t::value_type(i, img));
105  }
106 
108  inline virtual
109  void appendImage(image_t & img){
110  this->insert(typename map_t::value_type(this->size(), img));
111  }
112 
114  template <class T2>
115  inline
116  void copy(const Tray<T2> &t){
117  this->clear();
118  for (typename Tray<T2>::const_iterator it=t.begin(); it!=t.end(); ++it){
119  appendImage(it->second);
120  }
121  }
122 
124  template <class T2>
125  inline //virtual
126  void copyVector(std::vector<T2> & v){
127  this->clear();
128  for (typename std::vector<T2>::iterator it = v.begin(); it != v.end(); ++it) {
129  appendImage(*it);
130  }
131  }
132 
134  virtual
135  const Geometry & getGeometry() const {
136  if (!this->empty())
137  geometry.setGeometry(this->get().getGeometry());
138  geometry.channels.set(this->size());
139  return geometry;
140  }
141 
143  virtual
144  bool checkGeometry(const Geometry & g) const {
145  if (this->empty()){
146  return false;
147  }
148  for (typename Tray<T>::const_iterator it=this->begin(); it!=this->end(); ++it){
149  if (g != it->second.getGeometry())
150  return false;
151  }
152  return true;
153  }
154 
156  bool checkGeometry() const {
157  if (this->empty()){
158  return false;
159  }
160  return checkGeometry(this->get().getGeometry());
161  }
162 
163 
164 
165 
167  // Applied by?
168  template <class T2>
169  inline
170  void putPixel(const Point2D<int> & p, const std::vector<T2> & v){
171  typename map_t::iterator it=this->begin();
172  typename std::vector<T2>::const_iterator vit = v.begin();
173  while (it!=this->end()){
174  it->second.put(p, *vit);
175  ++it;
176  ++vit;
177  }
178  }
179 
181  // Applied by?
182  template <class T2>
183  inline
184  void getPixel(const Point2D<int> & p, std::vector<T2> & v) const {
185  typename std::vector<T2>::iterator vit = v.begin();
186  typename map_t::const_iterator it=this->begin();
187  while (it!=this->end()){
188  *vit = it->second.template get<T2>(p);
189  ++it;
190  ++vit;
191  }
192  }
193 
194  /*
195  virtual inline
196  void adjustCoordinateHandler(CoordinateHandler2D & handler) const {
197 
198  Logger mout(getImgLog(), "Tray<T>", __FUNCTION__);
199 
200  if (this->empty()){
201  mout.warn("empty (no frames), leaving coordHandler intact" );
202  return;
203  }
204 
205  if (!this->checkGeometry()){
206  mout.warn("non-uniform geometry:" );
207  mout.note(*this );
208  }
209 
210  const Geometry & g = getGeometry();
211  handler.setLimits(g.getWidth(), g.getHeight());
212  handler.setPolicy(get().getCoordinatePolicy()); // ~policy of the first one
213 
214  };
215  */
216 
217  template <class T2>
218  bool hasOverlap(const Tray<T2> & tray) const {
219  for (typename map_t::const_iterator it=this->begin(); it!=this->end(); ++it){
220  for (typename Tray<T2>::map_t::const_iterator it2=tray.begin(); it2!=tray.end(); ++it2){
221  if (it->second.hasOverlap(it2->second)){
222  //std::cerr << __FUNCTION__ << ':' << it->first << '=' << it2->first << '\n';
223  return true;
224  }
225  }
226  }
227  return false;
228  }
229 
230  inline // virtual? (would reveal alpha?)
231  void toOStr(std::ostream & ostr) const {
232  for (typename map_t::const_iterator it=this->begin(); it!=this->end(); ++it){
233  ostr << it->first << ':' << it->second << '\n';
234  }
235  }
236 
237  void createVector(std::vector<Image> & v) const {
238  for (typename map_t::const_iterator it=this->begin(); it!=this->end(); ++it){
239  //v.insert(v.end(), Image(it->second.getType(), it->second.getGeometry()));
240  v.insert(v.end(), Image(it->second.getType()));
241  }
242  }
243 
244 protected:
245 
246  mutable Geometry geometry;
247 
248 
249 };
250 
251 
252 template <class T>
253 inline
254 std::ostream & operator<<(std::ostream &ostr, const Tray<T> & tray){
255  ostr << "Tray " << tray.getGeometry() << ":\n";
256  tray.toOStr(ostr);
257  return ostr;
258 }
259 
260 
261 
263 
266 template <class T> // TODO: rename to ImagePack2 etc. because valid also for Image's, not only for Channel's
267 class ImageTray : public Tray<T> {
268 
269 public:
270 
271  // "Inherit" types.
272  typedef typename Tray<T>::image_t image_t;
273  typedef typename Tray<T>::map_t map_t;
274 
275  Tray<T> alpha;
276 
277  // todo getChannels, getAlphaFrames
278  ImageTray(){};
279 
280  template <class T2>
281  inline
282  ImageTray(const ImageTray<T2> &t){
283  copy(t);
284  }
285 
286  template <class T2>
287  inline
289  copy(t);
290  }
291 
293  /*
294  ImageTray(image_t & img){
295  this->set(img);
296  }
297  */
298 
300 
305  /*
306  ImageTray(image_t & img, image_t & alpha){
307  this->set(img);
308  this->setAlpha(alpha);
309  }
310  */
311 
312  //ImageTray(std::vector<image_t> & v) : Tray<T>(v){
313  //}
314 
315  const Geometry & getGeometry() const {
316  this->geometry.setGeometry(this->get().getGeometry());
317  this->geometry.channels.set(this->size(), this->alpha.size());
318  return this->geometry;
319  }
320 
321  inline
322  bool hasAlpha() const {
323  return !alpha.empty();
324  }
325 
326 
328  inline
329  const image_t & getAlpha(size_t i = 0) const {
330  typename map_t::const_iterator it = alpha.find(i);
331  if (it == alpha.end()){
332  throw std::runtime_error("ChannelTray::getAlpha(i): find failed");
333  }
334  return it->second;
335  }
336 
337 
338  void clear(){
339  Tray<T>::clear();
340  this->alpha.Tray<T>::clear();
341  }
342 
344  template <class T2>
345  inline
346  void copy(const Tray<T2> &t){
347  Tray<T>::copy(t);
348  }
349 
351  template <class T2>
352  inline
353  void copy(Tray<T2> &t){
354  Tray<T>::copy(t);
355  }
356 
357  template <class T2>
358  inline
359  void copy(ImageTray<T2> &t){
360  this->Tray<T>::copy(t);
361  this->alpha.Tray<T>::copy(t.alpha);
362  }
363 
364  template <class T2>
365  inline
366  void copy(const ImageTray<T2> &t){
367  Tray<T>::copy(t);
368  alpha.Tray<T>::copy(t.alpha);
369  }
370 
371 
373  inline
374  void setAlpha(image_t & img, size_t i = 0){
375  this->alpha.insert(typename map_t::value_type(i, img));
376  }
377 
379  inline
380  image_t & getAlpha(size_t i = 0){
381  typename map_t::iterator it = alpha.find(i);
382  if (it == alpha.end()){
383  throw std::runtime_error("ChannelTray::getAlpha(i): find failed");
384  }
385  return it->second;
386  }
387 
388 
390  inline
391  void appendAlpha(image_t & img){
392  setAlpha(img, this->alpha.size());
393  }
394 
395 
397 
400  template <class T2> // consider copyVector(v, channelGeometry) with ChannelGeometry
401  inline
402  void setChannels(T2 & img){
403  takeImageChannels(*this, img);
404  takeAlphaChannels(alpha, img);
405  }
406 
407  template <class T2> // consider copyVector(v, channelGeometry) with ChannelGeometry
408  inline
409  void setChannels(const T2 & img){
410  takeImageChannels(*this, img);
411  takeAlphaChannels(alpha, img);
412  }
413 
414  template <class T2> // consider copyVector(v, channelGeometry) with ChannelGeometry
415  inline
416  void setChannels(T2 & img, T2 & alphaImg){
417  takeImageChannels(*this, img);
418  takeImageChannels(alpha, alphaImg);
419  }
420 
421  template <class T2> // consider copyVector(v, channelGeometry) with ChannelGeometry
422  inline
423  void setChannels(const T2 & img, const T2 & alphaImg){
424  takeImageChannels(*this, img);
425  takeImageChannels(alpha, alphaImg);
426  }
427 
429 
432  template <class T2> // consider copyVector(v, channelGeometry) with ChannelGeometry
433  inline
434  void setAlphaChannels(T2 & img){
435  takeImageChannels(alpha, img);
436  }
437 
439 
442  template <class T2> // consider copyVector(v, channelGeometry) with ChannelGeometry
443  inline
444  void setAlphaChannels(const T2 & img){
445  takeImageChannels(this->alpha, img);
446  }
447 
448 
449 
450  inline
451  void toOStr(std::ostream & ostr = std::cout) const {
452  //ostr << "ImageTray " << this->getGeometry() << ":\n";
453  Tray<T>::toOStr(ostr);
454  if (this->hasAlpha()){
455  ostr << "alphas: " << std::endl;
456  alpha.Tray<T>::toOStr(ostr);
457  }
458  }
459 
460 protected:
461 
463 
466  template <class T2> // consider copyVector(v, channelGeometry) with ChannelGeometry
467  static inline
468  void takeImageChannels(Tray<T> & tray, T2 & img){
469  tray.clear();
470  for (size_t i = 0; i < img.getImageChannelCount(); ++i) {
471  tray.appendImage(img.getChannel(i));
472  }
473  }
474 
475  template <class T2> // consider copyVector(v, channelGeometry) with ChannelGeometry
476  static inline
477  void takeAlphaChannels(Tray<T> & tray, T2 & img){
478  tray.clear();
479  for (size_t i = 0; i < img.getAlphaChannelCount(); ++i) {
480  tray.appendImage(img.getAlphaChannel(i));
481  }
482  }
483 
485 
488  template <class T2> // consider copyVector(v, channelGeometry) with ChannelGeometry
489  static inline
490  void takeImageChannels(Tray<const T> & tray, const T2 & img){
491  tray.clear();
492  for (size_t i = 0; i < img.getImageChannelCount(); ++i) {
493  tray.appendImage(img.getChannel(i));
494  }
495  }
496 
497  template <class T2> // consider copyVector(v, channelGeometry) with ChannelGeometry
498  static inline
499  void takeAlphaChannels(Tray<const T> & tray, const T2 & img){
500  tray.clear();
501  for (size_t i = 0; i < img.getAlphaChannelCount(); ++i) {
502  tray.appendImage(img.getAlphaChannel(i));
503  }
504  }
505 
506 
507 };
508 
509 
510 template <class T>
511 inline
512 std::ostream & operator<<(std::ostream &ostr, const ImageTray<T> & tray){
513  ostr << "ChannelTray " << tray.getGeometry() << ":\n";
514  tray.toOStr(ostr);
515  ostr << "*\n";
516  return ostr;
517 }
518 
519 
520 
521 
522 
524 
527 /*
528 template <class T>
529 class Clip : public Tray<T> {
530 
531 public:
532 
533  // "Inherit" types.
534  typedef typename Tray<T>::image_t image_t;
535  typedef typename Tray<T>::map_t map_t;
536 
537  Tray<T> alpha; // what if always Frame?
538 
539  Clip(){};
540 
541  Clip(const Clip<image_t> &t){};
542 
544  / **
545  * \param image - image object to be referenced
546  * Notice: if image contains alpha channels, they will \e not be separated.
547  * /
548  Clip(image_t & image){
549  this->set(0, image);
550  }
551 
553  / **
554  \param image - image object, the image channels of which will referenced.
555  \param alpha - image object, the image channels of which will referenced as alpha channels.
556  Notice: if first argument contains alpha channels, they will \e not be separated.
557 
558  TODO: consider if empty alpha?
559  * /
560  Clip(image_t & image, image_t & alpha){
561  this->set(0, image);
562  setAlpha(0, alpha);
563  }
564 
565  virtual
566  ~Clip(){};
567 
569  const Geometry & getGeometry() const {
570  geometry.setGeometry(this->get().getGeometry());
571  geometry.setChannelCount(this->size(), this->alpha.size());
572  return geometry;
573  }
574  // TODO consider setGeometry
575 
576 
578  / *
579  inline
580  void appendAlpha(image_t & image){
581  alpha.insert(typename map_t::value_type(alpha.size(), image));
582  }
583  * /
584 
585  inline
586  bool hasAlpha() const {
587  return !alpha.empty();
588  }
589 
590 
592  // TODO: if no explicit alpha, return images alpha?
593  // what about frame?
594  inline
595  const image_t & getAlpha(size_t i = 0) const {
596  typename map_t::const_iterator it = alpha.find(i);
597  if (it == alpha.end()){
598  std::runtime_error("ImageTray::getAlpha(i): find failed");
599  }
600  return it->second;
601  }
602 
603 
605  inline
606  image_t & getAlpha(size_t i = 0){
607  typename map_t::iterator it = alpha.find(i);
608  if (it == alpha.end()){
609  std::runtime_error("ImageTray::getAlpha(i): find failed");
610  }
611  return it->second;
612  }
613 
614 
615  inline
616  void toOStr(std::ostream & ostr) const {
617  Tray<T>::toOStr(ostr);
618  ostr << "alphas:\n";
619  for (typename Tray<T>::map_t::const_iterator it=alpha.begin(); it!=alpha.end(); ++it){
620  ostr << '\t' << it->first << ':' << it->second << '\n';
621  }
622  }
623 
624 protected:
625 
627  inline
628  void setAlpha(size_t i, image_t & image){
629  alpha.insert(typename map_t::value_type(i, image));
630  }
631 
633  inline
634  virtual
635  void append(image_t & image){
636  throw std::runtime_error("Clip::append defunct");
637  //this->insert(typename map_t::value_type(this->size(), image));
638  }
639 
640  mutable Geometry geometry;
641 
642 };
643 */
644 
645 // todo: lower append() ?
646 
647 /*
648 class ImageClip : public Clip<Image> {
649 
650 public:
651  void setGeometry(){}; // TODO
652 };
653 */
654 
656 
662 } // image
663 } // drain
664 
665 
666 
667 
668 
669 #endif
670 
671 // Drain
Definition: Geometry.h:145
Container applicable for Channels and Images, with alpha support.
Definition: ImageTray.h:267
void setAlphaChannels(const T2 &img)
Splits.
Definition: ImageTray.h:444
void setChannels(T2 &img)
Splits.
Definition: ImageTray.h:402
void setAlphaChannels(T2 &img)
Splits.
Definition: ImageTray.h:434
void setAlpha(image_t &img, size_t i=0)
Replace image in position i.
Definition: ImageTray.h:374
static void takeImageChannels(Tray< T > &tray, T2 &img)
Splits.
Definition: ImageTray.h:468
void copy(const Tray< T2 > &t)
Add image sequence.
Definition: ImageTray.h:346
void copy(Tray< T2 > &t)
Add image sequence.
Definition: ImageTray.h:353
void appendAlpha(image_t &img)
Add image to the end of the container.
Definition: ImageTray.h:391
image_t & getAlpha(size_t i=0)
Returns the i'th alpha image.
Definition: ImageTray.h:380
const image_t & getAlpha(size_t i=0) const
Returns the i'th alpha image.
Definition: ImageTray.h:329
const Geometry & getGeometry() const
Appends the whole single image.
Definition: ImageTray.h:315
static void takeImageChannels(Tray< const T > &tray, const T2 &img)
Splits.
Definition: ImageTray.h:490
Set of images, usable for general calls of type traverseFrame(src, dst) .
Definition: ImageTray.h:52
image_t & get(size_t i=0)
Returns the i'th image.
Definition: ImageTray.h:91
virtual void appendImage(image_t &img)
Add image to the end.
Definition: ImageTray.h:109
void putPixel(const Point2D< int > &p, const std::vector< T2 > &v)
Put intensity vector.
Definition: ImageTray.h:170
virtual bool checkGeometry(const Geometry &g) const
Returns true, if all the frames have the same width and height.
Definition: ImageTray.h:144
void copy(const Tray< T2 > &t)
Add image sequence. Replaces old values.
Definition: ImageTray.h:116
const image_t & get(size_t i=0) const
Returns the i'th image.
Definition: ImageTray.h:81
virtual const Geometry & getGeometry() const
Returns the geometry of the first frame.
Definition: ImageTray.h:135
void copyVector(std::vector< T2 > &v)
Add image sequence.
Definition: ImageTray.h:126
void set(image_t &img, size_t i=0)
Replace image in position i.
Definition: ImageTray.h:103
void getPixel(const Point2D< int > &p, std::vector< T2 > &v) const
Get intensity vector.
Definition: ImageTray.h:184
bool checkGeometry() const
Returns true, if all the frames have the same width and height.
Definition: ImageTray.h:156
Definition: DataSelector.cpp:1277