mot_comp.cpp

00001 /* ***** BEGIN LICENSE BLOCK *****
00002 *
00003 * $Id: mot_comp.cpp,v 1.3 2005/01/30 05:11:40 gabest Exp $ $Name:  $
00004 *
00005 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006 *
00007 * The contents of this file are subject to the Mozilla Public License
00008 * Version 1.1 (the "License"); you may not use this file except in compliance
00009 * with the License. You may obtain a copy of the License at
00010 * http://www.mozilla.org/MPL/
00011 *
00012 * Software distributed under the License is distributed on an "AS IS" basis,
00013 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
00014 * the specific language governing rights and limitations under the License.
00015 *
00016 * The Original Code is BBC Research and Development code.
00017 *
00018 * The Initial Developer of the Original Code is the British Broadcasting
00019 * Corporation.
00020 * Portions created by the Initial Developer are Copyright (C) 2004.
00021 * All Rights Reserved.
00022 *
00023 * Contributor(s): Richard Felton (Original Author), 
00024 *                 Thomas Davies,
00025 *                 Steve Bearcroft
00026 *
00027 * Alternatively, the contents of this file may be used under the terms of
00028 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
00029 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
00030 * the GPL or the LGPL are applicable instead of those above. If you wish to
00031 * allow use of your version of this file only under the terms of the either
00032 * the GPL or LGPL and not to allow others to use your version of this file
00033 * under the MPL, indicate your decision by deleting the provisions above
00034 * and replace them with the notice and other provisions required by the GPL
00035 * or LGPL. If you do not delete the provisions above, a recipient may use
00036 * your version of this file under the terms of any one of the MPL, the GPL
00037 * or the LGPL.
00038 * ***** END LICENSE BLOCK ***** */
00039 
00040 
00041 #include <libdirac_common/mot_comp.h>
00042 #include <libdirac_common/motion.h>
00043 #include <libdirac_common/frame_buffer.h>
00044 using namespace dirac;
00045 
00046 using std::vector;
00047 
00048 //--public member functions--//
00050 
00051 
00052 //Constructor
00053 //Initialises the lookup table that is needed for 1/8th pixel accuracy
00054 //motion estimation. Creates the necessary arithmetic objects and
00055 //calls ReConfig to create weighting blocks to fit the values within
00056 //m_cparams.
00057 MotionCompensator::MotionCompensator( const CodecParams &cp , const AddOrSub direction ): 
00058     m_cparams(cp),
00059     luma_or_chroma(true),
00060     m_add_or_sub( direction )
00061 {
00062     //Configure weighting blocks for the first time
00063     m_block_weights = NULL;
00064     m_half_block_weights = NULL;
00065     ReConfig();
00066 }
00067 
00068 //Destructor
00069 MotionCompensator::~MotionCompensator(){
00070 
00071     //Tidy up the pointers
00072     delete[] m_block_weights;
00073     delete[] m_half_block_weights;
00074 }
00075 
00076 //Called to perform motion compensated addition/subtraction on an entire frame.
00077 void MotionCompensator::CompensateFrame(FrameBuffer& my_buffer,int fnum,const MvData& mv_data)
00078 {
00079 
00080      int ref1_idx,ref2_idx;    
00081      Frame& my_frame=my_buffer.GetFrame(fnum);
00082      const FrameSort& fsort=my_frame.GetFparams().FSort();
00083 
00084      m_cformat = my_frame.GetFparams().CFormat();
00085 
00086      if (fsort!=I_frame)
00087      {//we can motion compensate
00088 
00089          const vector<int>& refs=my_frame.GetFparams().Refs();
00090          if (refs.size()>0)
00091          {
00092              //extract the references
00093              ref1_idx=refs[0];
00094              if (refs.size()>1)
00095                  ref2_idx=refs[1];
00096              else
00097                  ref2_idx=refs[0];
00098 
00099              const Frame& ref1frame=my_buffer.GetFrame(ref1_idx);
00100              const Frame& ref2frame=my_buffer.GetFrame(ref2_idx);
00101 
00102              luma_or_chroma = true;                
00103              //now do all the components
00104              CompensateComponent( my_frame , ref1frame , ref2frame , mv_data , Y_COMP);
00105 
00106              if ( m_cformat != Yonly )
00107              {
00108                  luma_or_chroma = false;                
00109                  CompensateComponent( my_frame , ref1frame , ref2frame , mv_data , U_COMP);
00110                  CompensateComponent( my_frame , ref1frame , ref2frame , mv_data , V_COMP);
00111              }
00112          }
00113      }
00114 }
00115 
00116 //--private member functions--//
00118 
00119 //Needs to be called if the blocksize changes (and
00120 //on startup). This method creates an array of weighting
00121 //blocks that are used to acheive correctly overlapping
00122 //blocks.
00123 void MotionCompensator::ReConfig()
00124 {
00125     if (luma_or_chroma)
00126         m_bparams = m_cparams.LumaBParams(2);
00127     else
00128         m_bparams = m_cparams.ChromaBParams(2);
00129 
00130     if(m_block_weights != NULL)
00131         delete[] m_block_weights;
00132 
00133     if(m_half_block_weights != NULL)
00134         delete[] m_half_block_weights;
00135 
00136     // Create new weights array.
00137     m_block_weights = new TwoDArray<CalcValueType>[9];
00138     m_half_block_weights = new TwoDArray<CalcValueType>[9];
00139     for(int i = 0; i < 9; i++)
00140     {
00141         m_block_weights[i].Resize(  m_bparams.Yblen() , m_bparams.Xblen() );
00142         m_half_block_weights[i].Resize(  m_bparams.Yblen() , m_bparams.Xblen() );
00143     }
00144     // We can create all nine weighting blocks by calculating values
00145     // for four blocks and mirroring them to generate the others.
00146     CreateBlock( m_bparams , false , false , m_half_block_weights[0] );
00147     CreateBlock( m_bparams , false , true , m_half_block_weights[3] );
00148     CreateBlock( m_bparams , true , false , m_half_block_weights[1] );
00149     CreateBlock( m_bparams , true , true , m_half_block_weights[4] );
00150 
00151     // Note order of flipping is important.    
00152     FlipX( m_half_block_weights[3] , m_bparams , m_half_block_weights[5] );
00153     FlipX( m_half_block_weights[0] , m_bparams , m_half_block_weights[2] );
00154     FlipY( m_half_block_weights[0] , m_bparams , m_half_block_weights[6] );
00155     FlipX( m_half_block_weights[6] , m_bparams , m_half_block_weights[8] );
00156     FlipY( m_half_block_weights[1] , m_bparams , m_half_block_weights[7] );
00157 
00158     for( int k = 0; k < 9; k++)
00159     {
00160         for ( int j =m_half_block_weights[k].FirstY(); j <= m_half_block_weights[k].LastY(); j++)
00161         {
00162             for ( int i =m_half_block_weights[k].FirstX(); i <= m_half_block_weights[k].LastX(); i++)
00163             {
00164                 m_block_weights[k][j][i] = m_half_block_weights[k][j][i] << 1;
00165             }// i
00166         }// j
00167     }// k
00168 }
00169 
00170 void MotionCompensator::CompensateComponent(Frame& picframe, const Frame &ref1frame, const Frame& ref2frame,
00171     const MvData& mv_data,const CompSort cs)
00172 {
00173     // Set up references to pictures and references
00174     PicArray& pic_data_out = picframe.Data( cs );
00175 
00176     const PicArray& ref1up = ref1frame.UpData( cs );
00177     const PicArray& ref2up = ref2frame.UpData( cs );
00178 
00179     // Set up another picture which will contain the MC data, which
00180     // we'll add or subtract to pic_data_out
00181     TwoDArray<CalcValueType> pic_data(pic_data_out.LengthY(), pic_data_out.LengthX() , 0);
00182 
00183     // Factors to compensate for subsampling of chroma
00184     int xscale_factor = 1;
00185     int yscale_factor = 1;
00186 
00187     if ( cs != Y_COMP )
00188     {
00189         if (m_cformat == format420)
00190         {
00191             xscale_factor = 2;
00192             yscale_factor = 2;
00193         }
00194         else if (m_cformat == format422)
00195         {
00196             xscale_factor = 2;
00197             yscale_factor = 1;
00198         }
00199         else if (m_cformat == format411)
00200         {
00201             xscale_factor = 4;
00202             yscale_factor = 1;
00203         }
00204 
00205     } 
00206 
00207     // Reference to the relevant DC array
00208     const TwoDArray<ValueType>& dcarray = mv_data.DC( cs );
00209 
00210     // Set up references to the vectors
00211     const int num_refs = picframe.GetFparams().Refs().size();
00212     const MvArray* mv_array1; 
00213     const MvArray* mv_array2;
00214     mv_array1 = &mv_data.Vectors(1);
00215     if (num_refs ==2 )
00216         mv_array2 = &mv_data.Vectors(2);
00217     else
00218         mv_array2 = &mv_data.Vectors(1);
00219 
00220     ReConfig();//set all the weighting blocks up    
00221 
00222     //Blocks are listed left to right, line by line.
00223     MVector mv1,mv2;
00224     PredMode block_mode;
00225     ValueType dc;
00226 
00227     //Coords of the top-left corner of a block
00228     ImageCoords pos;
00229 
00230     //Loop for each block in the output image.
00231     //The CompensateBlock function will use the image pointed to by ref1up
00232     //and add the compensated pixels to the image pointed to by pic_data.
00233     size_t wgt_idx;
00234 
00235     //Loop over all the block rows
00236 
00237     pos.y = -m_bparams.Yoffset();
00238     for(int yblock = 0; yblock < m_cparams.YNumBlocks(); ++yblock)
00239     {
00240         pos.x = -m_bparams.Xoffset();
00241         //loop over all the blocks in a row
00242         for(int xblock = 0 ; xblock < m_cparams.XNumBlocks(); ++xblock)
00243         {
00244 
00245             //Decide which weights to use.
00246             if((xblock != 0)&&(xblock < m_cparams.XNumBlocks() - 1))
00247             {
00248                 if((yblock != 0)&&(yblock < m_cparams.YNumBlocks() - 1))    
00249                     wgt_idx = 4;
00250                 else if(yblock == 0) 
00251                     wgt_idx = 1;
00252                 else 
00253                     wgt_idx= 7;
00254             }
00255             else if(xblock == 0)
00256             {
00257                 if((yblock != 0)&&(yblock < m_cparams.YNumBlocks() - 1))    
00258                     wgt_idx = 3;
00259                 else if(yblock == 0) 
00260                     wgt_idx = 0;
00261                 else 
00262                     wgt_idx = 6;
00263             }
00264             else
00265             {
00266                 if((yblock != 0)&&(yblock < m_cparams.YNumBlocks() - 1))    
00267                     wgt_idx = 5;
00268                 else if(yblock == 0) 
00269                     wgt_idx = 2;
00270                 else 
00271                     wgt_idx = 8;
00272             }
00273 
00274             block_mode = mv_data.Mode()[yblock][xblock];
00275             mv1 = (*mv_array1)[yblock][xblock];
00276             mv1.x /= xscale_factor;
00277             mv1.y /= yscale_factor;
00278 
00279             mv2 = (*mv_array2)[yblock][xblock];
00280             mv2.x /= xscale_factor;
00281             mv2.y /= yscale_factor;
00282 
00283 
00284             dc = dcarray[yblock][xblock]<<2;// DC is only given 8 bits, 
00285                                             // so need to shift to get 10-bit data
00286 
00287             if(block_mode == REF1_ONLY)
00288             {
00289                 CompensateBlock(pic_data, ref1up, mv1, pos, m_block_weights[wgt_idx]);
00290             }
00291             else if (block_mode == REF2_ONLY)
00292             {                
00293                 CompensateBlock(pic_data, ref2up, mv2, pos, m_block_weights[wgt_idx]);
00294             }
00295             else if(block_mode == REF1AND2)
00296             {
00297                 CompensateBlock(pic_data, ref1up, mv1, pos, m_half_block_weights[wgt_idx]);
00298                 CompensateBlock(pic_data, ref2up, mv2, pos, m_half_block_weights[wgt_idx]);                    
00299             }
00300             else
00301             {//we have a DC block.
00302                 DCBlock(pic_data, dc,pos, m_block_weights[wgt_idx]);
00303             }
00304 
00305             //Increment the block horizontal position
00306             pos.x += m_bparams.Xbsep();
00307 
00308         }//xblock
00309 
00310         //Increment the block vertical position
00311         pos.y += m_bparams.Ybsep();
00312 
00313     }//yblock
00314 
00315     if ( m_add_or_sub == SUBTRACT)
00316     {
00317         int x_end_data = std::min(pic_data.LastX(), m_cparams.XNumBlocks()*m_bparams.Xbsep() );
00318         int y_end_data = std::min(pic_data.LastY(), m_cparams.YNumBlocks()*m_bparams.Ybsep() );
00319 
00320         for ( int i =pic_data.FirstY(); i <= y_end_data; i++)
00321         {
00322             for ( int j =pic_data.FirstX(); j <= x_end_data; ++j)
00323             {
00324                 pic_data_out[i][j] -= static_cast<ValueType>( (pic_data[i][j] + 1024) >> 11 );
00325             }
00326  
00327             // Okay, we've done all the actual blocks. Now if the picture is further padded
00328             // we need to set the padded values to zero beyond the last block in the row,
00329             // for all the picture lines in the block row. Need only do this when we're
00330             // subtracting.
00331 
00332             for (int j=( m_cparams.XNumBlocks()*m_bparams.Xbsep() ); j<pic_data.LengthX() ; ++j )
00333             {
00334                 pic_data_out[i][j] = 0;
00335             }
00336         }
00337         // Finally, now we've done all the blocks, we must set all padded lines below 
00338         // the last row equal to 0, if we're subtracting
00339         for ( int y=m_cparams.YNumBlocks()*m_bparams.Ybsep() ; y<pic_data.LengthY() ; ++y )
00340         {
00341             for ( int x=0 ; x<pic_data.LengthX() ; ++x )
00342             {
00343                 pic_data_out[y][x] = 0;
00344             }
00345 
00346         }
00347     }
00348     else
00349     {
00350         for ( int i =pic_data.FirstY(); i <= pic_data.LastY(); i++)
00351         {
00352             for ( int j =pic_data.FirstX(); j <= pic_data.LastX(); j++)
00353             {
00354                 pic_data_out[i][j] += static_cast<ValueType>( (pic_data[i][j] + 1024) >> 11 );
00355             }
00356         }
00357     }
00358 }
00359 
00360 void MotionCompensator::CompensateBlock( TwoDArray<CalcValueType> &pic_data , const PicArray &refup_data , const MVector &mv , 
00361 const ImageCoords& pos , const TwoDArray<CalcValueType>& wt_array )
00362 {
00363 
00364     //Coordinates in the image being written to.
00365     const ImageCoords start_pos( std::max(pos.x,0) , std::max(pos.y,0) );
00366     const ImageCoords end_pos( std::min( pos.x + m_bparams.Xblen() , pic_data.LengthX() ) , 
00367                                std::min( pos.y + m_bparams.Yblen() , pic_data.LengthY() ) );
00368 
00369     //The difference between the desired start point
00370     //pos and the actual start point start_pos.
00371     const ImageCoords diff( start_pos.x - pos.x , start_pos.y - pos.y );
00372 
00373     //Set up the start point in the reference image by rounding the motion vector
00374     //NB: bit shift rounds negative values DOWN, as required
00375     const MVector roundvec( mv.x>>2 , mv.y>>2 );
00376 
00377     //Get the remainder after rounding. NB rmdr values always 0,1,2 or 3
00378     const MVector rmdr( mv.x - ( roundvec.x<<2 ) , mv.y - ( roundvec.y<<2 ) );
00379 
00380     //Where to start in the upconverted image
00381     const ImageCoords ref_start( ( start_pos.x<<1 ) + roundvec.x ,( start_pos.y<<1 ) + roundvec.y );
00382 
00383     //weights for doing linear interpolation, calculated from the remainder values
00384     const ValueType TLweight( (4 - rmdr.x) * (4 - rmdr.y) );
00385     const ValueType TRweight( rmdr.x * ( 4 - rmdr.y ) );
00386     const ValueType BLweight( ( 4 - rmdr.x ) * rmdr.y );
00387     const ValueType BRweight( rmdr.x * rmdr.y );
00388 
00389     //An additional stage to make sure the block to be copied does not fall outside
00390     //the reference image.
00391     const int refXlen = refup_data.LengthX();
00392     const int refYlen = refup_data.LengthY();
00393     bool do_bounds_checking = false;
00394 
00395     //Check if there are going to be any problems copying the block from
00396     //the upvconverted reference image.
00397     if( ref_start.x < 0 ) 
00398         do_bounds_checking = true;
00399     else if( ref_start.x + ((end_pos.x - start_pos.x)<<1 ) >= refXlen )
00400         do_bounds_checking = true;
00401     if( ref_start.y < 0 ) 
00402         do_bounds_checking = true;
00403     else if( ref_start.y + ((end_pos.y - start_pos.y)<<1 ) >= refYlen)
00404         do_bounds_checking = true;
00405 
00406      if( !do_bounds_checking )
00407      {
00408          for(int c = start_pos.y, wY = diff.y, uY = ref_start.y; c < end_pos.y; ++c, ++wY, uY += 2)
00409          {
00410              for(int l = start_pos.x, wX = diff.x, uX = ref_start.x; l < end_pos.x; ++l, ++wX, uX += 2)
00411              {
00412 
00413                  pic_data[c][l] += (( TLweight * refup_data[uY][uX] +
00414                           TRweight * refup_data[uY][uX+1] +
00415                           BLweight * refup_data[uY+1][uX] +
00416                           BRweight * refup_data[uY+1][uX+1] +
00417                           8
00418                           ) >> 4) * wt_array[wY][wX];
00419              }//l
00420          }//c
00421      }
00422      else
00423      {
00424          //We're doing bounds checking because we'll fall off the edge of the reference otherwise.
00425 
00426         for(int c = start_pos.y, wY = diff.y, uY = ref_start.y,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen);
00427             c < end_pos.y; ++c, ++wY, uY += 2,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen))
00428         {
00429             for(int l = start_pos.x, wX = diff.x, uX = ref_start.x,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen);
00430                 l < end_pos.x; ++l, ++wX, uX += 2,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen))
00431             {
00432 
00433                 pic_data[c][l] += (( TLweight * refup_data[BuY][BuX] +
00434                          TRweight * refup_data[BuY][BuX1]  +
00435                          BLweight * refup_data[BuY1][BuX]+
00436                          BRweight * refup_data[BuY1][BuX1] +
00437                          8
00438                          ) >> 4) * wt_array[wY][wX];
00439             }//l
00440         }//c
00441 
00442     }
00443 
00444 }
00445 
00446 void MotionCompensator::DCBlock( TwoDArray<CalcValueType> &pic_data ,const ValueType dc , const ImageCoords& pos ,
00447     const TwoDArray<CalcValueType>& wt_array)
00448 {
00449 
00450     //Coordinates in the image being written to.
00451     const ImageCoords start_pos( std::max(0 , pos.x) , std::max(0 , pos.y) );
00452     const ImageCoords end_pos( std::min(pos.x + m_bparams.Xblen() , pic_data.LengthX() ) , 
00453                                std::min(pos.y + m_bparams.Yblen() , pic_data.LengthY() ) );
00454 
00455     //The difference between the desired start point
00456     //pos and the actual start point start_pos.
00457     const ImageCoords diff(start_pos.x - pos.x , start_pos.y - pos.y);
00458 
00459     //Quick process where we can just copy from the double size image.
00460 
00461     for(int c = start_pos.y, wY = diff.y; c < end_pos.y; ++c, ++wY)
00462     {
00463         for(int l = start_pos.x, wX = diff.x; l < end_pos.x; ++l, ++wX)
00464         {
00465             pic_data[c][l] += dc * wt_array[wY][wX];
00466         }
00467     }
00468 }
00469 
00470 //Overlapping blocks are acheived by applying a 2D raised cosine shape
00471 //to them. This function facilitates the calculations
00472 float MotionCompensator::RaisedCosine(float t, float B)
00473 {
00474     if(std::abs(t)>(B+1.0)/2.0) 
00475         return 0.0f;
00476     else if(std::abs(t)<(1.0-B)/2.0) 
00477         return 1.0f;
00478     else 
00479         return( 0.5 * ( 1.0 + std::cos( 3.141592654 * ( std::abs(t)-(1.0-B)/2.0 )/B ) ) );
00480 }
00481 
00482 //Calculates a weighting block.
00483 //bparams defines the block parameters so the relevant weighting arrays can be created.
00484 //FullX and FullY refer to whether the weight should be adjusted for the edge of an image.
00485 //eg. 1D Weighting shapes in x direction
00486 
00487 //  FullX true        FullX false
00488 //     ***           ********
00489 //   *     *                  *
00490 //  *       *                  *
00491 //*           *                  *
00492 
00493 void MotionCompensator::CreateBlock(const OLBParams &bparams, bool FullX, bool FullY, TwoDArray<CalcValueType>& WeightArray)
00494 {
00495     // Create temporary arrays
00496     OneDArray<CalcValueType> HWts( WeightArray.LengthX() );
00497     OneDArray<CalcValueType> VWts( WeightArray.LengthY() );
00498 
00499     // Calculation variables
00500     float rolloffX = (float(bparams.Xblen()+1)/float(bparams.Xbsep())) - 1;
00501     float rolloffY = (float(bparams.Yblen()+1)/float(bparams.Ybsep())) - 1;
00502     float val;
00503 
00504     // Window in the x direction
00505     for(int x = 0; x < bparams.Xblen(); ++x)
00506     {
00507         val = (float(x) - (float(bparams.Xblen()-1)/2.0))/float(bparams.Xbsep());
00508         HWts[x] = static_cast<CalcValueType>( 32.0 * RaisedCosine(val,rolloffX) );
00509         HWts[x] = std::max( HWts[x] , 1 );
00510         HWts[x] = std::min( HWts[x] , 32 );
00511     }// x
00512 
00513     // Window in the y direction
00514     for(int y = 0; y < bparams.Yblen(); ++y)
00515     {
00516         val = (float(y) - (float(bparams.Yblen()-1)/2.0))/float(bparams.Ybsep());
00517         VWts[y] = static_cast<CalcValueType>( 32.0 * RaisedCosine(val,rolloffY) );
00518         VWts[y] = std::max( VWts[y] , 1 );
00519         VWts[y] = std::min( VWts[y] , 32 );
00520     }// y
00521 
00522     // Rationalise to avoid rounding errors
00523     for(int x = HWts.Last(); x > HWts.Last()-bparams.Xoffset(); --x)
00524     {
00525         if (HWts[x] + HWts[HWts.Last()-(x-bparams.Xbsep())] > 32)
00526             HWts[HWts.Last()-(x-bparams.Xbsep())] = 32-HWts[x];
00527             
00528         else if (HWts[x] + HWts[HWts.Last()-(x-bparams.Xbsep())] < 32)
00529             HWts[x] = 32-HWts[HWts.Last()-(x-bparams.Xbsep())];
00530     }// x 
00531 
00532     // Now reflect or pad, as appropriate
00533     if (!FullX)
00534     {
00535         for( int x = 0; x < (bparams.Xblen()>>1) ; ++x)
00536             HWts[x] = 32;
00537     }
00538     else
00539     {
00540         for( int x = 0; x < (bparams.Xblen()>>1); ++x)
00541             HWts[x] = HWts[HWts.Last()-x];
00542     }
00543 
00544     // Rationalise to avoid rounding errors
00545     for(int y = VWts.Last(); y > VWts.Last()-bparams.Yoffset(); --y)
00546     {
00547         if (VWts[y] + VWts[VWts.Last()-(y-bparams.Ybsep())] > 32)
00548             VWts[VWts.Last()-(y-bparams.Ybsep())] = 32-VWts[y];
00549         else if (VWts[y] + VWts[VWts.Last()-(y-bparams.Ybsep())] < 32)
00550             VWts[y] = 32-VWts[VWts.Last()-(y-bparams.Ybsep())];
00551     }// x 
00552 
00553     // Reflect or pad, as appropriate
00554     if (!FullY)
00555     {
00556         for( int y = 0 ; y < (bparams.Yblen()>>1); ++y)
00557             VWts[y] = 32;
00558     }
00559     else
00560     {
00561         for( int y = 0 ; y < (bparams.Yblen()>>1); ++y)
00562             VWts[y] = VWts[VWts.Last()-y];
00563     }
00564 
00565     for(int y = 0; y < bparams.Yblen(); ++y)
00566     {
00567         for(int x = 0; x < bparams.Xblen(); ++x)
00568         {
00569             WeightArray[y][x] = VWts[y] * HWts[x];
00570         }// x
00571     }// y
00572 
00573 }
00574 
00575 //Flips the values in an array in the x direction.
00576 void MotionCompensator::FlipX(const TwoDArray<CalcValueType>& Original, const OLBParams &bparams, TwoDArray<CalcValueType>& Flipped)
00577 {
00578     for(int x = 0; x < bparams.Xblen(); ++x)
00579     {
00580         for(int y = 0; y < bparams.Yblen(); ++y)
00581         {
00582             Flipped[y][x] = Original[y][(bparams.Xblen()-1) - x];
00583         }// y
00584     }// x
00585 }
00586 
00587 //Flips the values in an array in the y direction.
00588 void MotionCompensator::FlipY(const TwoDArray<CalcValueType>& Original, const OLBParams &bparams, TwoDArray<CalcValueType>& Flipped)
00589 {
00590     for(int x = 0; x < bparams.Xblen(); ++x)
00591     {
00592         for(int y = 0; y < bparams.Yblen(); ++y)
00593         {
00594             Flipped[y][x] = Original[(bparams.Yblen()-1) - y][x];
00595         }// y
00596     }// x
00597 }

Generated on Tue Dec 13 14:47:13 2005 for guliverkli by  doxygen 1.4.5