1
// -*- c-basic-offset: 4 -*-
2
/** @file FunctorAccessor.h
4
* @author Pablo d'Angelo <pablo.dangelo@web.de>
6
* $Id: FunctorAccessor.h,v 1.5 2007/01/27 05:00:35 acmihal Exp $
8
* This is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public
10
* License as published by the Free Software Foundation; either
11
* version 2 of the License, or (at your option) any later version.
13
* This software is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
18
* You should have received a copy of the GNU General Public
19
* License along with this software; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
#ifndef _FUNCTORACCESSOR_H
25
#define _FUNCTORACCESSOR_H
27
#include <vigra/numerictraits.hxx>
32
/** This class can be used to apply a function when reading
35
Can be used to apply point operations temporarily, like scaling,
38
This is a read only accessor, writing is not supported.
40
template <class Functor, class Accessor>
41
class ReadFunctorAccessor
44
typedef typename Functor::result_type value_type;
45
ReadFunctorAccessor(Functor f, Accessor a)
50
/** Get functor result
51
template <class A, class B>
52
void function(A a, B b)
57
template <typename ITERATOR_, typename DIFFERENCE_>
58
typename Functor::result_type operator()(ITERATOR_ const & i, DIFFERENCE_ d) const
63
/** Get functor result
65
template <class ITERATOR>
66
typename Functor::result_type operator()(ITERATOR const & i) const {
75
/** This class can be used to apply a function when writing
78
Can be used to apply point operations temporarily, like scaling,
81
This is a write only accessor, reading is not supported.
83
template <class Functor, class Accessor>
84
class WriteFunctorAccessor
87
typedef typename Functor::result_type value_type;
89
WriteFunctorAccessor(Functor f, Accessor a)
94
/** Set functor result
96
template <class Value, class ITERATOR>
97
void set(Value const & v, ITERATOR const & i) const
99
m_a.set(m_f(vigra::detail::RequiresExplicitCast<typename Functor::argument_type>::cast(v)), i);
102
/** Set functor result
104
template <class Value, class ITERATOR_, class DIFFERENCE_>
105
void set(Value const & v, ITERATOR_ const & i, DIFFERENCE_ d) const
107
m_a.set(m_f(vigra::detail::RequiresExplicitCast<typename Functor::argument_type>::cast(v)),i,d);
114
/** define a write only accessor for a virtual Image<TinyVector<Acc1::value_type>, 2>
115
image, which actually consists of two Images.
117
Useful to split an image into gray and alpha images while loading, like it is
118
shown in the following example:
121
vigra::ImageImportInfo info(argv[1]);
123
if(info.numBands() == 2 && info.numExtraBands() == 1)
127
image.resize(info.width(), info.height());
128
mask.resize(info.width(), info.height());
130
// construct special reading accessor, to split
131
// the image into two images while reading
132
vigra_ext::SplitVector2Accessor<BImage::Iterator,
136
splitA(image.upperLeft(), image.accessor(),
137
mask.upperLeft(), mask.accessor());
139
importImage(info, Diff2D(), splitA );
142
template <class Iter1, class Acc1, class Iter2, class Acc2>
143
class SplitVector2Accessor
146
/** the vector's value_type
148
typedef vigra::TinyVector<typename Acc1::value_type, 2> value_type;
149
typedef typename value_type::value_type component_type;
151
/** Construct from two image iterators and associated accessors.
153
SplitVector2Accessor(Iter1 i1, Acc1 a1, Iter2 i2, Acc2 a2)
154
: i1_(i1), a1_(a1), i2_(i2), a2_(a2)
157
/** scalar & scalar image */
158
template <class V, class ITERATOR>
159
void setComponent( V const & value, ITERATOR const & i, int idx ) const
163
a1_.set(value, i1_, *i);
166
a2_.set(value, i2_, *i);
169
vigra_fail("too many components in input value");
173
/** return the size (Number of Bands) */
174
template <class ITERATOR>
175
unsigned int size(ITERATOR const & i) const
186
/** split a vector image into a vector and a scalar image
188
* like SplitVector2Accessor, but for the vector -> vector, scalar
191
* the template parameter SIZE gives the length of each vector
192
* in the input image. components 0..SIZE-2, are put into the
193
* image 1 (must be a vector image), and component SIZE-1
194
* is stored in image 2 (should be a scalar image)
196
template <class Iter1, class Acc1, class Iter2, class Acc2, int SIZE>
197
class SplitVectorNAccessor
200
/** the vector's value_type
202
typedef vigra::TinyVector<typename Acc1::value_type, SIZE> value_type;
203
typedef typename value_type::value_type component_type;
205
/** Construct from two image iterators and associated accessors.
207
SplitVectorNAccessor(Iter1 i1, Acc1 a1, Iter2 i2, Acc2 a2)
208
: i1_(i1), a1_(a1), i2_(i2), a2_(a2)
211
/** vector & scalar image */
212
template <class V, class ITERATOR>
213
void setComponent( V const & value, ITERATOR const & i, int idx ) const
215
if ( idx < SIZE - 1 ) {
216
a1_.setComponent(value, i1_, *i, idx);
217
} else if ( idx == SIZE - 1 ) {
218
a2_.set(value, i2_, *i);
220
vigra_fail("too many components in input value");
224
/** return the size (Number of Bands) */
225
template <class ITERATOR>
226
unsigned int size(ITERATOR const & i) const
237
/** merge two scalar images into a vector image.
239
* the inverse to SplitVector2Accessor.
242
template <class Iter1, class Acc1, class Iter2, class Acc2>
243
class MergeScalarScalar2VectorAccessor
246
/** the vector's value_type
248
typedef vigra::TinyVector<typename Acc1::value_type, 2> value_type;
249
typedef typename value_type::value_type component_type;
251
/** Construct from two image iterators and associated accessors.
253
MergeScalarScalar2VectorAccessor(Iter1 i1, Acc1 a1, Iter2 i2, Acc2 a2)
254
: i1_(i1), a1_(a1), i2_(i2), a2_(a2)
257
/** read the current data item
259
template <class DIFFERENCE_>
260
value_type operator()(DIFFERENCE_ const & d) const
262
return value_type(a1_(i1_, d), a2_(i2_, d));
265
/** read one component */
266
template <class ITERATOR>
267
component_type getComponent(ITERATOR const & i, int idx) const
271
return a1_( i1_, *i );
273
return a2_( i2_, *i );
275
vigra_fail("too many components in input value");
276
// never reached, but here to silence compiler
281
/** read one component, with offset */
282
template <class ITERATOR, class DIFFERENCE_>
283
component_type const & getComponent(ITERATOR const & i, DIFFERENCE_ const & d, int idx) const
288
return a1_.getComponent(i1_, *i, idx);
290
return a2_.getComponent(i2_, *i, idx);
292
vigra_fail("too many components in input value");
296
/** return the size (Number of Bands) */
297
template <class ITERATOR>
298
unsigned int size(ITERATOR const & i) const
310
/** merge a vector and a scalar image into a vector image.
312
* This virtually "appends" the scalar image plane to
315
* the inverse to SplitVectorNAccessor.
318
template <class Iter1, class Acc1, class Iter2, class Acc2, int SIZE>
319
class MergeVectorScalar2VectorAccessor
322
/** the vector's value_type
324
typedef typename Acc1::value_type image1_type;
325
typedef typename Acc2::value_type image2_type;
327
typedef typename image1_type::value_type component_type;
329
typedef vigra::TinyVector<component_type, SIZE> value_type;
331
/** Construct from two image iterators and associated accessors.
333
MergeVectorScalar2VectorAccessor(Iter1 i1, Acc1 a1, Iter2 i2, Acc2 a2)
334
: i1_(i1), a1_(a1), i2_(i2), a2_(a2)
337
/** read the current data item
339
template <class DIFFERENCE_>
340
value_type operator()(DIFFERENCE_ const & d) const
343
typename value_type::iterator it = ret.begin();
344
const image1_type & i1 = a1_(i1_, d);
345
for ( typename image1_type::const_iterator it1 = i1.begin();
346
it1 != i1.end(); ++it1 )
355
/** read one component */
356
template <class ITERATOR>
357
component_type getComponent(ITERATOR const & i, int idx) const
359
if ( idx < SIZE - 1 ) {
360
return a1_.getComponent(i1_, *i, idx);
361
} else if ( idx == SIZE - 1 ) {
364
vigra_fail("too many components in input value");
365
// just to silence the compiler warning. this is
366
// never reached, since vigra_fail will always
367
// throw an exception.
372
/** read one component, with offset */
373
template <class ITERATOR, class DIFFERENCE_>
374
component_type const getComponent(ITERATOR i, DIFFERENCE_ const & d, int idx) const
377
if ( idx < SIZE - 1 ) {
378
return a1_.getComponent(i1_, *i, idx);
379
} else if ( idx == SIZE - 1 ) {
382
vigra_fail("too many components in input value");
383
// just to silence the compiler warning. this is
384
// never reached, since vigra_fail will always
385
// throw an exception.
391
/** return the size (Number of Bands) */
392
template <class ITERATOR>
393
unsigned int size(ITERATOR const & i) const
405
/** An accessor to encapsulate write access to a multiband image,
406
and move divide it into two images.
408
This is particulary useful, if a multiband image should be splitted
409
into separate images during import operations. Then one doesn't
410
need to create a temporary image.
412
This can be used to copy a 4 band image into a 3 band image
413
and a 1 band image, with a single copyImage, or during other
416
For example, some images contain an alpha channel, and depending
417
on the application, this doesn't need to have the same type, for
418
example, float RGB channels, uint8 mask channel. Many algorithms
419
provided by vigra also expect the masks and the image in separate
422
The following image combinations are supported so far:
424
- vector -> scalar, scalar
425
- vector -> vector, scalar
427
This accessor is quite slow. It checks the vector indicies on
430
@bug This is not a complete accessor, only write operations are supported.
431
@bug value_type is not specified correctly, I don't know how to merge
432
them properly with template programming.
435
both images need to have the same elementary type
437
template <class Iter1, class Acc1, class Iter2, class Acc2, int SIZE>
438
class ImageSplittingAccessor
441
/** value type of image 1 */
442
typedef typename Acc1::value_type image_type1;
444
/** value type of image 2 */
445
typedef typename Acc2::value_type image_type2;
447
/** @BUG: how to combine two value types into one? */
448
// typedef image_type1 value_type;
450
/** Construct from two image iterators and associated accessors.
452
ImageSplittingAccessor(Iter1 i1, Acc1 a1, Iter2 i2, Acc2 a2)
453
: i1_(i1), a1_(a1), i2_(i2), a2_(a2)
456
/** write value V into the two images.
458
* V has to be a stl compatible vector type,
459
* the two images can be of vector or scalar types.
462
template <class V, class ITERATOR>
463
void setComponent(V const & value, ITERATOR const & i, int idx) const
465
setComponentIsScalar(value, i, idx,
466
vigra::NumericTraits<image_type1>::isScalar() );
471
/** Write the current data item. The type <TT>V</TT> must be
472
a sequence type, Likewise the value types
473
of image 1 and image 2.
475
Its size must be size(image_type1) + size(image_type2);
477
The type <TT>V</TT> of the passed
478
in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
479
In case of a conversion floating point -> intergral this includes rounding and clipping.
481
template <class V, class ITERATOR>
482
void setVector2VectorVector(V const & value, ITERATOR const & i) const
484
// get pixels at current position indicated by iterator
485
image_type1 & v1 = a1_(i);
486
image_type2 & v2 = a2_(i2_, i - i1_);
487
// TODO: check if the size of both images is correct
489
// copy into first image
490
typename V::iterator vIt = value.begin();
491
typename image_type1::iterator v1It = v1.begin();
492
while ( v1It != v1.end() && vIt != value.end()) {
493
*v1It = detail::RequiresExplicitCast<VALUETYPE>::cast(*vIt);
497
// copy rest into second image
498
typename image_type2::iterator v2It = v2.begin();
499
while ( v2It != v1.end() && vIt != value.end()) {
500
*v2It = detail::RequiresExplicitCast<VALUETYPE>::cast(*vIt);
507
for (int i=0; i < value.size(); i++) {
510
*i = detail::RequiresExplicitCast<VALUETYPE>::cast(value); }
512
/** Write the data item at an offset (can be 1D or 2D or higher order difference)..
513
The type <TT>V</TT> of the passed
514
in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
515
In case of a conversion floating point -> intergral this includes rounding and clipping.
517
template <class V, class ITERATOR, class DIFFERENCE_>
518
void set(V const & value, ITERATOR const & i, DIFFERENCE_ const & diff) const
520
i[diff]= detail::RequiresExplicitCast<VALUETYPE>::cast(value);
526
/** if first dest image is scalar */
527
template <class V, class ITERATOR>
528
void setComponentIsScalar(V const & value, ITERATOR const & i, int idx,
529
vigra::VigraTrueType) const
531
setComponentScalarIsScalar(value, i, idx,
532
vigra::NumericTraits<image_type2>::isScalar() );
535
/** if first dest image is vector image */
536
template <class V, class ITERATOR>
537
void setComponentIsScalar(V const & value, ITERATOR const & i, int idx,
538
vigra::VigraFalseType) const
540
setComponentVectorIsScalar(value, i, idx,
541
vigra::NumericTraits<image_type2>::isScalar() );
544
/** if scalar & scalar image */
545
template <class V, class ITERATOR>
546
void setComponentScalarIsScalar(V const & value, ITERATOR const & i, int idx,
547
vigra::VigraTrueType) const
554
a2_.set(value, i2_, i - i1_);
557
vigra_fail("too many components in input value");
561
/** if scalar & vector image */
562
template <class V, class ITERATOR>
563
void setComponentScalarIsVector(V const & value, ITERATOR const & i, int idx,
564
vigra::VigraTrueType) const
566
vigra_fail("vector -> scalar, vector accessor not implemented");
569
/** if vector & scalar image */
570
template <class V, class ITERATOR>
571
void setComponentVectorIsScalar(V const & value, ITERATOR const & i, int idx,
572
vigra::VigraTrueType) const
574
image_type1 & v1 = a1_(i);
575
typename image_type1::size_type s1 = v1.size();
577
a1_.setComponent(value, i, idx);
578
} else if ( idx == s1) {
579
a2_.set(value, i2_, i - i1_);
581
vigra_fail("too many components in input value");
585
/** if vector & vector image */
586
template <class V, class ITERATOR>
587
void setComponentVectorIsVector(V const & value, ITERATOR const & i, int idx,
588
vigra::VigraTrueType) const
590
vigra_fail("vector -> vector, vector accessor not implemented");
599
/** a sample functor that can be used to multiply pixel values with a constant*/
603
typedef T result_type;
609
template <class PixelType>
610
PixelType operator()(PixelType const& v) const
612
return vigra::NumericTraits<result_type>::fromRealPromote(v * m_factor);
622
#endif // _FUNCTORACCESSOR_H