TuttleOFX  1
details.hpp
Go to the documentation of this file.
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