Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
hugin_base/vigra_ext/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; 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; 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; 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::Int16 fromUInt8(vigra::UInt8 v) 00153 { 00154 return v<<23; 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
1.3.9.1