TuttleOFX
1
|
00001 #ifndef _TERRY_SAMPLER_DETAILS_HPP_ 00002 #define _TERRY_SAMPLER_DETAILS_HPP_ 00003 00004 #include <terry/numeric/operations.hpp> 00005 00006 #include "sampler.hpp" 00007 00008 #include <terry/clamp.hpp> 00009 #include <terry/globals.hpp> 00010 #include <terry/basic_colors.hpp> 00011 00012 #include <terry/typedefs.hpp> 00013 00014 #include <cmath> 00015 #include <vector> 00016 00017 00018 namespace terry { 00019 using namespace boost::gil; 00020 namespace sampler { 00021 00022 namespace details { 00023 00024 template <typename Weight> 00025 struct add_dst_mul_src_channel 00026 { 00027 const Weight _w; 00028 00029 add_dst_mul_src_channel( const Weight w ) : _w( w ) { } 00030 00031 template <typename SrcChannel, typename DstChannel> 00032 void operator( )( const SrcChannel& src, DstChannel& dst ) const 00033 { 00034 dst += DstChannel( channel_convert<DstChannel>(src) * _w ); 00035 } 00036 }; 00037 00038 template <typename SrcP, typename Weight, typename DstP> 00039 struct add_dst_mul_src 00040 { 00041 void operator( )( const SrcP& src, const Weight weight, DstP & dst ) const 00042 { 00043 static_for_each( src, dst, add_dst_mul_src_channel<Weight>( weight ) ); 00044 } 00045 }; 00046 00047 00048 /** 00049 * @brief Get pixels around a particular position. 00050 * @param[in] loc locator which points to a pixel 00051 * @param[in] pt0 x,y position of loc 00052 * @param[in] windowWidth the region inside which we search our pixels 00053 * @param[out] ptN pixel value to retrieve 00054 * 00055 * it's to use with (B,C) filter 00056 * number of points need to be even 00057 * 00058 * ----------------- 00059 * | A | B | C | D | 00060 * ----------------- 00061 * ^..... loc is pointing to D point 00062 */ 00063 template < typename xy_locator, typename SrcP > 00064 void getPixelsPointers( const xy_locator& loc, const point2<std::ptrdiff_t>& p0, const int& windowWidth, const int& imageWidth, const EParamFilterOutOfImage& outOfImageProcess, std::vector< SrcP >& src ) 00065 { 00066 int middlePosition = floor( (src.size() - 1) * 0.5 ); 00067 00068 if( ( p0.x < 0 ) || ( p0.x > imageWidth - 1 ) ) 00069 { 00070 switch( outOfImageProcess ) 00071 { 00072 case eParamFilterOutBlack : 00073 { 00074 src.at( middlePosition ) = get_black<SrcP>(); 00075 break; 00076 } 00077 case eParamFilterOutTransparency : 00078 { 00079 src.at( middlePosition ) = SrcP(0); 00080 break; 00081 } 00082 case eParamFilterOutCopy : 00083 { 00084 src.at( middlePosition ) = loc.x()[ ( p0.x < 0 ) ? (- p0.x) : - 1 - p0.x + imageWidth ]; 00085 break; 00086 } 00087 case eParamFilterOutMirror : 00088 { 00089 src.at( middlePosition ) = SrcP(0); 00090 break; 00091 } 00092 } 00093 } 00094 else 00095 { 00096 src.at( middlePosition ) = *loc; 00097 } 00098 00099 // from center to left 00100 for( int i = middlePosition - 1; i > -1; i-- ) 00101 { 00102 if( ( p0.x - (middlePosition - i) > -1 ) ) 00103 { 00104 if( ( p0.x - (middlePosition - i) < imageWidth ) ) 00105 { 00106 src.at( i ) = loc.x( )[ - (middlePosition - i) ]; 00107 } 00108 else 00109 { 00110 switch( outOfImageProcess ) 00111 { 00112 case eParamFilterOutBlack : 00113 { 00114 src.at( i ) = get_black<SrcP>(); 00115 break; 00116 } 00117 case eParamFilterOutTransparency : 00118 { 00119 src.at( i ) = SrcP(0); 00120 break; 00121 } 00122 case eParamFilterOutCopy : 00123 { 00124 src.at( i ) = src.at( i + 1 ); 00125 break; 00126 } 00127 case eParamFilterOutMirror : 00128 { 00129 src.at( i ) = SrcP(0); 00130 break; 00131 } 00132 }; 00133 } 00134 } 00135 else 00136 { 00137 switch( outOfImageProcess ) 00138 { 00139 case eParamFilterOutBlack : 00140 { 00141 src.at( i ) = get_black<SrcP>(); 00142 break; 00143 } 00144 case eParamFilterOutTransparency : 00145 { 00146 src.at( i ) = SrcP(0); 00147 break; 00148 } 00149 case eParamFilterOutCopy : 00150 { 00151 src.at( i ) = src.at( i + 1 ); 00152 break; 00153 } 00154 case eParamFilterOutMirror : 00155 { 00156 src.at( i ) = SrcP(0); 00157 break; 00158 } 00159 }; 00160 } 00161 } 00162 00163 // from center to right 00164 for( int i = middlePosition + 1; i < (int) src.size(); i++ ) 00165 { 00166 if( ( p0.x - (middlePosition - i) < imageWidth ) ) 00167 { 00168 if( p0.x - (middlePosition - i) < 0 ) 00169 { 00170 switch( outOfImageProcess ) 00171 { 00172 case eParamFilterOutBlack : 00173 { 00174 src.at( i ) = get_black<SrcP>(); 00175 break; 00176 } 00177 case eParamFilterOutTransparency : 00178 { 00179 src.at( i ) = SrcP(0); 00180 break; 00181 } 00182 case eParamFilterOutCopy : 00183 { 00184 src.at( i ) = src.at( i - 1 ); 00185 break; 00186 } 00187 case eParamFilterOutMirror : 00188 { 00189 src.at( i ) = SrcP(0); 00190 break; 00191 } 00192 }; 00193 } 00194 else 00195 { 00196 src.at( i ) = loc.x( )[ - (middlePosition - i) ]; 00197 } 00198 } 00199 else 00200 { 00201 switch( outOfImageProcess ) 00202 { 00203 case eParamFilterOutBlack : 00204 { 00205 src.at( i ) = get_black<SrcP>(); 00206 break; 00207 } 00208 case eParamFilterOutTransparency : 00209 { 00210 src.at( i ) = SrcP(0); 00211 break; 00212 } 00213 case eParamFilterOutCopy : 00214 { 00215 src.at( i ) = src.at( i - 1 ); 00216 break; 00217 } 00218 case eParamFilterOutMirror : 00219 { 00220 src.at( i ) = SrcP(0); 00221 break; 00222 } 00223 }; 00224 } 00225 } 00226 00227 } 00228 00229 template <typename SrcP, typename Weight, typename DstP> 00230 struct process1Dresampling 00231 { 00232 void operator( )( const std::vector<SrcP>& src, const std::vector<Weight>& weight, DstP& dst ) const 00233 { 00234 DstP mp( 0 ); 00235 for( std::size_t i = 0; i < src.size(); i++ ) 00236 details::add_dst_mul_src< SrcP, Weight, DstP > ( )( src.at(i), weight.at(i) , mp ); 00237 dst = mp; 00238 } 00239 }; 00240 00241 /// @todo specialization for SIMD 00242 //template <typename F> 00243 //struct process1Dresampling 00244 //{ 00245 // void operator()( const std::vector<rgba32f_t> src, const std::vector<F> weight, rgba32f_t & dst ) const 00246 // { 00247 // //... 00248 // } 00249 //}; 00250 00251 } 00252 00253 template <typename Sampler, typename DstP, typename SrcView, typename F> 00254 bool sample( Sampler& sampler, const SrcView& src, const point2<F>& p, DstP& result, const EParamFilterOutOfImage outOfImageProcess ) 00255 { 00256 typedef typename SrcView::value_type SrcP; 00257 typedef typename floating_pixel_from_view<SrcView>::type SrcC; //PixelFloat; 00258 typedef typename boost::gil::bits64f Weight; 00259 typedef typename SrcView::xy_locator xy_locator; 00260 00261 // xWeights and yWeights are weights for in relation of the distance to each point 00262 std::vector<Weight> xWeights, yWeights; 00263 00264 SrcC mp( 0 ); 00265 std::vector<SrcP> ptr; 00266 std::vector<SrcC> xProcessed; 00267 00268 /* 00269 * pTL is the closest integer coordinate top left from p 00270 * 00271 * pTL ---> x x 00272 * o <------ p 00273 * 00274 * x x 00275 */ 00276 point2<std::ptrdiff_t> pTL( ifloor( p ) ); 00277 00278 // loc is the point in the source view 00279 xy_locator loc = src.xy_at( pTL.x, pTL.y ); 00280 // frac is the distance between the point pTL and the current point 00281 point2<RESAMPLING_CORE_TYPE> frac( p.x - pTL.x, p.y - pTL.y ); 00282 00283 // assign Weights vector to the window size of the sampler 00284 xWeights.assign ( sampler._windowSize , 0 ); 00285 yWeights.assign ( sampler._windowSize , 0 ); 00286 00287 ptr.assign ( sampler._windowSize, SrcP(0) ); 00288 xProcessed.assign ( sampler._windowSize, SrcC(0) ); 00289 00290 // compute the middle position on the filter 00291 std::size_t middlePosition = floor( ( sampler._windowSize - 1.0 ) * 0.5 ); 00292 00293 // get weights for each pixels 00294 for( size_t i = 0; i < sampler._windowSize; i++ ) 00295 { 00296 RESAMPLING_CORE_TYPE distancex = - frac.x - middlePosition + i ; 00297 sampler( distancex, xWeights.at(i) ); 00298 RESAMPLING_CORE_TYPE distancey = - frac.y - middlePosition + i ; 00299 sampler( distancey, yWeights.at(i) ); 00300 } 00301 /* 00302 for( int i=0; i<xWeights.size(); i++ ) 00303 { 00304 std::cout << xWeights.at(i) << "\t" ; 00305 } 00306 std::cout << std::endl; 00307 */ 00308 // first process the middle point 00309 // if it's mirrored, we need to copy the center point 00310 if( (pTL.y < 0.0) || (pTL.y > (int) ( src.height( ) - 1.0 ) ) ) 00311 { 00312 if( pTL.y < 0.0 ) // under the image 00313 { 00314 switch( outOfImageProcess ) 00315 { 00316 case eParamFilterOutBlack : 00317 { 00318 xProcessed.at( middlePosition ) = get_black<DstP>(); 00319 break; 00320 } 00321 case eParamFilterOutTransparency : 00322 { 00323 xProcessed.at( middlePosition ) = SrcP(0); 00324 break; 00325 } 00326 case eParamFilterOutCopy : 00327 { 00328 loc.y( ) -= pTL.y; 00329 details::getPixelsPointers( loc, pTL, sampler._windowSize, src.width(), outOfImageProcess, ptr ); 00330 details::process1Dresampling<SrcP, Weight, SrcC> () ( ptr, xWeights, xProcessed.at( middlePosition ) ); 00331 loc.y( ) += pTL.y; 00332 break; 00333 } 00334 case eParamFilterOutMirror : 00335 { 00336 xProcessed.at( middlePosition ) = SrcP(1); 00337 break; 00338 } 00339 } 00340 } 00341 else // upper the image 00342 { 00343 //TUTTLE_LOG_INFO( src.height() << " @@ " << (pTL.y - src.height() ) ); 00344 switch( outOfImageProcess ) 00345 { 00346 case eParamFilterOutBlack : 00347 { 00348 xProcessed.at( middlePosition ) = get_black<DstP>(); 00349 break; 00350 } 00351 case eParamFilterOutTransparency : 00352 { 00353 xProcessed.at( middlePosition ) = SrcP(0); 00354 break; 00355 } 00356 case eParamFilterOutCopy : 00357 { 00358 loc.y( ) -= pTL.y - src.height() + 1.0 ; 00359 details::getPixelsPointers( loc, pTL, sampler._windowSize, src.width(), outOfImageProcess, ptr ); 00360 details::process1Dresampling<SrcP, Weight, SrcC> () ( ptr, xWeights, xProcessed.at( middlePosition ) ); 00361 loc.y( ) += pTL.y - src.height() + 1.0; 00362 break; 00363 } 00364 case eParamFilterOutMirror : 00365 { 00366 xProcessed.at( middlePosition ) = SrcP(1); 00367 break; 00368 } 00369 } 00370 } 00371 } 00372 else 00373 { 00374 details::getPixelsPointers( loc, pTL, sampler._windowSize, src.width() , outOfImageProcess, ptr ); 00375 details::process1Dresampling<SrcP, Weight, SrcC> () ( ptr, xWeights, xProcessed.at( middlePosition ) ); 00376 } 00377 00378 // from center to bottom 00379 for( int i = middlePosition - 1; i > -1; i-- ) 00380 { 00381 if( (int) ( pTL.y - (middlePosition - i) ) < (int) src.height( ) ) 00382 { 00383 if( (int) ( pTL.y - (middlePosition - i) ) < 0 ) 00384 { 00385 switch( outOfImageProcess ) 00386 { 00387 case eParamFilterOutBlack : 00388 { 00389 xProcessed.at( i ) = get_black<DstP>(); 00390 break; 00391 } 00392 case eParamFilterOutTransparency : 00393 { 00394 xProcessed.at( i ) = SrcP(0); 00395 break; 00396 } 00397 case eParamFilterOutCopy : 00398 { 00399 xProcessed.at( i ) = xProcessed.at( i + 1 ); 00400 break; 00401 } 00402 case eParamFilterOutMirror : 00403 { 00404 xProcessed.at( i ) = xProcessed.at( i + 1 ); 00405 break; 00406 } 00407 } 00408 } 00409 else 00410 { 00411 loc.y( ) -= (middlePosition - i); 00412 details::getPixelsPointers( loc, pTL, sampler._windowSize, src.width(), outOfImageProcess, ptr ); 00413 details::process1Dresampling<SrcP, Weight, SrcC> () ( ptr, xWeights, xProcessed.at( i ) ); 00414 loc.y( ) += (middlePosition - i); 00415 } 00416 } 00417 else 00418 { 00419 switch( outOfImageProcess ) 00420 { 00421 case eParamFilterOutBlack : 00422 { 00423 xProcessed.at( i ) = get_black<DstP>(); 00424 break; 00425 } 00426 case eParamFilterOutTransparency : 00427 { 00428 xProcessed.at( i ) = SrcP(0); 00429 break; 00430 } 00431 case eParamFilterOutCopy : 00432 { 00433 xProcessed.at( i ) = xProcessed.at( i + 1 ); 00434 break; 00435 } 00436 case eParamFilterOutMirror : 00437 { 00438 xProcessed.at( i ) = xProcessed.at( i + 1 ); 00439 break; 00440 } 00441 } 00442 } 00443 } 00444 00445 // from center to top 00446 for( int i = middlePosition + 1; i < (int)sampler._windowSize; i++ ) 00447 { 00448 if( (int) ( pTL.y + (i - middlePosition) ) < (int) src.height( ) ) 00449 { 00450 if( (int) ( pTL.y + (i - middlePosition) ) < 0 ) 00451 { 00452 xProcessed.at( i ) = xProcessed.at( i - 1 ); 00453 } 00454 else 00455 { 00456 loc.y( ) -= ( middlePosition - i ); 00457 details::getPixelsPointers( loc, pTL, sampler._windowSize, src.width(), outOfImageProcess, ptr ); 00458 details::process1Dresampling<SrcP, Weight, SrcC> () ( ptr, xWeights, xProcessed.at( i ) ); 00459 loc.y( ) += ( middlePosition - i ); 00460 } 00461 } 00462 else 00463 { 00464 switch( outOfImageProcess ) 00465 { 00466 case eParamFilterOutBlack : 00467 { 00468 xProcessed.at( i ) = get_black<DstP>(); 00469 break; 00470 } 00471 case eParamFilterOutTransparency : 00472 { 00473 xProcessed.at( i ) = SrcP(0); 00474 break; 00475 } 00476 case eParamFilterOutCopy : 00477 { 00478 xProcessed.at( i ) = xProcessed.at( i - 1 ); 00479 break; 00480 } 00481 case eParamFilterOutMirror : 00482 { 00483 xProcessed.at( i ) = xProcessed.at( i - 1 ); 00484 break; 00485 } 00486 } 00487 } 00488 } 00489 00490 // vertical process 00491 details::process1Dresampling<SrcC, Weight, SrcC> () ( xProcessed, yWeights, mp ); 00492 00493 // Convert from floating point average value to the destination type 00494 color_convert( mp, result ); 00495 00496 return true; 00497 } 00498 00499 } 00500 } 00501 00502 #endif