core/filter.hh
Go to the documentation of this file.
1 /* -*- mia-c++ -*-
2  *
3  * This file is part of MIA - a toolbox for medical image analysis
4  * Copyright (c) Leipzig, Madrid 1999-2013 Gert Wollny
5  *
6  * MIA is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with MIA; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef mia_core_filter_hh
22 #define mia_core_filter_hh
23 
24 #include <cassert>
25 #include <stdexcept>
26 #include <mia/core/pixeltype.hh>
27 #include <mia/core/product_base.hh>
28 #include <mia/core/factory.hh>
30 
32 
36 struct EXPORT_CORE combiner_type {
37  static const char *type_descr;
38 };
39 
43 struct EXPORT_CORE filter_type {
44  static const char *type_descr;
45 };
46 
47 #define DC(T, D) dynamic_cast<const T&>(D)
48 #define DV(T, D) dynamic_cast<T&>(D)
49 
51 
67 template <typename R>
68 struct TFilter {
70  typedef R result_type;
71 };
72 
83 template <class D>
84 class EXPORT_HANDLER TDataFilter: public TFilter< std::shared_ptr<D > >, public CProductBase {
85 public:
86 
88  typedef D plugin_data;
90  typedef filter_type plugin_type;
91 
93  typedef D Image;
94 
96  typedef std::shared_ptr<TDataFilter<D> > Pointer;
97 
100 
101  virtual ~TDataFilter();
102 
106  result_type filter(const Image& image) const;
107 
111  result_type filter(std::shared_ptr<D> pimage) const;
112 private:
113  virtual result_type do_filter(const Image& image) const = 0;
114  virtual result_type do_filter(std::shared_ptr<D> image) const;
115 };
116 
128 template <class Image>
129 class EXPORT_HANDLER TDataFilterPlugin: public TFactory<TDataFilter<Image> > {
130 public:
133  TDataFilterPlugin(char const * const name):
134  TFactory<TDataFilter<Image> >(name)
135  {}
136 };
137 
143 template <template <class> class D>
144 struct __bind_all {
145  typedef D<bool> Dbool;
146  typedef D<signed char> Dsc;
147  typedef D<unsigned char> Duc;
148  typedef D<signed short> Dss;
149  typedef D<unsigned short> Dus;
150  typedef D<signed int> Dsi;
151  typedef D<unsigned int> Dui;
152 #ifdef LONG_64BIT
153  typedef D<signed long> Dsl;
154  typedef D<unsigned long> Dul;
155 #endif
156  typedef D<float> Dfloat;
157  typedef D<double> Ddouble;
158 };
159 
171 template <typename B>
172 struct Binder {
173 };
175 
176 
195 template <typename F, typename B>
196 static typename F::result_type filter(const F& f, const B& b)
197 {
198  typedef typename Binder<B>::Derived D;
199  switch (b.get_pixel_type()) {
200  case it_bit: return f(DC(typename D::Dbool,b));
201  case it_sbyte: return f(DC(typename D::Dsc,b));
202  case it_ubyte: return f(DC(typename D::Duc,b));
203  case it_sshort:return f(DC(typename D::Dss,b));
204  case it_ushort:return f(DC(typename D::Dus,b));
205  case it_sint: return f(DC(typename D::Dsi,b));
206  case it_uint: return f(DC(typename D::Dui,b));
207 #ifdef LONG_64BIT
208  case it_slong: return f(DC(typename D::Dsl,b));
209  case it_ulong: return f(DC(typename D::Dul,b));
210 #endif
211  case it_float: return f(DC(typename D::Dfloat,b));
212  case it_double:return f(DC(typename D::Ddouble,b));
213  default:
214  assert(!"unsupported pixel type in image");
215  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
216  }
217 }
218 
231 template <typename F, typename B>
232 static typename F::result_type filter_inplace(const F& f, B& b)
233 {
234  typedef typename Binder<B>::Derived D;
235  switch (b.get_pixel_type()) {
236  case it_bit: return f(DV(typename D::Dbool,b));
237  case it_sbyte: return f(DV(typename D::Dsc,b));
238  case it_ubyte: return f(DV(typename D::Duc,b));
239  case it_sshort:return f(DV(typename D::Dss,b));
240  case it_ushort:return f(DV(typename D::Dus,b));
241  case it_sint: return f(DV(typename D::Dsi,b));
242  case it_uint: return f(DV(typename D::Dui,b));
243 #ifdef LONG_64BIT
244  case it_slong: return f(DV(typename D::Dsl,b));
245  case it_ulong: return f(DV(typename D::Dul,b));
246 #endif
247  case it_float: return f(DV(typename D::Dfloat,b));
248  case it_double:return f(DV(typename D::Ddouble,b));
249  default:
250  assert(!"unsupported pixel type in image");
251  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
252  }
253 }
254 
266 template <typename F, typename B>
267 static typename F::result_type accumulate(F& f, const B& data)
268 {
269  typedef typename Binder<B>::Derived D;
270  switch (data.get_pixel_type()) {
271  case it_bit: return f(DC(typename D::Dbool,data));
272  case it_sbyte: return f(DC(typename D::Dsc,data));
273  case it_ubyte: return f(DC(typename D::Duc,data));
274  case it_sshort:return f(DC(typename D::Dss,data));
275  case it_ushort:return f(DC(typename D::Dus,data));
276  case it_sint: return f(DC(typename D::Dsi,data));
277  case it_uint: return f(DC(typename D::Dui,data));
278 #ifdef LONG_64BIT
279  case it_slong: return f(DC(typename D::Dsl,data));
280  case it_ulong: return f(DC(typename D::Dul,data));
281 #endif
282  case it_float: return f(DC(typename D::Dfloat,data));
283  case it_double:return f(DC(typename D::Ddouble,data));
284  default:
285  assert(!"unsupported pixel type in image");
286  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
287  }
288 }
289 
302 template <typename F, typename B>
303 static typename F::result_type filter_equal(const F& f, const B& a, const B& b)
304 {
305  assert(a.get_pixel_type() == b.get_pixel_type());
306  typedef typename Binder<B>::Derived D;
307  switch (a.get_pixel_type()) {
308  case it_bit: return f(DC(typename D::Dbool, a), DC(typename D::Dbool,b));
309  case it_sbyte: return f( DC(typename D::Dsc, a), DC(typename D::Dsc,b));
310  case it_ubyte: return f( DC(typename D::Duc, a), DC(typename D::Duc,b));
311  case it_sshort:return f( DC(typename D::Dss, a), DC(typename D::Dss,b));
312  case it_ushort:return f( DC(typename D::Dus, a), DC(typename D::Dus,b));
313  case it_sint: return f( DC(typename D::Dsi, a), DC(typename D::Dsi,b));
314  case it_uint: return f( DC(typename D::Dui, a), DC(typename D::Dui,b));
315 #ifdef LONG_64BIT
316  case it_slong: return f( DC(typename D::Dsl, a), DC(typename D::Dsl,b));
317  case it_ulong: return f( DC(typename D::Dul, a), DC(typename D::Dul,b));
318 #endif
319  case it_float: return f( DC(typename D::Dfloat, a), DC(typename D::Dfloat,b));
320  case it_double:return f( DC(typename D::Ddouble, a), DC(typename D::Ddouble,b));
321  default:
322  assert(!"unsupported pixel type in image");
323  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
324  }
325 }
326 
327 
339 template <typename F, typename B>
340 static void filter_equal_inplace(const F& f, const B& a, B& b)
341 {
342  assert(a.get_pixel_type() == b.get_pixel_type());
343  typedef typename Binder<B>::Derived D;
344  switch (a.get_pixel_type()) {
345  case it_bit: f(DC(typename D::Dbool, a), DV(typename D::Dbool,b));break;
346  case it_sbyte: f( DC(typename D::Dsc, a), DV(typename D::Dsc,b));break;
347  case it_ubyte: f( DC(typename D::Duc, a), DV(typename D::Duc,b));break;
348  case it_sshort: f( DC(typename D::Dss, a), DV(typename D::Dss,b));break;
349  case it_ushort: f( DC(typename D::Dus, a), DV(typename D::Dus,b));break;
350  case it_sint: f( DC(typename D::Dsi, a), DV(typename D::Dsi,b));break;
351  case it_uint: f( DC(typename D::Dui, a), DV(typename D::Dui,b));break;
352 #ifdef LONG_64BIT
353  case it_slong: f( DC(typename D::Dsl, a), DV(typename D::Dsl,b));break;
354  case it_ulong: f( DC(typename D::Dul, a), DV(typename D::Dul,b));break;
355 #endif
356  case it_float: f( DC(typename D::Dfloat, a), DV(typename D::Dfloat,b));break;
357  case it_double: f( DC(typename D::Ddouble, a), DV(typename D::Ddouble,b));break;
358  default:
359  assert(!"unsupported pixel type in image");
360  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
361  }
362 }
363 
364 
376 template <typename F, typename B, typename O>
377 static typename F::result_type filter_and_output(const F& f, const B& a, O& b)
378 {
379  typedef typename Binder<B>::Derived D;
380  switch (a.get_pixel_type()) {
381  case it_bit: return f(DC(typename D::Dbool, a), b);break;
382  case it_sbyte: return f(DC(typename D::Dsc, a), b);break;
383  case it_ubyte: return f(DC(typename D::Duc, a), b);break;
384  case it_sshort: return f(DC(typename D::Dss, a), b);break;
385  case it_ushort: return f(DC(typename D::Dus, a), b);break;
386  case it_sint: return f(DC(typename D::Dsi, a), b);break;
387  case it_uint: return f(DC(typename D::Dui, a), b);break;
388 #ifdef HAVE_INT64
389  case it_slong: return f(DC(typename D::Dsl, a), b);break;
390  case it_ulong: return f(DC(typename D::Dul, a), b);break;
391 #endif
392  case it_float: return f(DC(typename D::Dfloat, a), b);break;
393  case it_double: return f(DC(typename D::Ddouble, a), b);break;
394  default:
395  assert(!"unsupported pixel type in image");
396  throw std::invalid_argument("mia::filter_and_output: unsupported pixel type in image");
397  }
398 }
399 
401 
402 template <typename F, typename A, typename B>
403 static typename F::result_type _filter(const F& f, const A& a, const B& b)
404 {
405  typedef typename Binder<A>::Derived D;
406  switch (a.get_pixel_type()) {
407  case it_bit: return f(DC(typename D::Dbool, a), b);
408  case it_sbyte: return f(DC(typename D::Dsc, a), b);
409  case it_ubyte: return f(DC(typename D::Duc, a), b);
410  case it_sshort:return f(DC(typename D::Dss, a), b);
411  case it_ushort:return f(DC(typename D::Dus, a), b);
412  case it_sint: return f(DC(typename D::Dsi, a), b);
413  case it_uint: return f(DC(typename D::Dui, a), b);
414 #ifdef LONG_64BIT
415  case it_slong: return f(DC(typename D::Dsl, a), b);
416  case it_ulong: return f(DC(typename D::Dul, a), b);
417 #endif
418  case it_float: return f(DC(typename D::Dfloat,a), b);
419  case it_double:return f(DC(typename D::Ddouble,a), b);
420  default:
421  assert(!"unsupported pixel type in image");
422  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
423  }
424 }
426 
427 
440 template <typename F, typename A, typename B>
441 static typename F::result_type filter(const F& f, const A& a, const B& b)
442 {
443  typedef typename Binder<B>::Derived D;
444  switch (b.get_pixel_type()) {
445  case it_bit: return _filter(f, a, DC(typename D::Dbool, b));
446  case it_sbyte: return _filter(f, a, DC(typename D::Dsc, b));
447  case it_ubyte: return _filter(f, a, DC(typename D::Duc, b));
448  case it_sshort:return _filter(f, a, DC(typename D::Dss, b));
449  case it_ushort:return _filter(f, a, DC(typename D::Dus, b));
450  case it_sint: return _filter(f, a, DC(typename D::Dsi, b));
451  case it_uint: return _filter(f, a, DC(typename D::Dui, b));
452 #ifdef LONG_64BIT
453  case it_slong: return _filter(f, a, DC(typename D::Dsl, b));
454  case it_ulong: return _filter(f, a, DC(typename D::Dul, b));
455 #endif
456  case it_float: return _filter(f, a, DC(typename D::Dfloat, b));
457  case it_double:return _filter(f, a, DC(typename D::Ddouble,b));
458  default:
459  assert(!"unsupported pixel type in image");
460  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
461  }
462 }
463 
464 
466 template <typename F, typename A, typename B>
467 static typename F::result_type _accumulate(F& f, const A& a, const B& b)
468 {
469  typedef typename Binder<A>::Derived D;
470  switch (a.get_pixel_type()) {
471  case it_bit: return f(DC(typename D::Dbool, a), b);
472  case it_sbyte: return f(DC(typename D::Dsc, a), b);
473  case it_ubyte: return f(DC(typename D::Duc, a), b);
474  case it_sshort:return f(DC(typename D::Dss, a), b);
475  case it_ushort:return f(DC(typename D::Dus, a), b);
476  case it_sint: return f(DC(typename D::Dsi, a), b);
477  case it_uint: return f(DC(typename D::Dui, a), b);
478 #ifdef LONG_64BIT
479  case it_slong: return f(DC(typename D::Dsl, a), b);
480  case it_ulong: return f(DC(typename D::Dul, a), b);
481 #endif
482  case it_float: return f(DC(typename D::Dfloat,a), b);
483  case it_double:return f(DC(typename D::Ddouble,a), b);
484  default:
485  assert(!"unsupported pixel type in image");
486  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
487  }
488 }
490 
503 template <typename F, typename A, typename B>
504 static typename F::result_type accumulate(F& f, const A& a, const B& b)
505 {
506  typedef typename Binder<B>::Derived D;
507  switch (b.get_pixel_type()) {
508  case it_bit: return _accumulate(f, a, DC(typename D::Dbool, b));
509  case it_sbyte: return _accumulate(f, a, DC(typename D::Dsc, b));
510  case it_ubyte: return _accumulate(f, a, DC(typename D::Duc, b));
511  case it_sshort:return _accumulate(f, a, DC(typename D::Dss, b));
512  case it_ushort:return _accumulate(f, a, DC(typename D::Dus, b));
513  case it_sint: return _accumulate(f, a, DC(typename D::Dsi, b));
514  case it_uint: return _accumulate(f, a, DC(typename D::Dui, b));
515 #ifdef LONG_64BIT
516  case it_slong: return _accumulate(f, a, DC(typename D::Dsl, b));
517  case it_ulong: return _accumulate(f, a, DC(typename D::Dul, b));
518 #endif
519  case it_float: return _accumulate(f, a, DC(typename D::Dfloat, b));
520  case it_double:return _accumulate(f, a, DC(typename D::Ddouble,b));
521  default:
522  assert(!"unsupported pixel type in image");
523  throw std::invalid_argument("mia::accumulate: unsupported pixel type in image");
524  }
525 }
526 
527 
528 #undef DC
529 #undef DV
530 
531 
532 template <class D>
534 {
535 }
536 
537 template <class D>
539 TDataFilter<D>::filter(const D& image) const
540 {
541  return do_filter(image);
542 }
543 
544 template <class D>
546 TDataFilter<D>::filter(std::shared_ptr<D> pimage) const
547 {
548  return do_filter(pimage);
549 }
550 
551 template <class D>
553 TDataFilter<D>::do_filter(std::shared_ptr<D> pimage) const
554 {
555  return do_filter(*pimage);
556 }
557 
559 
560 #endif