impexalpha.hxx

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00029 #ifndef VIGRA_EXT_IMPEX_ALPHA_IMAGE_H
00030 #define VIGRA_EXT_IMPEX_ALPHA_IMAGE_H
00031 
00032 #include <iostream>
00033 #include <vigra/imageiterator.hxx>
00034 #include <vigra/transformimage.hxx>
00035 #include <vigra/initimage.hxx>
00036 #include <vigra/numerictraits.hxx>
00037 
00038 #include <vigra/impex.hxx>
00039 
00040 namespace vigra {
00041 
00042 #if 0
00043 
00046 template <class T1>
00047 struct GetMaskTrue;
00048 
00049 #define VIGRA_EXT_GETMASKTRUE(T1, S) \
00050 template<> \
00051 struct GetMaskTrue<T1> \
00052 { \
00053     static T1 get() \
00054 { \
00055         return S; \
00056 } \
00057 };
00058 
00059 #define VIGRA_EXT_GETMASKMAX(T1) \
00060 template<> \
00061 struct GetMaskTrue<T1> \
00062 { \
00063     static T1 get() \
00064 { \
00065         return vigra::NumericTraits<T1>::max(); \
00066 } \
00067 };
00068 
00069 VIGRA_EXT_GETMASKMAX(vigra::UInt8)
00070 VIGRA_EXT_GETMASKMAX(vigra::Int16)
00071 VIGRA_EXT_GETMASKMAX(vigra::UInt16)
00072 VIGRA_EXT_GETMASKMAX(vigra::Int32)
00073 VIGRA_EXT_GETMASKMAX(vigra::UInt32)
00074 VIGRA_EXT_GETMASKTRUE(float, 1.0f)
00075 VIGRA_EXT_GETMASKTRUE(double, 1.0)
00076 
00077 #endif
00078 
00079 
00080 template <class T1>
00081 struct MaskConv;
00082 
00083 
00084 template<>
00085 struct MaskConv<vigra::UInt8>
00086 {
00087     static vigra::UInt8 toUInt8(vigra::UInt8 v)
00088     {
00089         return v;
00090     }
00091 
00092     static vigra::UInt8 fromUInt8(vigra::UInt8 v)
00093     {
00094         return v;
00095     }
00096 };
00097 
00098 template<>
00099         struct MaskConv<vigra::UInt16>
00100 {
00101     static vigra::UInt8 toUInt8(vigra::UInt16 v)
00102     {
00103         return v>>8;
00104     }
00105 
00106 
00107     static vigra::UInt16 fromUInt8(vigra::UInt8 v)
00108     {
00109         return (v<<8) + v;
00110     }
00111 };
00112 
00113 template<>
00114         struct MaskConv<vigra::Int16>
00115 {
00116     static vigra::UInt8 toUInt8(vigra::Int16 v)
00117     {
00118         return v>>7;
00119     }
00120 
00121 
00122     static vigra::Int16 fromUInt8(vigra::UInt8 v)
00123     {
00124         return (v<<7)+ (v & 127);
00125     }
00126 };
00127 
00128 template<>
00129 struct MaskConv<vigra::UInt32>
00130 {
00131     static vigra::UInt8 toUInt8(vigra::UInt32 v)
00132     {
00133         return v>>24;
00134     }
00135 
00136 
00137     static vigra::UInt32 fromUInt8(vigra::UInt8 v)
00138     {
00139         return (v<<24) + (v<<16) + (v<<8) + v;
00140     }
00141 };
00142 
00143 template<>
00144 struct MaskConv<vigra::Int32>
00145 {
00146     static vigra::UInt8 toUInt8(vigra::Int32 v)
00147     {
00148         return v>>23;
00149     }
00150 
00151 
00152     static vigra::Int32 fromUInt8(vigra::UInt8 v)
00153     {
00154         return (v<<23) + (v<<15) + (v<<7) + (v & 127);
00155     }
00156 };
00157 
00158 template<>
00159 struct MaskConv<float>
00160 {
00161     static vigra::UInt8 toUInt8(float v)
00162     {
00163         return vigra::NumericTraits<vigra::UInt8>::fromRealPromote(v*255);
00164     }
00165 
00166     static float fromUInt8(vigra::UInt8 v)
00167     {
00168         return v/255.0f;
00169     }
00170 
00171 };
00172 
00173 template<>
00174 struct MaskConv<double>
00175 {
00176     static vigra::UInt8 toUInt8(double v)
00177     {
00178         return vigra::NumericTraits<vigra::UInt8>::fromRealPromote(v*255);
00179     }
00180 
00181     static double fromUInt8(vigra::UInt8 v)
00182     {
00183         return v/255.0;
00184     }
00185 
00186 };
00187 
00188 
00189 template <class Iter1, class Acc1, class Iter2, class Acc2>
00190 class MultiImageMaskAccessor2
00191 {
00192 public:
00196     typedef vigra::TinyVector<typename Acc1::value_type, 2> value_type;
00197     typedef typename Acc1::value_type component_type;
00198     typedef typename Acc2::value_type alpha_type;
00199 
00202     MultiImageMaskAccessor2(Iter1 i1, Acc1 a1, Iter2 i2, Acc2 a2)
00203     : i1_(i1), a1_(a1), i2_(i2), a2_(a2)
00204     {}
00205 
00208     template <class DIFFERENCE>
00209     value_type operator()(DIFFERENCE const & d) const
00210     {
00211         return value_type(a1_(i1_, d),
00212                           MaskConv<component_type>::fromUInt8(a2_(i2_, d)));
00213     }
00214 
00217     template <class DIFFERENCE1, class DIFFERENCE2>
00218     value_type operator()(DIFFERENCE1 d, DIFFERENCE2 const & d2) const
00219     {
00220         d += d2;
00221         return value_type(a1_(i1_, d),
00222                           MaskConv<component_type>::fromUInt8(a2_(i2_, d)));
00223 //                          a2_(i2_, d)? GetMaskTrue<component_type>::get() * a2_(i2_, d) : vigra::NumericTraits<component_type>::zero());
00224 
00225 //        return std::make_pair(a1_(i1_, d1), a2_(i2_, d1));
00226     }
00227 
00230     template <class DIFFERENCE>
00231     value_type set(const value_type & vt, DIFFERENCE const & d) const
00232     {
00233         a1_.set(vt[0], i1_, d);
00234         a2_.set(MaskConv<component_type>::toUInt8(vt[1]));
00235                 //GetMaskTrue<alpha_type>::get() : vigra::NumericTraits<alpha_type>::zero(), i2_, d);
00236     }
00237 
00239     template <class V, class ITERATOR>
00240     void setComponent( V const & value, ITERATOR const & i, int idx ) const
00241     {
00242         switch (idx) {
00243         case 0:
00244             a1_.set(value, i1_, *i);
00245             break;
00246         case 1:
00247             a2_.set(MaskConv<V>::toUInt8(value), i2_, *i); 
00248             // ? GetMaskTrue<alpha_type>::get() : vigra::NumericTraits<alpha_type>::zero());
00249             break;
00250         default:
00251             vigra_fail("too many components in input value");
00252         }
00253     }
00254 
00256     template <class ITERATOR>
00257     component_type getComponent(ITERATOR const & i, int idx) const
00258     {
00259         switch (idx) {
00260             case 0:
00261                 return a1_( i1_, *i );
00262             case 1:
00263                 return MaskConv<component_type>::fromUInt8(a2_( i2_, *i ));
00264                 //? GetMaskTrue<component_type>::get() : vigra::NumericTraits<component_type>::zero();
00265             default:
00266                 vigra_fail("too many components in input value");
00267             // never reached, but here to silence compiler
00268                 exit(1);
00269         }
00270     }
00271 
00272     template <class ITERATOR>
00273     unsigned int size ( ITERATOR const & i ) const
00274     {
00275         return 2;
00276     }
00277 
00278 private:
00279     Iter1 i1_;
00280     Acc1 a1_;
00281     Iter2 i2_;
00282     Acc2 a2_;
00283 };
00284 
00285 
00286 // get: convert from UInt8 mask to native type
00287 // read: convert from native type to UInt8 mask
00288 template <class Iter1, class Acc1, class Iter2, class Acc2>
00289 class MultiImageVectorMaskAccessor4
00290 {
00291 public:
00295     typedef typename Acc1::value_type VT1;
00296     // todo.. check static_size, currently static_size == 4
00297     enum { static_size = 4 };
00298 
00299     typedef vigra::TinyVector<typename VT1::value_type, static_size> value_type;
00300     typedef typename value_type::value_type component_type;
00301 
00302     typedef typename Acc2::value_type alpha_type;
00303 
00306     MultiImageVectorMaskAccessor4(Iter1 i1, Acc1 a1, Iter2 i2, Acc2 a2)
00307     : i1_(i1), a1_(a1), i2_(i2), a2_(a2)
00308     {}
00309 
00312     template <class DIFFERENCE>
00313     value_type operator()(DIFFERENCE const & d) const
00314     {
00315         const VT1 & v1 = a1_.get(i1_,d);
00316         return value_type(v1[0],
00317                           v1[1],
00318                           v1[2],
00319                           MaskConv<component_type>::fromUInt8(a2_(i2_, d)));
00320     }
00321 
00324     template <class DIFFERENCE1, class DIFFERENCE2>
00325     value_type operator()(DIFFERENCE1 d, DIFFERENCE2 const & d2) const
00326     {
00327         d += d2;
00328         const VT1 & v1 = a1_.get(i1_,d);
00329         return value_type(v1[0],
00330                           v1[1],
00331                           v1[2],
00332                           MaskConv<component_type>::fromUInt8(a2_(i2_, d)));
00333     }
00334 
00337     template <class DIFFERENCE>
00338     value_type set(const value_type & vt, DIFFERENCE const & d) const
00339     {
00340         Iter1 i1(i1_);
00341         i1 +=d;
00342         a1_.setComponent(vt[0], i1_, 0);
00343         a1_.setComponent(vt[1], i1_, 1);
00344         a1_.setComponent(vt[2], i1_, 2);
00345         a2_.set(MaskConv<component_type>::toUInt8(vt[3]), i2_, d);
00346     }
00347 
00349     template <class V, class ITERATOR>
00350     void setComponent( V const & value, ITERATOR const & i, int idx ) const
00351     {
00352         if ( idx < static_size - 1 ) {
00353             a1_.setComponent(value, i1_, *i, idx);
00354         } else if ( idx == static_size - 1 ) {
00355             a2_.set(MaskConv<V>::toUInt8(value), i2_, *i);
00356         } else {
00357             vigra_fail("too many components in input value");
00358         }
00359     }
00360 
00362     template <class ITERATOR>
00363     component_type getComponent(ITERATOR const & i, int idx) const
00364     {
00365         if ( idx < static_size - 1 ) {
00366             return a1_.getComponent(i1_, *i, idx);
00367         } else 
00368 #ifndef DEBUG
00369             return MaskConv<component_type>::fromUInt8(a2_(i2_, *i));
00370 #else
00371             if ( idx == static_size - 1 ) {
00372                 return MaskConv<component_type>::fromUInt8(a2_(i2_, *i));
00373         } else {
00374             vigra_fail("too many components in input value");
00375             // just to silence the compiler warning. this is
00376             // never reached, since vigra_fail will always
00377             // throw an exception.
00378             throw 0;
00379         }
00380 #endif
00381     }
00382 
00383     template <class ITERATOR>
00384     unsigned int size ( ITERATOR const & i ) const
00385     {
00386         return static_size;
00387     }
00388 
00389   private:
00390     Iter1 i1_;
00391     Acc1 a1_;
00392     Iter2 i2_;
00393     Acc2 a2_;
00394 };
00395 
00396 
00397 // scalar image
00398 template<class SrcIterator, class SrcAccessor,
00399          class AlphaIterator, class AlphaAccessor>
00400 void exportImageAlpha(vigra::triple<SrcIterator, SrcIterator, SrcAccessor> image,
00401                       std::pair<AlphaIterator, AlphaAccessor> alpha,
00402                       vigra::ImageExportInfo const & info,
00403                       vigra::VigraTrueType)
00404 {
00405     typedef MultiImageMaskAccessor2<SrcIterator, SrcAccessor, AlphaIterator, AlphaAccessor> MAcc;
00406 
00407     exportImage(vigra::CoordinateIterator(),
00408                 vigra::CoordinateIterator() + (image.second - image.first),
00409                 MAcc(image.first, image.third, alpha.first, alpha.second),
00410                 info);
00411 }
00412 
00413 
00414 // vector image
00415 template<class SrcIterator, class SrcAccessor,
00416          class AlphaIterator, class AlphaAccessor>
00417 void exportImageAlpha(vigra::triple<SrcIterator, SrcIterator, SrcAccessor> image,
00418                       std::pair<AlphaIterator, AlphaAccessor> alpha,
00419                       vigra::ImageExportInfo const & info,
00420                       vigra::VigraFalseType)
00421 {
00422     typedef MultiImageVectorMaskAccessor4<SrcIterator, SrcAccessor, AlphaIterator, AlphaAccessor> MAcc;
00423 
00424     exportImage(vigra::CoordinateIterator(), vigra::CoordinateIterator(image.second - image.first),
00425                 MAcc(image.first, image.third, alpha.first, alpha.second), info );
00426 }
00427 
00428 
00437 template<class SrcIterator, class SrcAccessor,
00438          class AlphaIterator, class AlphaAccessor>
00439 void exportImageAlpha(vigra::triple<SrcIterator, SrcIterator, SrcAccessor> image,
00440                       std::pair<AlphaIterator, AlphaAccessor> alpha,
00441                       vigra::ImageExportInfo const & info)
00442                       {
00443     typedef typename vigra::NumericTraits<typename SrcAccessor::value_type>::isScalar is_scalar;
00444     // select function for scalar, or vector image, depending on source type.
00445     // the alpha image has to be scalar all the time. stuff will break with strange
00446     // compile error if it isn't
00447     exportImageAlpha( image, alpha, info, is_scalar());
00448 }
00449 
00450 
00451 // vector image
00452 template<class DestIterator, class DestAccessor,
00453          class AlphaIterator, class AlphaAccessor>
00454 void importImageAlpha(vigra::ImageImportInfo const & info,
00455                       std::pair<DestIterator, DestAccessor> image,
00456                       std::pair<AlphaIterator, AlphaAccessor> alpha,
00457                                       vigra::VigraFalseType)
00458 {
00459     vigra_precondition(image.second(image.first).size() == 3,
00460                        "only scalar and 3 channel (vector) images supported by impexalpha.hxx");
00461 
00462     typedef MultiImageVectorMaskAccessor4<DestIterator, DestAccessor, AlphaIterator, AlphaAccessor> MAcc;
00463     importImage(info,
00464                 vigra::CoordinateIterator(),
00465                 MAcc(image.first, image.second, alpha.first, alpha.second) );
00466 }
00467 
00468 // scalar image
00469 template<class DestIterator, class DestAccessor,
00470          class AlphaIterator, class AlphaAccessor>
00471 void importImageAlpha(vigra::ImageImportInfo const & info,
00472                       std::pair<DestIterator, DestAccessor> image,
00473                       std::pair<AlphaIterator, AlphaAccessor> alpha,
00474                       vigra::VigraTrueType)
00475 {
00476     typedef MultiImageMaskAccessor2<DestIterator, DestAccessor, AlphaIterator, AlphaAccessor> MAcc;
00477 
00478     importImage(info, vigra::CoordinateIterator(),
00479                 MAcc(image.first, image.second, alpha.first, alpha.second) );
00480 }
00481 
00482 
00495 template<class DestIterator, class DestAccessor,
00496          class AlphaIterator, class AlphaAccessor>
00497 void importImageAlpha(vigra::ImageImportInfo const & info,
00498                       vigra::pair<DestIterator, DestAccessor> image,
00499                       std::pair<AlphaIterator, AlphaAccessor> alpha
00500                       )
00501 {
00502     typedef typename vigra::NumericTraits<typename DestAccessor::value_type>::isScalar is_scalar;
00503 
00504     if (info.numExtraBands() == 1 ) {
00505         // import image and alpha channel
00506         importImageAlpha(info, image, alpha, is_scalar());
00507     } else if (info.numExtraBands() == 0 ) {
00508         // no alphachannel in file, import as usual.
00509         importImage(info, image);
00510         // fill alpha image
00511         vigra::initImage(alpha.first ,
00512                          alpha.first + vigra::Diff2D(info.width(), info.height()),
00513                          alpha.second,
00514                          255);
00515     } else {
00516         vigra_fail("Images with two or more channel are not supported");
00517     }
00518 }
00519 
00520 } // namespace
00521 
00522 #endif // VIGRA_EXT_IMPEX_ALPHA_IMAGE_H

Generated on 25 Nov 2014 for Hugintrunk by  doxygen 1.4.7