37 #ifndef VIGRA_TRANSFORMIMAGE_HXX
38 #define VIGRA_TRANSFORMIMAGE_HXX
40 #include "utilities.hxx"
41 #include "numerictraits.hxx"
42 #include "iteratortraits.hxx"
43 #include "rgbvalue.hxx"
44 #include "functortraits.hxx"
45 #include "inspectimage.hxx"
61 template <
class SrcIterator,
class SrcAccessor,
62 class DestIterator,
class DestAccessor,
class Functor>
64 transformLine(SrcIterator s,
65 SrcIterator send, SrcAccessor src,
66 DestIterator d, DestAccessor dest,
69 for(; s != send; ++s, ++d)
70 dest.set(f(src(s)), d);
73 template <
class SrcIterator,
class SrcAccessor,
74 class MaskIterator,
class MaskAccessor,
75 class DestIterator,
class DestAccessor,
78 transformLineIf(SrcIterator s,
79 SrcIterator send, SrcAccessor src,
80 MaskIterator m, MaskAccessor mask,
81 DestIterator d, DestAccessor dest,
84 for(; s != send; ++s, ++d, ++m)
86 dest.set(f(src(s)), d);
167 template <
class SrcImageIterator,
class SrcAccessor,
168 class DestImageIterator,
class DestAccessor,
class Functor>
171 SrcImageIterator src_lowerright, SrcAccessor sa,
172 DestImageIterator dest_upperleft, DestAccessor da,
175 int w = src_lowerright.x - src_upperleft.x;
177 for(; src_upperleft.y < src_lowerright.y; ++src_upperleft.y, ++dest_upperleft.y)
179 transformLine(src_upperleft.rowIterator(),
180 src_upperleft.rowIterator() + w, sa,
181 dest_upperleft.rowIterator(), da, f);
185 template <
class SrcImageIterator,
class SrcAccessor,
186 class DestImageIterator,
class DestAccessor,
class Functor>
189 transformImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
190 pair<DestImageIterator, DestAccessor> dest,
194 dest.first, dest.second, f);
287 template <
class SrcImageIterator,
class SrcAccessor,
288 class MaskImageIterator,
class MaskAccessor,
289 class DestImageIterator,
class DestAccessor,
293 SrcImageIterator src_lowerright, SrcAccessor sa,
294 MaskImageIterator mask_upperleft, MaskAccessor ma,
295 DestImageIterator dest_upperleft, DestAccessor da,
298 int w = src_lowerright.x - src_upperleft.x;
300 for(; src_upperleft.y < src_lowerright.y;
301 ++src_upperleft.y, ++mask_upperleft.y, ++dest_upperleft.y)
303 transformLineIf(src_upperleft.rowIterator(),
304 src_upperleft.rowIterator() + w, sa,
305 mask_upperleft.rowIterator(), ma,
306 dest_upperleft.rowIterator(), da, f);
310 template <
class SrcImageIterator,
class SrcAccessor,
311 class MaskImageIterator,
class MaskAccessor,
312 class DestImageIterator,
class DestAccessor,
316 transformImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
317 pair<MaskImageIterator, MaskAccessor> mask,
318 pair<DestImageIterator, DestAccessor> dest,
322 mask.first, mask.second,
323 dest.first, dest.second, f);
404 template <
class SrcImageIterator,
class SrcAccessor,
405 class DestImageIterator,
class DestAccessor,
class Functor>
408 DestImageIterator destul, DestAccessor da, Functor
const & grad)
410 int w = srclr.x - srcul.x;
411 int h = srclr.y - srcul.y;
414 SrcImageIterator sy = srcul;
415 DestImageIterator dy = destul;
417 static const Diff2D left(-1,0);
418 static const Diff2D right(1,0);
419 static const Diff2D top(0,-1);
420 static const Diff2D bottom(0,1);
422 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
423 TmpType diffx, diffy;
425 SrcImageIterator sx = sy;
426 DestImageIterator dx = dy;
428 diffx = sa(sx) - sa(sx, right);
429 diffy = sa(sx) - sa(sx, bottom);
430 da.set(grad(diffx, diffy), dx);
432 for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
434 diffx = (sa(sx, left) - sa(sx, right)) / TmpType(2.0);
435 diffy = sa(sx) - sa(sx, bottom);
436 da.set(grad(diffx, diffy), dx);
439 diffx = sa(sx, left) - sa(sx);
440 diffy = sa(sx) - sa(sx, bottom);
441 da.set(grad(diffx, diffy), dx);
446 for(y=2; y<h; ++y, ++sy.y, ++dy.y)
451 diffx = sa(sx) - sa(sx, right);
452 diffy = (sa(sx, top) - sa(sx, bottom)) / TmpType(2.0);
453 da.set(grad(diffx, diffy), dx);
455 for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
457 diffx = (sa(sx, left) - sa(sx, right)) / TmpType(2.0);
458 diffy = (sa(sx, top) - sa(sx, bottom)) / TmpType(2.0);
459 da.set(grad(diffx, diffy), dx);
462 diffx = sa(sx, left) - sa(sx);
463 diffy = (sa(sx, top) - sa(sx, bottom)) / TmpType(2.0);
464 da.set(grad(diffx, diffy), dx);
470 diffx = sa(sx) - sa(sx, right);
471 diffy = sa(sx, top) - sa(sx);
472 da.set(grad(diffx, diffy), dx);
474 for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
476 diffx = (sa(sx, left) - sa(sx, right)) / TmpType(2.0);
477 diffy = sa(sx, top) - sa(sx);
478 da.set(grad(diffx, diffy), dx);
481 diffx = sa(sx, left) - sa(sx);
482 diffy = sa(sx, top) - sa(sx);
483 da.set(grad(diffx, diffy), dx);
486 template <
class SrcImageIterator,
class SrcAccessor,
487 class DestImageIterator,
class DestAccessor,
class Functor>
491 pair<DestImageIterator, DestAccessor> dest, Functor
const & grad)
494 dest.first, dest.second, grad);
505 template <
class DestValueType,
class Multiplier =
double>
506 class LinearIntensityTransform
512 typedef DestValueType argument_type;
516 typedef DestValueType result_type;
520 typedef DestValueType value_type;
526 NumericTraits<DestValueType>::RealPromote argument_promote;
530 typedef Multiplier scalar_multiplier_type;
534 LinearIntensityTransform(scalar_multiplier_type scale, argument_promote offset)
535 : scale_(scale), offset_(offset)
540 template <
class SrcValueType>
541 result_type operator()(SrcValueType
const & s)
const
543 return NumericTraits<result_type>::fromRealPromote(scale_ * (s + offset_));
548 scalar_multiplier_type scale_;
549 argument_promote offset_;
552 template <
class DestValueType,
class Multiplier>
553 class FunctorTraits<LinearIntensityTransform<DestValueType, Multiplier> >
554 :
public FunctorTraitsBase<LinearIntensityTransform<DestValueType, Multiplier> >
557 typedef VigraTrueType isUnaryFunctor;
560 template <
class DestValueType,
class Multiplier =
double>
561 class ScalarIntensityTransform
567 typedef DestValueType argument_type;
571 typedef DestValueType result_type;
575 typedef DestValueType value_type;
579 typedef Multiplier scalar_multiplier_type;
583 ScalarIntensityTransform(scalar_multiplier_type scale)
589 template <
class SrcValueType>
590 result_type operator()(SrcValueType
const & s)
const
592 return NumericTraits<result_type>::fromRealPromote(scale_ * s);
596 scalar_multiplier_type scale_;
599 template <
class DestValueType,
class Multiplier>
600 class FunctorTraits<ScalarIntensityTransform<DestValueType, Multiplier> >
601 :
public FunctorTraitsBase<ScalarIntensityTransform<DestValueType, Multiplier> >
604 typedef VigraTrueType isUnaryFunctor;
679 template <
class Multiplier,
class DestValueType>
680 LinearIntensityTransform<DestValueType, Multiplier>
683 return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
686 template <
class DestValueType,
class Multiplier>
687 ScalarIntensityTransform<DestValueType, Multiplier>
690 return ScalarIntensityTransform<DestValueType, Multiplier>(scale);
761 template <
class SrcValueType,
class DestValueType>
762 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
764 DestValueType dest_min, DestValueType dest_max )
767 typename NumericTraits<DestValueType>::isScalar());
770 template <
class SrcValueType,
class DestValueType>
771 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
773 DestValueType dest_min, DestValueType dest_max )
776 typename NumericTraits<DestValueType>::isScalar());
779 template <
class SrcValueType,
class DestValueType>
780 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
782 SrcValueType src_min, SrcValueType src_max,
783 DestValueType dest_min, DestValueType dest_max,
786 typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
787 Multiplier diff = src_max - src_min;
788 Multiplier scale = diff == NumericTraits<Multiplier>::zero()
789 ? NumericTraits<Multiplier>::one()
790 : (dest_max - dest_min) / diff;
791 return LinearIntensityTransform<DestValueType, Multiplier>(
792 scale, dest_min / scale - src_min );
795 template <
class SrcValueType,
class DestValueType>
796 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
798 SrcValueType src_min, SrcValueType src_max,
799 DestValueType dest_min, DestValueType dest_max,
802 typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
803 typedef typename Multiplier::value_type MComponent;
804 Multiplier scale(dest_max), offset(dest_max);
805 for(
unsigned int i=0; i<src_min.size(); ++i)
807 MComponent diff = src_max[i] - src_min[i];
808 scale[i] = diff == NumericTraits<MComponent>::zero()
809 ? NumericTraits<MComponent>::one()
810 : (dest_max[i] - dest_min[i]) / diff;
811 offset[i] = dest_min[i] / scale[i] - src_min[i];
813 return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
860 template <
class SrcValueType,
class DestValueType>
877 : lower_(lower), higher_(higher),
878 yesresult_(yesresult), noresult_(noresult)
885 return ((s < lower_) || (higher_ < s)) ? noresult_ : yesresult_;
894 template <
class SrcValueType,
class DestValueType>
895 class FunctorTraits<Threshold<SrcValueType, DestValueType> >
896 :
public FunctorTraitsBase<Threshold<SrcValueType, DestValueType> >
899 typedef VigraTrueType isUnaryFunctor;
981 template <
class PixelType>
985 NumericTraits<PixelType>::RealPromote promote_type;
1008 : b_(1.0/brightness),
1012 zero_(NumericTraits<promote_type>::zero()),
1013 one_(NumericTraits<promote_type>::one())
1020 promote_type v1 = (v - min_) / diff_;
1021 promote_type brighter = VIGRA_CSTD::pow(v1, b_);
1022 promote_type v2 = 2.0 * brighter - one_;
1023 promote_type contrasted = (v2 < zero_) ?
1024 -VIGRA_CSTD::pow(-v2, c_) :
1025 VIGRA_CSTD::pow(v2, c_);
1026 return result_type(0.5 * diff_ * (contrasted + one_) + min_);
1030 promote_type b_, c_;
1032 promote_type diff_, zero_, one_;
1036 class BrightnessContrastFunctor<unsigned char>
1038 typedef NumericTraits<unsigned char>::RealPromote promote_type;
1039 unsigned char lut[256];
1048 BrightnessContrastFunctor<promote_type> f(brightness, contrast, min, max);
1050 for(
int i = min; i <= max; ++i)
1052 lut[i] =
static_cast<unsigned char>(f(i)+0.5);
1063 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1065 template <
class ComponentType>
1066 class BrightnessContrastFunctor<RGBValue<ComponentType> >
1069 NumericTraits<ComponentType>::RealPromote promote_type;
1070 BrightnessContrastFunctor<ComponentType> red, green, blue;
1078 : red(brightness, contrast, min.red(), max.red()),
1079 green(brightness, contrast, min.green(), max.green()),
1080 blue(brightness, contrast, min.blue(), max.blue())
1086 return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1090 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1093 class BrightnessContrastFunctor<RGBValue<int> >
1095 typedef NumericTraits<int>::RealPromote promote_type;
1096 BrightnessContrastFunctor<int> red, green, blue;
1104 : red(brightness, contrast, min.red(), max.red()),
1105 green(brightness, contrast, min.green(), max.green()),
1106 blue(brightness, contrast, min.blue(), max.blue())
1112 return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1117 class BrightnessContrastFunctor<RGBValue<float> >
1119 typedef NumericTraits<float>::RealPromote promote_type;
1120 BrightnessContrastFunctor<float> red, green, blue;
1128 : red(brightness, contrast, min.red(), max.red()),
1129 green(brightness, contrast, min.green(), max.green()),
1130 blue(brightness, contrast, min.blue(), max.blue())
1136 return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1140 template <
class PixelType>
1141 class FunctorTraits<BrightnessContrastFunctor<PixelType> >
1142 :
public FunctorTraitsBase<BrightnessContrastFunctor<PixelType> >
1145 typedef VigraTrueType isUnaryFunctor;
1148 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1151 class BrightnessContrastFunctor<RGBValue<unsigned char> >
1153 typedef NumericTraits<unsigned char>::RealPromote promote_type;
1154 BrightnessContrastFunctor<unsigned char> red, green, blue;
1163 : red(brightness, contrast, min.red(), max.red()),
1164 green(brightness, contrast, min.green(), max.green()),
1165 blue(brightness, contrast, min.blue(), max.blue())
1171 return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1247 template <
class PixelType>
1251 NumericTraits<PixelType>::RealPromote promote_type;
1273 : gamma_((promote_type)gamma),
1276 zero_(NumericTraits<promote_type>::zero()),
1277 one_(NumericTraits<promote_type>::one())
1284 promote_type v1 = (v - min_) / diff_;
1285 promote_type brighter = VIGRA_CSTD::pow(v1, gamma_);
1290 promote_type gamma_;
1292 promote_type diff_, zero_, one_;
1296 class GammaFunctor<unsigned char>
1298 typedef NumericTraits<unsigned char>::RealPromote promote_type;
1299 unsigned char lut[256];
1308 GammaFunctor<promote_type> f(gamma, min, max);
1310 for(
int i = min; i <= max; ++i)
1312 lut[i] =
static_cast<unsigned char>(f(i)+0.5);
1323 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1325 template <
class ComponentType>
1326 class GammaFunctor<RGBValue<ComponentType> >
1329 NumericTraits<ComponentType>::RealPromote promote_type;
1330 GammaFunctor<ComponentType> red, green, blue;
1338 : red(gamma, min.red(), max.red()),
1339 green(gamma, min.green(), max.green()),
1340 blue(gamma, min.blue(), max.blue())
1345 return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1349 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1352 class GammaFunctor<RGBValue<int> >
1354 typedef NumericTraits<int>::RealPromote promote_type;
1355 GammaFunctor<int> red, green, blue;
1363 : red(gamma, min.red(), max.red()),
1364 green(gamma, min.green(), max.green()),
1365 blue(gamma, min.blue(), max.blue())
1370 return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1375 class GammaFunctor<RGBValue<float> >
1377 typedef NumericTraits<float>::RealPromote promote_type;
1378 GammaFunctor<float> red, green, blue;
1386 : red(gamma, min.red(), max.red()),
1387 green(gamma, min.green(), max.green()),
1388 blue(gamma, min.blue(), max.blue())
1393 return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1397 template <
class PixelType>
1398 class FunctorTraits<GammaFunctor<PixelType> >
1399 :
public FunctorTraitsBase<GammaFunctor<PixelType> >
1402 typedef VigraTrueType isUnaryFunctor;
1405 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1408 class GammaFunctor<RGBValue<unsigned char> >
1410 typedef NumericTraits<unsigned char>::RealPromote promote_type;
1411 GammaFunctor<unsigned char> red, green, blue;
1419 : red(gamma, min.red(), max.red()),
1420 green(gamma, min.green(), max.green()),
1421 blue(gamma, min.blue(), max.blue())
1426 return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1468 template <
class ValueType>
1478 typedef typename NumericTraits<typename ValueType::value_type>::RealPromote
result_type;
1488 template <
class ValueType>
1489 class FunctorTraits<VectorNormFunctor<ValueType> >
1490 :
public FunctorTraitsBase<VectorNormFunctor<ValueType> >
1493 typedef VigraTrueType isUnaryFunctor;
1513 template <
class ValueType>
1523 typedef typename NumericTraits<typename ValueType::value_type>::RealPromote
result_type;
1533 template <
class ValueType>
1534 class FunctorTraits<VectorNormSqFunctor<ValueType> >
1535 :
public FunctorTraitsBase<VectorNormSqFunctor<ValueType> >
1538 typedef VigraTrueType isUnaryFunctor;
1545 #endif // VIGRA_TRANSFORMIMAGE_HXX