source: 3DVCSoftware/trunk/source/Lib/TLibRenderer/TRenFilter.cpp @ 2

Last change on this file since 2 was 2, checked in by hhi, 13 years ago

inital import

  • Property svn:eol-style set to native
File size: 48.5 KB
Line 
1
2
3#include "TRenImage.h"
4#include "TRenFilter.h"
5#include "../TLibCommon/TComPredFilter.h"
6
7
8///// COMMON /////
9Void TRenFilter::setSubPelShiftLUT( Int iLutPrec, Int** piSubPelShiftLUT, Int iShift )
10{
11  //ToDo: use same rounding for left and right
12  AOT( iLutPrec < 0 || iLutPrec > 2 );
13  Int iStep = 1 << iLutPrec;
14  for (Int iDelta = 0; iDelta < (iStep << 1)+1; iDelta++ )
15  {
16    for (Int iCurDelta = 0; iCurDelta < (iStep << 1)+1; iCurDelta++ )
17    {
18      if (iCurDelta <= iDelta)
19      {
20        piSubPelShiftLUT[iDelta][iCurDelta] =  (iDelta != 0) ?( ( iStep * iCurDelta + ( iDelta >> 1) )/ iDelta) + iShift * iStep :  iShift * iStep;
21      }
22      else
23      {
24        piSubPelShiftLUT[iDelta][iCurDelta] = 0xdeaddead;
25      }
26    }
27  }
28}
29
30Void TRenFilter::setupZLUT( Bool bBlendUseDistWeight, Int iBlendZThresPerc, Int iRelDistToLeft, Int** ppiBaseShiftLUTLeft, Int** ppiBaseShiftLUTRight, Int& riBlendZThres, Int& riBlendDistWeight, Int* piInvZLUTLeft, Int* piInvZLUTRight )
31{
32  AOT( iRelDistToLeft == -1 );
33  riBlendDistWeight = bBlendUseDistWeight ? iRelDistToLeft :  1 << (REN_VDWEIGHT_PREC - 1);
34
35  for (UInt uiDepthValue = 0; uiDepthValue <= 256; uiDepthValue++)
36  {
37    //GT: retrieve depth approx from shift
38    piInvZLUTLeft [uiDepthValue] = abs( ppiBaseShiftLUTLeft [0][uiDepthValue] );
39    piInvZLUTRight[uiDepthValue] = abs( ppiBaseShiftLUTRight[0][uiDepthValue] );
40  }
41  // Set Threshold
42  riBlendZThres  = ( max( abs(piInvZLUTLeft[0]- piInvZLUTLeft[255]), abs(piInvZLUTRight[0]- piInvZLUTRight[255]) ) * iBlendZThresPerc + 50)  / 100;
43}
44
45Void TRenFilter::filledToUsedPelMap( PelImage* pcFilledImage, PelImage* pcUsedPelsImage, Int iUsedPelMapMarExt )
46{
47  // Convert to binary map
48  Int iWidth  = pcFilledImage      ->getPlane(0)->getWidth ();
49  Int iHeight = pcFilledImage      ->getPlane(0)->getHeight();
50
51  AOT( iWidth  != pcUsedPelsImage  ->getPlane(0)->getWidth () );
52  AOT( iHeight != pcUsedPelsImage  ->getPlane(0)->getHeight() );
53  AOF( pcUsedPelsImage->is420() );
54
55  Int iSrcStride  = pcFilledImage  ->getPlane(0)->getStride();
56  Int iDstStrideY = pcUsedPelsImage->getPlane(0)->getStride();
57  Int iDstStrideU = pcUsedPelsImage->getPlane(1)->getStride();
58  Int iDstStrideV = pcUsedPelsImage->getPlane(2)->getStride();
59
60  Pel* pcSrcData  = pcFilledImage  ->getPlane(0)->getPlaneData();
61  Pel* pcDstDataY = pcUsedPelsImage->getPlane(0)->getPlaneData();
62  Pel* pcDstDataU = pcUsedPelsImage->getPlane(1)->getPlaneData();
63  Pel* pcDstDataV = pcUsedPelsImage->getPlane(2)->getPlaneData(); // Only used as buffer
64
65  for (Int iPosY = 0; iPosY < iHeight; iPosY++ )
66  {
67    for (Int iPosX = 0; iPosX < iWidth; iPosX++ )
68    {
69      pcDstDataY[iPosX] = ( pcSrcData[iPosX] != REN_IS_FILLED ) ? REN_USED_PEL : REN_UNUSED_PEL;
70
71      if ((iPosX & 1) && (iPosY & 1))
72      {
73        pcDstDataU[iPosX >> 1] = (   ( pcSrcData[iPosX                 ] != REN_IS_FILLED )
74          || ( pcSrcData[iPosX - 1             ] != REN_IS_FILLED )
75          || ( pcSrcData[iPosX     - iSrcStride] != REN_IS_FILLED )
76          || ( pcSrcData[iPosX - 1 - iSrcStride] != REN_IS_FILLED )
77          ) ? REN_USED_PEL : REN_UNUSED_PEL;
78      }
79    }
80
81    if ( iPosY & 1 )
82    {
83      pcDstDataU += iDstStrideU;
84    }
85
86    pcDstDataY += iDstStrideY;
87    pcSrcData  += iSrcStride;
88  }
89
90  //// Dilatation for Interpolation Filters ////
91  //GT: should better be defined somewhere else ...
92  const Int iLumaIntFiltHalfSize   = 4;
93  const Int iChromaIntFiltHalfSize = 2;
94
95  Int iDilateSizeLuma   = iLumaIntFiltHalfSize   +   iUsedPelMapMarExt      ;
96  Int iDilateSizeChroma = iChromaIntFiltHalfSize + ( iUsedPelMapMarExt >> 1);
97
98  pcDstDataY = pcUsedPelsImage->getPlane(0)->getPlaneData();
99  pcDstDataU = pcUsedPelsImage->getPlane(1)->getPlaneData();
100  pcDstDataV = pcUsedPelsImage->getPlane(2)->getPlaneData();
101
102  // Dilate Luma horizontally
103  xDilate( pcDstDataY, iDstStrideY, iWidth, iHeight, pcDstDataY, iDstStrideY, iDilateSizeLuma, false, true  );
104  xDilate( pcDstDataY, iDstStrideY, iWidth, iHeight, pcDstDataY, iDstStrideY, iDilateSizeLuma, false, false );
105
106  // Dilate Chorma vertically and horizontally (for UV-up)
107  xDilate( pcDstDataU, iDstStrideU, iWidth>>1, iHeight>>1, pcDstDataU, iDstStrideU, iDilateSizeChroma, false, true  );
108  xDilate( pcDstDataU, iDstStrideU, iWidth>>1, iHeight>>1, pcDstDataU, iDstStrideU, iDilateSizeChroma, false, false );
109
110  xDilate( pcDstDataU, iDstStrideU, iWidth>>1, iHeight>>1, pcDstDataU, iDstStrideU, iChromaIntFiltHalfSize, true, true  );
111  xDilate( pcDstDataU, iDstStrideU, iWidth>>1, iHeight>>1, pcDstDataU, iDstStrideU, iChromaIntFiltHalfSize, true, false );
112
113  for (Int iPosY = 0; iPosY < (iHeight >> 1); iPosY++ )
114  {
115    for (Int iPosX = 0; iPosX < (iWidth >> 1); iPosX++ )
116    {
117      pcDstDataV[iPosX] = pcDstDataU[iPosX];
118    }
119
120    pcDstDataU += iDstStrideU;
121    pcDstDataV += iDstStrideV;
122  }
123}
124
125/////////// Copy /////////////
126Void TRenFilter::copy(Pel* pcInputPlaneData, Int iInputStride, Int iWidth, Int iHeight, Pel* pcOutputPlaneData, Int iOutputStride  )
127{
128  xDistributeArray(pcInputPlaneData, iInputStride, 1, 1, iWidth, iHeight ,pcOutputPlaneData, iOutputStride, 1 , 1 );
129
130}
131
132/////////// Horizontal Mirror ///////////
133template <typename T>
134Void TRenFilter::mirrorHor( TRenImage<T> *pcImage )
135{
136  for (UInt uCurPlane = 0 ; uCurPlane < pcImage->getNumberOfPlanes(); uCurPlane++ )
137  {
138    mirrorHor( pcImage->getPlane(uCurPlane) );
139  }
140}
141
142template <typename T>
143Void TRenFilter::mirrorHor( TRenImagePlane<T> *pcImagePlane )
144{
145  T* pcPlaneData = pcImagePlane->getPlaneDataOrg();
146  T cTemp;
147  UInt uiStride = pcImagePlane->getStride();
148  UInt uiHeight = pcImagePlane->getHeightOrg();
149  UInt uiWidth  = pcImagePlane->getWidthOrg();
150
151  for (UInt uiPosY = 0; uiPosY < uiHeight; uiPosY++)
152  {
153    for (UInt uiPosX = 0; uiPosX < ( (uiWidth+1) >> 1); uiPosX++ )
154    {
155      cTemp = pcPlaneData[uiPosX];
156      pcPlaneData[uiPosX] = pcPlaneData[uiWidth - uiPosX-1];
157      pcPlaneData[uiWidth-uiPosX-1] = cTemp;
158    }
159    pcPlaneData += uiStride;
160  }
161}
162
163/////////// Comparison ///////////
164Int64 TRenFilter::SSE   (PelImagePlane* pcInputPlane1, PelImagePlane* pcInputPlane2   )
165{
166  UInt uiWidth     = pcInputPlane1->getWidth();
167  UInt uiHeight    = pcInputPlane1->getHeight();
168
169  UInt uiStride1   = pcInputPlane1->getStride();
170  UInt uiStride2   = pcInputPlane2->getStride();
171
172  Pel* pucImData1  = pcInputPlane1->getPlaneData();
173  Pel* pucImData2  = pcInputPlane2->getPlaneData();
174
175  return SSE( pucImData1, (Int) uiStride1, (Int) uiWidth, (Int) uiHeight, pucImData2, (Int) uiStride2 );
176}
177
178Int64 TRenFilter::SSE( Pel* piSrc1, Int iSrcStride1, Int iWidth, Int iHeight,  Pel* piSrc2, Int iSrcStride2 )
179{
180  Int64 iSSE = 0;
181
182  Int iShift = g_uiBitIncrement << 1;
183  for(Int iPosY = 0; iPosY < iHeight; iPosY++)
184  {
185    for(Int iPosX = 0; iPosX < iWidth; iPosX++)
186    {
187      Int iDiff = ( piSrc1[iPosX] - piSrc2[iPosX] );
188      iSSE += (( iDiff * iDiff ) >> iShift);
189    }
190    piSrc1 += iSrcStride1;
191    piSrc2 += iSrcStride2;
192  }
193  return iSSE;
194}
195
196template <typename T>
197Bool TRenFilter::compare( TRenImage<T> *pInputImage1, TRenImage<T> *pInputImage2 )
198{
199  Bool bIsEqual = true;
200  for (UInt uiCurPlane = 0 ; uiCurPlane < pInputImage1->getNumberOfPlanes(); uiCurPlane++ )
201  {
202    bIsEqual = bIsEqual && compare(pInputImage1->getPlane(uiCurPlane), pInputImage2->getPlane(uiCurPlane));
203  }
204  return bIsEqual;
205}
206
207template <typename T>
208Bool TRenFilter::compare   (TRenImagePlane<T>* pcInputPlane1  , TRenImagePlane<T>* pcInputPlane2   )
209{
210  UInt uiWidth  = pcInputPlane1->getWidth();
211  UInt uiHeight = pcInputPlane1->getHeight();
212
213  UInt uiStride1 = pcInputPlane1->getStride();
214  UInt uiStride2 = pcInputPlane2->getStride();
215
216  T* pucImData1  = pcInputPlane1->getPlaneData();
217  T* pucImData2  = pcInputPlane2->getPlaneData();
218
219  Bool bEqual = true;
220  for(UInt uiPosY = 0; uiPosY < uiHeight; uiPosY++)
221  {
222
223    for(UInt uiPosX = 0; uiPosX < uiWidth; uiPosX++)
224    {
225      bEqual = bEqual && ( pucImData1[uiPosX] == pucImData2[uiPosX]);
226    }
227    pucImData1 += uiStride1;
228    pucImData2 += uiStride2;
229  }
230  return bEqual;
231}
232
233/////////// Sampling ///////////
234
235inline Void TRenFilter::sampleUp2Tap13(PelImage* pcInputImage, PelImage* pcOutputImage)
236{// UpSampling from JSVM Software (DownConvertStatic) ???
237  UInt uiNumPlanes = pcInputImage->getNumberOfPlanes();
238
239  for (UInt uiCurPlane = 0; uiCurPlane < uiNumPlanes; uiCurPlane++)
240  {
241    PelImagePlane* pcInputPlane  = pcInputImage ->getPlane(uiCurPlane);
242    PelImagePlane* pcOutputPlane = pcOutputImage->getPlane(uiCurPlane);
243
244    Int iWidth  = pcInputPlane->getWidth();
245    Int iHeight = pcInputPlane->getHeight();
246
247    Int iInputStride  = pcInputPlane->getStride();
248    Int iOutputStride = pcOutputPlane->getStride();
249
250    assert( iWidth  == 2 * pcOutputPlane->getWidth ());
251    assert( iHeight == 2 * pcOutputPlane->getHeight());
252
253    Int iOffset;
254
255    Pel *pcInputPlaneData   = pcInputPlane->getPlaneData();
256    Int *piDataVerUp        = new Int[iWidth * iHeight * 2];
257    Pel *pcOutputPlaneData  = pcOutputPlane->getPlaneData();
258
259    // Up sampling filter.
260    Int aiFilterCoeff[16] = { 0, 0, 1, 0, -5, 0, 20, 32, 20, 0, -5,  0, 1, 0, 0, 32 };
261
262    // Normalization factors for filtered values.
263    Int iDivH = 1, iDivV = 1, iAddH = 0, iAddV = 0;
264
265    // Factors after horizontal and vertical filtering.
266    iDivH = (aiFilterCoeff[15]*aiFilterCoeff[15]); iAddH = iDivH / 2;
267
268    Int* piDst = new Int[2*iWidth];
269    //1) VERTICAL UPSAMPLING.
270
271    // Process all cols.
272    for(Int i=0; i<iWidth; i++ )
273    {
274      // Set source (col) poInter.
275      Pel* pcSrc = &pcInputPlaneData[i];
276
277      // Process all rows.
278      for( Int j=0; j<iHeight; j++ )
279      {
280        // Adjust indices of border samples.
281        Int i00 = ((j <   3) ? 0   : j-3) * iInputStride;
282        Int i01 = ((j <   2) ? 0   : j-2) * iInputStride;
283        Int i02 = ((j <   1) ? 0   : j-1) * iInputStride;
284        Int i03 = ((j < iHeight  ) ? j   : j-1) * iInputStride;
285        Int i04 = ((j < iHeight-1) ? j+1 : j-1) * iInputStride;
286        Int i05 = ((j < iHeight-2) ? j+2 : j-1) * iInputStride;
287        Int i06 = ((j < iHeight-3) ? j+3 : j-1) * iInputStride;
288        Int i07 = ((j < iHeight-4) ? j+4 : j-1) * iInputStride;
289
290        // Calculate filtered (even) sample.
291        piDst[2*j+0] = aiFilterCoeff[13] * pcSrc[i00]
292        + aiFilterCoeff[11] * pcSrc[i01]
293        + aiFilterCoeff[ 9] * pcSrc[i02]
294        + aiFilterCoeff[ 7] * pcSrc[i03]
295        + aiFilterCoeff[ 5] * pcSrc[i04]
296        + aiFilterCoeff[ 3] * pcSrc[i05]
297        + aiFilterCoeff[ 1] * pcSrc[i06];
298
299        // Calculate filtered (odd) sample.
300        piDst[2*j+1] = aiFilterCoeff[14] * pcSrc[i00]
301        + aiFilterCoeff[12] * pcSrc[i01]
302        + aiFilterCoeff[10] * pcSrc[i02]
303        + aiFilterCoeff[ 8] * pcSrc[i03]
304        + aiFilterCoeff[ 6] * pcSrc[i04]
305        + aiFilterCoeff[ 4] * pcSrc[i05]
306        + aiFilterCoeff[ 2] * pcSrc[i06]
307        + aiFilterCoeff[ 0] * pcSrc[i07];
308      }
309
310      // Process all filtered samples.
311      for(Int j=0; j<(2*iHeight); j++ )
312      {
313        // Scale and copy to image buffer.
314        piDataVerUp[iWidth*j+i] = (piDst[j] + iAddV) / iDivV;
315      }
316    }
317
318    // Update h
319    iHeight *= 2;
320
321    // 2) HORIZONTAL UPSAMPLING.
322
323    // Process all rows.
324    for( Int j=0; j<iHeight; j++ )
325    {
326      // Set source (row) poInter.
327      Int* piSrc = &piDataVerUp[iWidth*j];
328
329      // Process all cols.
330      for( Int i=0; i<iWidth; i++ )
331      {
332        // Adjust indices of border samples.
333        Int i00 = (i <   3) ? 0   : i-3;
334        Int i01 = (i <   2) ? 0   : i-2;
335        Int i02 = (i <   1) ? 0   : i-1;
336        Int i03 = (i < iWidth  ) ? i   : iWidth-1;
337        Int i04 = (i < iWidth-1) ? i+1 : iWidth-1;
338        Int i05 = (i < iWidth-2) ? i+2 : iWidth-1;
339        Int i06 = (i < iWidth-3) ? i+3 : iWidth-1;
340        Int i07 = (i < iWidth-4) ? i+4 : iWidth-1;
341
342        // Calculate filtered (even) sample.
343        piDst[2*i+0] =   aiFilterCoeff[13] * piSrc[i00]
344        + aiFilterCoeff[11] * piSrc[i01]
345        + aiFilterCoeff[ 9] * piSrc[i02]
346        + aiFilterCoeff[ 7] * piSrc[i03]
347        + aiFilterCoeff[ 5] * piSrc[i04]
348        + aiFilterCoeff[ 3] * piSrc[i05]
349        + aiFilterCoeff[ 1] * piSrc[i06];
350
351        // Calculate filtered (odd) sample.
352        piDst[2*i+1] = aiFilterCoeff[14] * piSrc[i00]
353        + aiFilterCoeff[12] * piSrc[i01]
354        + aiFilterCoeff[10] * piSrc[i02]
355        + aiFilterCoeff[ 8] * piSrc[i03]
356        + aiFilterCoeff[ 6] * piSrc[i04]
357        + aiFilterCoeff[ 4] * piSrc[i05]
358        + aiFilterCoeff[ 2] * piSrc[i06]
359        + aiFilterCoeff[ 0] * piSrc[i07];
360      }
361
362      iOffset = 2* iOutputStride * j;
363      // Process all filtered samples.
364      for(Int i=0; i<iWidth*2; i++ )
365      {
366        // Scale and copy to image buffer.
367        pcOutputPlaneData[iOffset+i] = Max(Min((Pel) ((piDst[i] + iAddH) / iDivH), g_uiBASE_MAX ),0);
368      }
369    }
370
371    delete [] piDataVerUp;
372    delete [] piDst;
373
374  }
375}
376
377
378Void TRenFilter::sampleDown2Tap13(PelImage* pcInputImage, PelImage* pcOutputImage)
379{ // DownSampling from JSVM Software (DownConvertStatic) ??
380
381  UInt uiNumPlanes = pcInputImage->getNumberOfPlanes();
382
383  for (UInt uiCurPlane = 0; uiCurPlane < uiNumPlanes; uiCurPlane++)
384  {
385    sampleDown2Tap13( pcInputImage ->getPlane(uiCurPlane),  pcOutputImage->getPlane(uiCurPlane) );
386  }
387};
388
389Void TRenFilter::sampleDown2Tap13( Pel* pcInputPlaneData, Int iInputStride, Int iWidth, Int iHeight, Pel* pcOutputPlaneData, Int iOutputStride  )
390{ // DownSampling from JSVM Software (DownConvertStatic) ??
391  Int iOffset, iPosX, iPosY, k;
392  Int* piDataHorDown = new Int[(Int)(iWidth * iHeight / 2)];
393
394  // Downsampling filter.
395  Int aiFilterCoeff[16] = { 0, 2, 0, -4, -3, 5, 19, 26, 19, 5, -3, -4, 0, 2, 0, 64 };
396
397  // Normalization factors for filtered values.
398  Int iDivH = 1, iDivV = 1, iAddH = 0, iAddV = 0;
399
400  iDivV = (aiFilterCoeff[15]*aiFilterCoeff[15]); iAddV = iDivV / 2;
401
402  // Allocate and init single row of filtered samples.
403  Int* piDst = new Int[iWidth];
404
405  // 1) HORIZONTAL DOWNSAMPLING.
406
407  // Process all rows.
408  for( iPosY=0; iPosY<iHeight; iPosY++ )
409  {
410    // Set source (row) poInter.
411    Pel* pcSrc = &pcInputPlaneData[iInputStride*iPosY];
412
413    // Process all cols.
414    for( iPosX=0, k=0; iPosX<(iWidth/2); iPosX++, k+=2 )
415    {
416      // Adjust indices of border samples.
417      Int i00 = (k <       7) ? 0   : k    -7;
418      Int i01 = (k <       6) ? 0   : k    -6;
419      Int i02 = (k <       5) ? 0   : k    -5;
420      Int i03 = (k <       4) ? 0   : k    -4;
421      Int i04 = (k <       3) ? 0   : k    -3;
422      Int i05 = (k <       2) ? 0   : k    -2;
423      Int i06 = (k <       1) ? 0   : k    -1;
424      Int i07 = (k < iWidth  ) ? k   : iWidth-1;
425      Int i08 = (k < iWidth-1) ? k+1 : iWidth-1;
426      Int i09 = (k < iWidth-2) ? k+2 : iWidth-1;
427      Int i10 = (k < iWidth-3) ? k+3 : iWidth-1;
428      Int i11 = (k < iWidth-4) ? k+4 : iWidth-1;
429      Int i12 = (k < iWidth-5) ? k+5 : iWidth-1;
430      Int i13 = (k < iWidth-6) ? k+6 : iWidth-1;
431      Int i14 = (k < iWidth-7) ? k+7 : iWidth-1;
432
433      // Calculate filtered sample.
434      piDst[iPosX] =     aiFilterCoeff[ 0] * pcSrc[i00]
435      + aiFilterCoeff[ 1] * pcSrc[i01]
436      + aiFilterCoeff[ 2] * pcSrc[i02]
437      + aiFilterCoeff[ 3] * pcSrc[i03]
438      + aiFilterCoeff[ 4] * pcSrc[i04]
439      + aiFilterCoeff[ 5] * pcSrc[i05]
440      + aiFilterCoeff[ 6] * pcSrc[i06]
441      + aiFilterCoeff[ 7] * pcSrc[i07]
442      + aiFilterCoeff[ 8] * pcSrc[i08]
443      + aiFilterCoeff[ 9] * pcSrc[i09]
444      + aiFilterCoeff[10] * pcSrc[i10]
445      + aiFilterCoeff[11] * pcSrc[i11]
446      + aiFilterCoeff[12] * pcSrc[i12]
447      + aiFilterCoeff[13] * pcSrc[i13]
448      + aiFilterCoeff[14] * pcSrc[i14];
449    }
450
451    iOffset = iPosY * iWidth/2;
452    // Process all filtered samples.
453    for( iPosX=0; iPosX<(iWidth/2); iPosX++ )
454    {
455      // Scale and copy back to image buffer.
456      piDataHorDown[iOffset+iPosX] = (piDst[iPosX] + iAddH) / iDivH;
457    }
458  }
459
460  // Update w.
461  iWidth >>= 1;
462
463  // 2) VERTICAL DOWNSAMPLING.
464
465  // Process all cols.
466  for(  iPosX=0; iPosX<iWidth; iPosX++ )
467  {
468    // Set source (col) poInter.
469    Int* piSrc = &piDataHorDown[iPosX];
470
471    // Process all rows.
472    for(  iPosY=0, k=0; iPosY<(iHeight/2); iPosY++, k+=2 )
473    {
474      // Adjust indices of border samples.
475      Int i00 = ((k <       7) ? 0   : k    -7) * iWidth;
476      Int i01 = ((k <       6) ? 0   : k    -6) * iWidth;
477      Int i02 = ((k <       5) ? 0   : k    -5) * iWidth;
478      Int i03 = ((k <       4) ? 0   : k    -4) * iWidth;
479      Int i04 = ((k <       3) ? 0   : k    -3) * iWidth;
480      Int i05 = ((k <       2) ? 0   : k    -2) * iWidth;
481      Int i06 = ((k <       1) ? 0   : k    -1) * iWidth;
482      Int i07 = ((k < iHeight  ) ? k   : iHeight-1) * iWidth;
483      Int i08 = ((k < iHeight-1) ? k+1 : iHeight-1) * iWidth;
484      Int i09 = ((k < iHeight-2) ? k+2 : iHeight-1) * iWidth;
485      Int i10 = ((k < iHeight-3) ? k+3 : iHeight-1) * iWidth;
486      Int i11 = ((k < iHeight-4) ? k+4 : iHeight-1) * iWidth;
487      Int i12 = ((k < iHeight-5) ? k+5 : iHeight-1) * iWidth;
488      Int i13 = ((k < iHeight-6) ? k+6 : iHeight-1) * iWidth;
489      Int i14 = ((k < iHeight-7) ? k+7 : iHeight-1) * iWidth;
490
491      // Calculate filtered sample.
492      piDst[iPosY] =     aiFilterCoeff[ 0] * piSrc[i00]
493      + aiFilterCoeff[ 1] * piSrc[i01]
494      + aiFilterCoeff[ 2] * piSrc[i02]
495      + aiFilterCoeff[ 3] * piSrc[i03]
496      + aiFilterCoeff[ 4] * piSrc[i04]
497      + aiFilterCoeff[ 5] * piSrc[i05]
498      + aiFilterCoeff[ 6] * piSrc[i06]
499      + aiFilterCoeff[ 7] * piSrc[i07]
500      + aiFilterCoeff[ 8] * piSrc[i08]
501      + aiFilterCoeff[ 9] * piSrc[i09]
502      + aiFilterCoeff[10] * piSrc[i10]
503      + aiFilterCoeff[11] * piSrc[i11]
504      + aiFilterCoeff[12] * piSrc[i12]
505      + aiFilterCoeff[13] * piSrc[i13]
506      + aiFilterCoeff[14] * piSrc[i14];
507    }
508
509    // Process all filtered samples.
510    for( iPosY=0; iPosY<(iHeight/2); iPosY++ )
511    {
512      // Scale and copy back to image buffer.
513      pcOutputPlaneData[iOutputStride*iPosY+iPosX] = Max(Min( ( Pel) ( (piDst[iPosY] + iAddV) / iDivV), g_uiBASE_MAX ),0);
514    }
515  }
516
517  delete [] piDataHorDown;
518  delete [] piDst;
519}
520
521Void TRenFilter::sampleDown2Tap13(PelImagePlane* pcInputPlane, PelImagePlane* pcOutputPlane)
522{ // DownSampling from JSVM Software (DownConvertStatic) ??
523  Int iWidth       = pcInputPlane->getWidth();
524  Int iHeight      = pcInputPlane->getHeight();
525
526  assert( pcOutputPlane->getWidth () == (iWidth  >> 1 ));
527  assert( pcOutputPlane->getHeight() == (iHeight >> 1 ));
528
529  Int iInputStride  = pcInputPlane->getStride();
530  Int iOutputStride = pcOutputPlane->getStride();
531
532  Pel* pcInputPlaneData = pcInputPlane ->getPlaneData();
533  Pel* pcOutputPlaneData = pcOutputPlane->getPlaneData();
534
535  sampleDown2Tap13( pcInputPlaneData, iInputStride, iWidth, iHeight, pcOutputPlaneData, iOutputStride );
536};
537
538Void TRenFilter::sampleVerDown2Tap13( PelImagePlane* pcInputPlane, PelImagePlane* pcOutputPlane, Int uiPad)
539{ // DownSampling from JSVM Software (DownConvertStatic) ??
540  Int iWidth       = pcInputPlane->getWidth();
541  Int iHeight      = pcInputPlane->getHeight();
542
543  assert( pcOutputPlane->getWidth () ==  iWidth       );
544  assert( pcOutputPlane->getHeight() == (iHeight >> 1));
545  assert (pcInputPlane ->getPad()    >=            12 );
546  assert (pcOutputPlane->getPad()    >=         uiPad );
547
548  Int iInputStride  = pcInputPlane->getStride();
549  Int iOutputStride = pcOutputPlane->getStride();
550
551  Pel* pcInputPlaneData  = pcInputPlane ->getPlaneData();
552  Pel* pcOutputPlaneData = pcOutputPlane->getPlaneData();
553
554  Int iStr0  = 0;
555  Int iStr1  = iInputStride;
556  Int iStr2  = iStr1  + iInputStride;
557  Int iStr3  = iStr2  + iInputStride;
558  Int iStr4  = iStr3  + iInputStride;
559  Int iStr5  = iStr4  + iInputStride;
560  Int iStr6  = iStr5  + iInputStride;
561  Int iStr7  = iStr6  + iInputStride;
562  Int iStr8  = iStr7  + iInputStride;
563  Int iStr9  = iStr8  + iInputStride;
564  Int iStr10 = iStr9  + iInputStride;
565  Int iStr11 = iStr10 + iInputStride;
566  Int iStr12 = iStr11 + iInputStride;;
567
568
569  // Downsampling filter { 0, 2, 0, -4, -3, 5, 19, 26, 19, 5, -3, -4, 0, 2, 0, 64 };
570  for ( Int iYPos = 0; iYPos < (iHeight >> 1); iYPos++)
571  {
572    Pel* pcTmpIn = pcInputPlaneData - 12 * iInputStride - uiPad;
573    for ( Int iXPos = -uiPad; iXPos < iWidth + uiPad; iXPos++)
574    {
575      Int iTmp0, iTmp1, iTmp2, iTmp3, iTmp4, iTmp5;
576      iTmp0 = pcTmpIn[iStr0] + pcTmpIn[iStr12];
577      iTmp1 = pcTmpIn[iStr2] + pcTmpIn[iStr10];
578      iTmp2 = pcTmpIn[iStr3] + pcTmpIn[iStr9 ];
579      iTmp3 = pcTmpIn[iStr4] + pcTmpIn[iStr8 ];
580      iTmp4 = pcTmpIn[iStr5] + pcTmpIn[iStr7 ];
581      iTmp5 = pcTmpIn[iStr6];
582
583      Int iSum = iTmp4 + iTmp3 - iTmp2 + ((iTmp0 + iTmp4 + iTmp5 - iTmp2) << 1) + ( ( iTmp3 - iTmp1)  << 2) + (  iTmp5 << 3 ) + (( iTmp4 + iTmp5 ) << 4);
584      pcOutputPlaneData[ iXPos ] = (Pel) Clip((iSum + 32) >> 6);
585      pcTmpIn++;
586    }
587    pcOutputPlaneData += iOutputStride;
588    pcInputPlaneData  += (iInputStride << 1);
589  }
590};
591
592Void TRenFilter::sampleHorDown2Tap13( PelImagePlane* pcInputPlane, PelImagePlane* pcOutputPlane, Int uiPad )
593{ // DownSampling from JSVM Software (DownConvertStatic) ??
594  Int iWidth       = pcInputPlane->getWidth();
595  Int iHeight      = pcInputPlane->getHeight();
596
597  assert( pcOutputPlane->getWidth () == (iWidth  >> 1));
598  assert( pcOutputPlane->getHeight() ==  iHeight      );
599  assert (pcInputPlane ->getPad()    >=            12 );
600  assert (pcOutputPlane->getPad()    >=         uiPad );
601
602  Int iInputStride  = pcInputPlane ->getStride();
603  Int iOutputStride = pcOutputPlane->getStride();
604
605  Pel* pcInputPlaneData  = pcInputPlane ->getPlaneData()- uiPad * iInputStride ;
606  Pel* pcOutputPlaneData = pcOutputPlane->getPlaneData()- uiPad * iOutputStride;
607
608  // Downsampling filter { 0, 2, 0, -4, -3, 5, 19, 26, 19, 5, -3, -4, 0, 2, 0, 64 };
609  for ( Int iYPos = 0; iYPos < iHeight + 2*uiPad; iYPos++)
610  {
611    Pel* pcTmpIn = pcInputPlaneData - 12;
612    for ( Int iXPos = 0; iXPos < ( iWidth >> 1); iXPos++)
613    {
614      Int iTmp0, iTmp1, iTmp2, iTmp3, iTmp4, iTmp5;
615      iTmp0 = pcTmpIn[0]+ pcTmpIn[12];
616      iTmp1 = pcTmpIn[2]+ pcTmpIn[10];
617      iTmp2 = pcTmpIn[3]+ pcTmpIn[9 ];
618      iTmp3 = pcTmpIn[4]+ pcTmpIn[8 ];
619      iTmp4 = pcTmpIn[5]+ pcTmpIn[7 ];
620      iTmp5 = pcTmpIn[6];
621
622      Int iSum = iTmp4 + iTmp3 - iTmp2 + ((iTmp0 + iTmp4 + iTmp5 - iTmp2) << 1) + ( ( iTmp3 - iTmp1)  << 2) + (  iTmp5 << 3 ) + (( iTmp4 + iTmp5 ) << 4);
623      pcOutputPlaneData[ iXPos ] = (Pel) Clip((iSum + 32) >> 6);
624      pcTmpIn += 2;
625    }
626    pcOutputPlaneData += iOutputStride;
627    pcInputPlaneData  += iInputStride ;
628  }
629};
630
631inline Pel TRenFilter::xMedian3(Pel* pcData)
632{
633  Bool bGT01 = pcData[0] >  pcData[1];
634  Bool bGT12 = pcData[1] >  pcData[2];
635  Bool bGT20 = pcData[2] >  pcData[0];
636
637  return ( (bGT01 && bGT20) || (!bGT01 && !bGT20) ) ?  pcData[0] : ( ( (bGT12 && bGT01) || (!bGT12 && !bGT01) ) ?  pcData[1] : pcData[2]) ;
638}
639
640
641Void TRenFilter::lineMedian3( PelImage* pcImage )
642{
643
644  PelImage* pcTemp = pcImage->create();
645
646  for (UInt uiCurPlane = 0; uiCurPlane < pcImage->getNumberOfPlanes(); uiCurPlane++)
647  {
648    PelImagePlane* pcImPlane   = pcImage->getPlane(uiCurPlane);
649    PelImagePlane* pcTempPlane = pcTemp ->getPlane(uiCurPlane);
650
651    UInt uiWidth  = pcImPlane->getWidth();
652    UInt uiHeight = pcImPlane->getHeight();
653
654    Pel* pcImData   = pcImPlane  ->getPlaneData();
655    Pel* pcTempData = pcTempPlane->getPlaneData();
656
657    UInt uiImDataStride   = pcImPlane  ->getStride();
658    UInt uiTempDataStride = pcTempPlane->getStride();
659
660    for(UInt uiPosY = 0; uiPosY < uiHeight; uiPosY++)
661    {
662      for(UInt uiPosX = 0; uiPosX < uiWidth; uiPosX++)
663      {
664        if ( (uiPosX >= 1) && (uiPosX < (uiWidth - 2)) )
665        {
666          pcTempData[uiPosX] = xMedian3(pcImData + uiPosX - 1);
667        }
668        else
669        {
670          pcTempData[uiPosX] = pcImData[uiPosX];
671        }
672      }
673      pcTempData += uiTempDataStride;
674      pcImData   += uiImDataStride;
675    }
676  }
677
678  pcImage->assign(pcTemp);
679  delete pcTemp;
680}
681
682
683Void TRenFilter::convRect( PelImage* pcImage, UInt uiSize )
684{
685  DoubleImage cKernel(uiSize, uiSize,1,0);
686  cKernel.getPlane(0)->assign( 1 / ( Double( uiSize )  * Double( uiSize) ));
687  conv(pcImage, &cKernel);
688}
689
690Void TRenFilter::binominal( PelImage* pcInputImage, PelImage* pcOutputImage, UInt uiSize )
691{
692  assert( pcInputImage->getNumberOfFullPlanes()   == pcOutputImage->getNumberOfFullPlanes  () );
693  assert( pcInputImage->getNumberOfQuaterPlanes() == pcOutputImage->getNumberOfQuaterPlanes() );
694
695  UInt uiPlane;
696  for (uiPlane = 0; uiPlane < pcInputImage->getNumberOfPlanes(); uiPlane ++)
697  {
698    binominal( pcInputImage->getPlane(uiPlane), pcOutputImage->getPlane(uiPlane), uiSize );
699  }
700
701  for (  ; uiPlane < pcInputImage->getNumberOfPlanes(); uiPlane ++)
702  {
703    binominal( pcInputImage->getPlane(uiPlane), pcOutputImage->getPlane(uiPlane), uiSize >> 1 );
704 }
705}
706
707Void TRenFilter::binominal( PelImagePlane* pcInputPlane, PelImagePlane* pcOutputPlane, UInt uiSize )
708{
709  Int iWidth  = pcInputPlane ->getWidth ();
710  Int iHeight = pcInputPlane ->getHeight();
711
712  assert( pcOutputPlane->getWidth () == iWidth  );
713  assert( pcOutputPlane->getHeight() == iHeight );
714  assert( pcInputPlane ->getPad   () >= uiSize );
715  assert( pcOutputPlane->getPad   () >= uiSize );
716
717  if (uiSize == 0)
718  {
719    pcOutputPlane->assign( pcInputPlane );
720    return;
721  };
722
723  Int iInputStride  = pcInputPlane ->getStride();
724  Int iOutputStride = pcOutputPlane->getStride();
725  Int iTempStride   = iWidth + (uiSize << 1);
726
727
728  Pel* pcCurInputData  = pcInputPlane ->getPlaneData() - uiSize;
729  Pel* pcTempData      = new Pel[iTempStride * iHeight];
730  Pel* pcCurTempData   = pcTempData;
731
732  Pel (*fpFilter) ( Pel*, Int ) = NULL;
733
734  switch( uiSize )
735  {
736  case 1:
737    fpFilter = &TRenFilter::xFiltBinom3;
738    break;
739  case 2:
740    fpFilter = &TRenFilter::xFiltBinom5;
741    break;
742  case 3:
743    fpFilter = &TRenFilter::xFiltBinom7;
744    break;
745  case 4:
746    fpFilter = &TRenFilter::xFiltBinom9;
747    break;
748  default:
749      AOT(true);
750  }
751
752  for (Int iPosY = 0; iPosY < iHeight; iPosY++ )
753  {
754    for (Int iPosX = 0; iPosX < iWidth + (uiSize << 1); iPosX++)
755    {
756      pcCurTempData[iPosX] = (*fpFilter)(pcCurInputData + iPosX, iInputStride );
757    }
758    pcCurTempData   += iTempStride;
759    pcCurInputData  += iInputStride;
760  }
761
762  pcCurTempData   = pcTempData + uiSize;
763  Pel* pcCurOutputData = pcOutputPlane->getPlaneData();
764
765  for (Int iPosY = 0; iPosY < iHeight; iPosY++ )
766  {
767    for (Int iPosX = 0; iPosX < iWidth; iPosX++)
768    {
769      pcCurOutputData[iPosX] = (*fpFilter)(pcCurTempData + iPosX, 1);
770    }
771    pcCurTempData    += iTempStride;
772    pcCurOutputData  += iOutputStride;
773  }
774
775  delete[] pcTempData;
776}
777
778Pel TRenFilter::xFiltBinom3( Pel* pcInputData, Int iStride )
779{
780  Int iSum = pcInputData[-1 * iStride ] + pcInputData[ 0 ] +  (pcInputData[iStride ] << 1 );
781  return Clip( (iSum +  2) >>  2 );
782}
783
784Pel TRenFilter::xFiltBinom5( Pel* pcInputData, Int iStride )
785{
786  // { 1,4,6,4,1 }
787  Int iStride0  = 0;
788  Int iStrideM1 = iStride0  - iStride;
789  Int iStrideM2 = iStrideM1 - iStride;
790  Int iStrideP1 = iStride0  + iStride;
791  Int iStrideP2 = iStrideP1 + iStride;
792
793  Int iTmp0 = pcInputData[iStrideM2] + pcInputData[iStrideP2];
794  Int iTmp1 = pcInputData[iStrideM1] + pcInputData[iStrideP1];
795  Int iTmp2 = pcInputData[iStride0 ];
796
797  Int iSum = iTmp0 +  (iTmp2 << 1) + ((iTmp1 + iTmp2) << 2);
798  return Clip( (iSum +  8) >>  4 );
799}
800
801Pel TRenFilter::xFiltBinom7( Pel* pcInputData, Int iStride )
802{
803  // { 1,6,15,20,15,6,1 }
804  Int iStride0  = 0;
805  Int iStrideM1 = iStride0  - iStride;
806  Int iStrideM2 = iStrideM1 - iStride;
807  Int iStrideM3 = iStrideM1 - iStride;
808  Int iStrideP1 = iStride0  + iStride;
809  Int iStrideP2 = iStrideP1 + iStride;
810  Int iStrideP3 = iStrideP1 + iStride;
811
812  Int iTmp0 = pcInputData[iStrideM3] + pcInputData[iStrideP3];
813  Int iTmp1 = pcInputData[iStrideM2] + pcInputData[iStrideP2];
814  Int iTmp2 = pcInputData[iStrideM1] + pcInputData[iStrideP1];
815  Int iTmp3 = pcInputData[iStride0];
816
817  Int iSum = iTmp0 - iTmp2 + ( iTmp1  << 1) + ( (iTmp1 + iTmp3) << 2) + ((iTmp2 + iTmp3) << 4);
818
819  return Clip( (iSum +  32) >>  6 );
820}
821
822Pel TRenFilter::xFiltBinom9( Pel* pcInputData, Int iStride )
823{
824  // {  1     8    28    56    70    56    28     8     1 }
825  Int iStride0  = 0;
826  Int iStrideM1 = iStride0  - iStride;
827  Int iStrideM2 = iStrideM1 - iStride;
828  Int iStrideM3 = iStrideM1 - iStride;
829  Int iStrideM4 = iStrideM1 - iStride;
830  Int iStrideP1 = iStride0  + iStride;
831  Int iStrideP2 = iStrideP1 + iStride;
832  Int iStrideP3 = iStrideP1 + iStride;
833  Int iStrideP4 = iStrideP1 + iStride;
834
835  Int iTmp0 = pcInputData[iStrideM4] + pcInputData[iStrideP4];
836  Int iTmp1 = pcInputData[iStrideM3] + pcInputData[iStrideP3];
837  Int iTmp2 = pcInputData[iStrideM2] + pcInputData[iStrideP2];
838  Int iTmp3 = pcInputData[iStrideM1] + pcInputData[iStrideP1];
839  Int iTmp4 = pcInputData[iStride0];
840
841  Int iSum = iTmp0 + ((iTmp4 ) << 1) + ( ( iTmp4 - iTmp2 ) << 2) +  ( (iTmp1 - iTmp3) << 3 ) +  ((iTmp2 ) << 5) + ((iTmp3+ iTmp4 ) << 6);
842
843  return Clip( (iSum +  128) >>  8 );
844}
845
846
847Pel TRenFilter::interpCHSpline(Double dX, Double dS0, Double dS1, Int iQ0, Int iQ1, Int iQ2, Int iQ3)
848{
849  Double dSq = (dX - dS0) / (dS1 - dS0);
850
851  Double adP[4];
852  Double dSqP2 = dSq * dSq;
853  Double dSqP3 = dSqP2 * dSq;
854
855  adP[0] = 1 - 3 * dSqP2 + 2 * dSqP3;
856  adP[1] = dSq - 2 * dSqP2 + dSqP3;
857  adP[2] = 3 * dSqP2 - 2 * dSqP3;
858  adP[3] = -dSqP2 + dSqP3;
859
860  Double dQ  = adP[0] * iQ0 + adP[1] * iQ1 + adP[2] * iQ2 + adP[3] * iQ3 ;
861
862  Pel cQ = (Pel) ( dQ + 0.5);
863
864  cQ = ( cQ < 0   ? 0   : cQ );
865  cQ = ( cQ > 255 ? 255 : cQ );
866
867  return cQ;
868
869}
870
871Void TRenFilter::diffHorSym(PelImage* pcInputImage, IntImage* pcOutputImage)
872{
873  for (UInt uiCurPlane = 0; uiCurPlane < pcInputImage->getNumberOfPlanes(); uiCurPlane++)
874  {
875    diffHorSym( pcInputImage->getPlane(uiCurPlane), pcOutputImage->getPlane(uiCurPlane));
876  };
877}
878
879Void TRenFilter::diffHorSym(PelImagePlane* pcInputPlane, IntImagePlane* pcOutputPlane)
880{
881  UInt uiInputStride = pcInputPlane ->getStride();
882  UInt uiOutputStride = pcOutputPlane->getStride();
883  UInt uiWidth        = pcInputPlane ->getWidth();
884  UInt uiHeight       = pcInputPlane ->getHeight();
885
886  Pel*   pcInputData   = pcInputPlane ->getPlaneData();
887  Int*   piOutputData  = pcOutputPlane->getPlaneData();
888
889  for (UInt uiPosY = 0; uiPosY < uiHeight; uiPosY++)
890  {
891    for (UInt uiPosX = 1; uiPosX < uiWidth-1; uiPosX++)
892    {
893      piOutputData[uiPosX] = ((Int) pcInputData[uiPosX+1] - (Int) pcInputData[uiPosX-1]);
894      piOutputData[uiPosX] /= 2;
895    };
896
897    piOutputData[0] = piOutputData[1];
898    piOutputData[uiWidth-1] = piOutputData[uiWidth-2];
899    pcInputData += uiInputStride;
900    piOutputData  += uiOutputStride;
901
902  };
903}
904
905Void TRenFilter::laplace( DoubleImage* pcInputImage, DoubleImage* pcOutputImage )
906{
907  for (UInt uiCurPlane = 0; uiCurPlane < pcInputImage->getNumberOfPlanes(); uiCurPlane++)
908  {
909    DoubleImagePlane* pcInputPlane  = pcInputImage  ->getPlane(uiCurPlane);
910    DoubleImagePlane* pcOutputPlane = pcOutputImage ->getPlane(uiCurPlane);
911
912    UInt uiWidth  = pcInputPlane->getWidth();
913    UInt uiHeight = pcInputPlane->getHeight();
914
915    Double* pdInputData  = pcInputPlane  ->getPlaneData();
916    Double* pdOutputData = pcOutputPlane ->getPlaneData();
917
918    for (UInt uiPosY = 1; uiPosY < uiHeight-1; uiPosY++)
919    {
920      UInt uOff = uiPosY * uiWidth;
921      for(UInt uiPosX = 1; uiPosX < uiWidth-1; uiPosX++)
922      {
923        UInt uOff2 = uOff + uiPosX;
924        pdOutputData[uOff2] =     4 * pdInputData[uOff2]
925        -   pdInputData[uOff2 - 1]
926        -   pdInputData[uOff2 + 1]
927        -   pdInputData[uOff2 - uiWidth]
928        -   pdInputData[uOff2 + uiWidth];
929      }
930    };
931
932    // left and right margin
933    for (UInt uiPosY = 1; uiPosY < uiHeight-1; uiPosY++)
934    {
935      UInt uOff  = uiPosY * uiWidth;
936      pdOutputData[uOff] = 3 * pdInputData[uOff]
937      -   pdInputData[uOff + 1]
938      -   pdInputData[uOff - uiWidth]
939      -   pdInputData[uOff + uiWidth];
940
941
942      uOff = (uiPosY + 1) * uiWidth - 1;
943      pdOutputData[uOff] = 3 * pdInputData[uOff]
944      -   pdInputData[uOff - 1]
945      -   pdInputData[uOff - uiWidth]
946      -   pdInputData[uOff + uiWidth];
947    }
948
949    for (UInt uiPosX = 1; uiPosX < uiWidth-1; uiPosX++)
950    {
951      UInt uOff  = uiPosX;
952      pdOutputData[uOff] = 3 * pdInputData[uOff]
953      -   pdInputData[uOff + 1]
954      -   pdInputData[uOff - 1]
955      -   pdInputData[uOff + uiWidth];
956
957
958      uOff = (uiHeight - 1) * uiWidth + uiPosX;
959      pdOutputData[uOff] = 3 * pdInputData[uOff]
960      -   pdInputData[uOff + 1]
961      -   pdInputData[uOff - 1]
962      -   pdInputData[uOff - uiWidth];
963    }
964
965    UInt uOff = 0;
966    pdOutputData[uOff] = 2 * pdInputData[uOff] - pdInputData[uOff+1] - pdInputData[ uOff + uiWidth];
967    uOff = uiWidth - 1;
968    pdOutputData[uOff] = 2 * pdInputData[uOff] - pdInputData[uOff-1] - pdInputData[ uOff + uiWidth ];
969    uOff = (uiHeight - 1) * uiWidth;
970    pdOutputData[uOff] = 2 * pdInputData[uOff] - pdInputData[uOff+1] - pdInputData[ uOff - uiWidth];
971    uOff = uiHeight * uiWidth - 1;
972    pdOutputData[uOff] = 2 * pdInputData[uOff] - pdInputData[uOff-1] - pdInputData[ uOff - uiWidth];
973
974  }
975}
976
977
978Void TRenFilter::conv( PelImage* pcImage, DoubleImage* pcKernel )
979{
980  PelImage* pcTemp = pcImage->create();
981
982  DoubleImagePlane* pcKernelPlane = 0;
983  for (UInt uiCurPlane = 0; uiCurPlane < pcImage->getNumberOfPlanes(); uiCurPlane++) {
984
985    PelImagePlane* pcPlane     = pcImage->getPlane(uiCurPlane);
986    PelImagePlane* pcTempPlane = pcTemp ->getPlane(uiCurPlane);
987
988    if ( uiCurPlane <= pcKernel->getNumberOfPlanes() )
989    {
990      pcKernelPlane = pcKernel->getPlane(uiCurPlane);
991    };
992
993    UInt uiWidth  = pcPlane->getWidth();
994    UInt uiHeight = pcPlane->getHeight();
995
996    UInt uiKernelWidth  = pcKernelPlane->getWidth();
997    UInt uiKernelHeight = pcKernelPlane->getHeight();
998
999    Pel*    pcData         = pcPlane      ->getPlaneData();
1000    Pel*    pcTempData     = pcTempPlane  ->getPlaneData();
1001    Double* pdKernelData   = pcKernelPlane->getPlaneData();
1002
1003    UInt uiDataStride       = pcPlane      ->getStride();
1004    UInt uiTempDataStride   = pcTempPlane  ->getStride();
1005    UInt uiKernelDataStride = pcKernelPlane->getStride();
1006
1007    for(UInt uiPosY = 0; uiPosY < uiHeight; uiPosY++)
1008    {
1009      UInt uOff = uiPosY * uiTempDataStride;
1010      for(UInt uiPosX = 0; uiPosX < uiWidth; uiPosX++)
1011      {
1012        Double dSum = 0;
1013        for(UInt uKY = 0; uKY < uiKernelHeight; uKY++)
1014        {
1015          UInt uKOff = uKY * uiKernelDataStride;
1016
1017          Int iYSrc = uiPosY - (uiKernelHeight/2) + uKY;
1018
1019          if (iYSrc < 0)
1020            iYSrc = -iYSrc;
1021
1022          if (iYSrc >= (Int)uiHeight)
1023            iYSrc = 2*uiHeight - iYSrc - 1;
1024
1025          UInt uSrcOff = iYSrc * uiDataStride;
1026
1027          for(UInt uKX = 0; uKX < uiKernelWidth; uKX++)
1028          {
1029            Int iXSrc = uiPosX - (uiKernelWidth/2) + uKX;
1030
1031            if (iXSrc < 0)
1032              iXSrc = -iXSrc;
1033
1034            if (iXSrc >= (Int)uiWidth)
1035              iXSrc = 2*uiWidth - iXSrc - 1;
1036
1037            dSum += pcData[uSrcOff + iXSrc] * pdKernelData[uKOff + uKX];
1038          }
1039        }
1040        pcTempData[uOff + uiPosX] = (Pel) (dSum + ( ( dSum < 0 ) ? -0.5 : 0.5)  );
1041      }
1042    }
1043  }
1044
1045  pcImage->assign(pcTemp);
1046  delete pcTemp;
1047}
1048
1049
1050// Horizontal Up sampling luma
1051Void TRenFilter::sampleHorUp( Int iLog2HorSampFac, Pel* pcInputPlaneData, Int iInputStride, Int iInputWidth, Int iHeight, Pel* pcOutputPlaneData, Int iOutputStride  )
1052{
1053  TComPredFilter cFilter;
1054  switch ( iLog2HorSampFac )
1055  {
1056  case 0:
1057    xDistributeArray              ( pcInputPlaneData, iInputStride, 1 , 1, iInputWidth, iHeight, pcOutputPlaneData, iOutputStride, 1, 1 );
1058    break;
1059  case 1:
1060    xDistributeArray              ( pcInputPlaneData, iInputStride, 1 , 1, iInputWidth, iHeight, pcOutputPlaneData, iOutputStride, 2, 1 );
1061    cFilter.xCTI_FilterHalfHor    ( pcInputPlaneData, iInputStride,     1, iInputWidth, iHeight, iOutputStride, 2, ++pcOutputPlaneData );
1062    break;
1063  case 2:
1064    xDistributeArray              ( pcInputPlaneData, iInputStride, 1 , 1, iInputWidth, iHeight, pcOutputPlaneData, iOutputStride, 4, 1 );
1065    cFilter.xCTI_FilterQuarter0Hor( pcInputPlaneData, iInputStride, 1, iInputWidth, iHeight, iOutputStride, 4, ++pcOutputPlaneData );
1066    cFilter.xCTI_FilterHalfHor    ( pcInputPlaneData, iInputStride, 1, iInputWidth, iHeight, iOutputStride, 4, ++pcOutputPlaneData );
1067    cFilter.xCTI_FilterQuarter1Hor( pcInputPlaneData, iInputStride, 1, iInputWidth, iHeight, iOutputStride, 4, ++pcOutputPlaneData );
1068    break;
1069  }
1070}
1071
1072// horizontal up sampling chroma
1073Void TRenFilter::sampleCHorUp(Int iLog2HorSampFac, Pel* pcInputPlaneData, Int iInputStride, Int iInputWidth, Int iHeight, Pel* pcOutputPlaneData, Int iOutputStride  )
1074{
1075  switch ( iLog2HorSampFac )
1076  {
1077  case 0:
1078    xDistributeArray( pcInputPlaneData,   iInputStride  , 1, 1, iInputWidth,   iHeight   , pcOutputPlaneData                  , iOutputStride, 1 , 1 );
1079    break;
1080  case 1:
1081    xDistributeArray( pcInputPlaneData,   iInputStride  , 1, 1, iInputWidth,   iHeight   , pcOutputPlaneData                  , iOutputStride, 2 , 1 );
1082    xInterpHorChroma( pcInputPlaneData  , iInputStride  , 1, 1, iInputWidth,   iHeight   , pcOutputPlaneData                +1, iOutputStride, 2 , 1, &TComPredFilter::xCTI_Filter_VPS04_C_HAL );
1083    break;
1084  case 2:
1085    xDistributeArray( pcInputPlaneData,   iInputStride  , 1, 1, iInputWidth,   iHeight   , pcOutputPlaneData                  , iOutputStride, 4 , 1 );
1086    xInterpHorChroma( pcInputPlaneData  , iInputStride  , 1, 1, iInputWidth,   iHeight   , pcOutputPlaneData                +1, iOutputStride, 4 , 1, &TComPredFilter::xCTI_Filter_VP04_C_QUA0 );
1087    xInterpHorChroma( pcInputPlaneData  , iInputStride  , 1, 1, iInputWidth,   iHeight   , pcOutputPlaneData                +2, iOutputStride, 4 , 1, &TComPredFilter::xCTI_Filter_VPS04_C_HAL );
1088    xInterpHorChroma( pcInputPlaneData  , iInputStride  , 1, 1, iInputWidth,   iHeight   , pcOutputPlaneData                +3, iOutputStride, 4 , 1, &TComPredFilter::xCTI_Filter_VP04_C_QUA1 );
1089    break;
1090  }
1091}
1092
1093Void TRenFilter::sampleCUpHorUp( Int iLog2HorSampFac, Pel* pcInputPlaneData, Int iInputStride, Int iInputWidth, Int iHeight, Pel* pcOutputPlaneData, Int iOutputStride  )
1094{
1095
1096  switch ( iLog2HorSampFac )
1097  {
1098  case 0:
1099    xDistributeArray( pcInputPlaneData-1, iInputStride  , 1, 1, iInputWidth+3, iHeight   , pcOutputPlaneData                -2, iOutputStride, 2,  2 );
1100    xInterpVerChroma( pcInputPlaneData-1, iInputStride  , 1, 1, iInputWidth+3, iHeight   , pcOutputPlaneData+1*iOutputStride-2, iOutputStride, 2 , 2, &TComPredFilter::xCTI_Filter_VPS04_C_HAL );
1101    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 2, 1, iInputWidth,   iHeight*2 , pcOutputPlaneData+1                , iOutputStride, 2 , 1, &TComPredFilter::xCTI_Filter_VPS04_C_HAL );
1102    break;
1103  case 1:
1104    xDistributeArray( pcInputPlaneData-1, iInputStride  , 1, 1, iInputWidth+3, iHeight   , pcOutputPlaneData                -4, iOutputStride, 4 , 2 );
1105    xInterpVerChroma( pcInputPlaneData-1, iInputStride  , 1, 1, iInputWidth+3, iHeight   , pcOutputPlaneData+1*iOutputStride-4, iOutputStride, 4 , 2, &TComPredFilter::xCTI_Filter_VPS04_C_HAL );
1106    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 4, 1, iInputWidth, iHeight*2 , pcOutputPlaneData                +1, iOutputStride, 4 , 1, &TComPredFilter::xCTI_Filter_VP04_C_QUA0 );
1107    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 4, 1, iInputWidth, iHeight*2 , pcOutputPlaneData                +2, iOutputStride, 4 , 1, &TComPredFilter::xCTI_Filter_VPS04_C_HAL );
1108    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 4, 1, iInputWidth, iHeight*2 , pcOutputPlaneData                +3, iOutputStride, 4 , 1, &TComPredFilter::xCTI_Filter_VP04_C_QUA1 );
1109    break;
1110  case 2:
1111    xDistributeArray( pcInputPlaneData-1, iInputStride  , 1, 1, iInputWidth+3, iHeight   , pcOutputPlaneData                -8, iOutputStride, 8 , 2 );
1112    xInterpVerChroma( pcInputPlaneData-1, iInputStride  , 1, 1, iInputWidth+3, iHeight   , pcOutputPlaneData+1*iOutputStride-8, iOutputStride, 8 , 2, &TComPredFilter::xCTI_Filter_VPS04_C_HAL );
1113    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 8, 1, iInputWidth,   iHeight*2 , pcOutputPlaneData                +1, iOutputStride, 8 , 1, &TComPredFilter::xCTI_Filter_VP04_C_OCT0 );
1114    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 8, 1, iInputWidth,   iHeight*2 , pcOutputPlaneData                +2, iOutputStride, 8 , 1, &TComPredFilter::xCTI_Filter_VP04_C_QUA0 );
1115    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 8, 1, iInputWidth,   iHeight*2 , pcOutputPlaneData                +3, iOutputStride, 8 , 1, &TComPredFilter::xCTI_Filter_VP04_C_OCT1 );
1116    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 8, 1, iInputWidth,   iHeight*2 , pcOutputPlaneData                +4, iOutputStride, 8 , 1, &TComPredFilter::xCTI_Filter_VPS04_C_HAL );
1117    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 8, 1, iInputWidth,   iHeight*2 , pcOutputPlaneData                +5, iOutputStride, 8 , 1, &TComPredFilter::xCTI_Filter_VP04_C_OCT2 );
1118    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 8, 1, iInputWidth,   iHeight*2 , pcOutputPlaneData                +6, iOutputStride, 8 , 1, &TComPredFilter::xCTI_Filter_VP04_C_QUA1 );
1119    xInterpHorChroma( pcOutputPlaneData , iOutputStride , 8, 1, iInputWidth,   iHeight*2 , pcOutputPlaneData                +7, iOutputStride, 8 , 1, &TComPredFilter::xCTI_Filter_VP04_C_OCT3 );
1120    break;
1121  }
1122}
1123
1124
1125// Down Sampling
1126// Down sample luma
1127Void TRenFilter::sampleHorDown(Int iLog2HorSampFac,  Pel* pcInputPlaneData, Int iInputStride, Int iInputWidth, Int iHeight, Pel* pcOutputPlaneData, Int iOutputStride  )
1128{
1129  switch ( iLog2HorSampFac )
1130  {
1131  case 0:
1132    xDistributeArray( pcInputPlaneData, iInputStride, 1, 1, iInputWidth,iHeight, pcOutputPlaneData, iOutputStride, 1 , 1 );
1133    break;
1134  case 1:
1135    xSampleDownHor2(pcInputPlaneData, iInputStride, iInputWidth, iHeight, pcOutputPlaneData, iOutputStride);
1136    break;
1137  case 2:
1138    xSampleDownHor4(pcInputPlaneData, iInputStride, iInputWidth, iHeight, pcOutputPlaneData, iOutputStride);
1139    break;
1140  }
1141}
1142
1143
1144Void TRenFilter::sampleCHorDown(Int iLog2HorSampFac,  Pel* pcInputPlaneData, Int iInputStride, Int iInputWidth, Int iHeight, Pel* pcOutputPlaneData, Int iOutputStride  )
1145{
1146  //GT: currently the same as for luma
1147  sampleHorDown( iLog2HorSampFac, pcInputPlaneData, iInputStride, iInputWidth, iHeight, pcOutputPlaneData, iOutputStride);
1148}
1149
1150
1151
1152// Up sampling chroma
1153Void TRenFilter::sampleCDownHorDown( Int iLog2HorSampFac,  Pel* pcInputPlaneData, Int iInputStride, Int iInputWidth, Int iInputHeight, Pel* pcOutputPlaneData, Int iOutputStride  )
1154{
1155  // create buffer
1156  Int iBufferStride   = iInputWidth >> (iLog2HorSampFac + 1);
1157  Pel* piBuffer       = new Pel[ iBufferStride * (iInputHeight+2) ];
1158
1159  switch ( iLog2HorSampFac )
1160  {
1161  case 0:
1162    xSampleDownHor2( pcInputPlaneData - iInputStride,  iInputStride, iInputWidth  , iInputHeight+1, piBuffer,  iBufferStride);
1163    break;
1164  case 1:
1165    xSampleDownHor4( pcInputPlaneData - iInputStride , iInputStride,  iInputWidth , iInputHeight+1, piBuffer, iBufferStride);
1166    break;
1167  case 2:
1168    xSampleDownHor8( pcInputPlaneData - iInputStride , iInputStride,  iInputWidth  , iInputHeight+1, piBuffer, iBufferStride);
1169    break;
1170  }
1171  xSampleDownVer2( piBuffer + iBufferStride       , iBufferStride, iBufferStride, iInputHeight,   pcOutputPlaneData, iOutputStride);
1172  delete[] piBuffer;
1173}
1174
1175Void TRenFilter::xDistributeArray(Pel* pcSrc, Int iSrcStride, Int iSrcStepX, Int iSrcStepY, Int iWidth, Int iHeight, Pel* pcDst, Int iDstStride, Int iDstStepX, Int iDstStepY)
1176{
1177  iDstStride *= iDstStepY;
1178  iSrcStride *= iSrcStepY;
1179  for (Int iYPos = 0; iYPos < iHeight; iYPos++ )
1180  {
1181    Pel* pcCurDst = pcDst;
1182    Pel* pcCurSrc  = pcSrc;
1183    for (Int iXPos = 0; iXPos < iWidth; iXPos ++)
1184    {
1185      *pcCurDst = *pcCurSrc;
1186
1187      pcCurDst += iDstStepX;
1188      pcCurSrc += iSrcStepX;
1189    }
1190    pcDst  += iDstStride;
1191    pcSrc  += iSrcStride;
1192  }
1193}
1194
1195
1196Void TRenFilter::xInterpHorChroma( Pel* piSrc, Int iSrcStride, Int iSrcStepX, Int iSrcStepY, Int iWidth, Int iHeight, Pel* piDst, Int iDstStride, Int iDstStepX, Int iDstStepY, FpChromaIntFilt fpFilter )
1197{
1198  Int   iSum;
1199  Pel*  piSrcTmp;
1200
1201  TComPredFilter cFilter;
1202  for ( Int y = iHeight; y != 0; y-- )
1203  {
1204    piSrcTmp = piSrc - iSrcStepX;
1205    for ( Int x = 0; x < iWidth; x++ )
1206    {
1207      iSum      = (cFilter.*fpFilter)( piSrcTmp,  iSrcStepX );
1208      piDst[x * iDstStepX ] =  Clip ((iSum +  32) >>  6 );
1209      piSrcTmp+= iSrcStepX;
1210    }
1211    piSrc += iSrcStride * iSrcStepY;
1212    piDst += iDstStride * iDstStepY;
1213  }
1214}
1215
1216Void TRenFilter::xInterpVerChroma( Pel* piSrc, Int iSrcStride, Int iSrcStepX, Int iSrcStepY, Int iWidth, Int iHeight, Pel* piDst, Int iDstStride, Int iDstStepX, Int iDstStepY, FpChromaIntFilt fpFilter )
1217{
1218  Int   iSum;
1219  Pel*  piSrcTmp;
1220
1221  TComPredFilter cFilter;
1222  for ( Int y = iHeight; y != 0; y-- )
1223  {
1224    piSrcTmp = piSrc - iSrcStepY * iSrcStride;
1225    for ( Int x = 0; x < iWidth; x++ )
1226    {
1227      iSum      = (cFilter.*fpFilter)( piSrcTmp,  iSrcStepY * iSrcStride );
1228      piDst[x * iDstStepX ]  =  Clip ((iSum +  32) >>  6 );
1229      piSrcTmp += iSrcStepX;
1230    }
1231    piSrc += iSrcStride * iSrcStepY;
1232    piDst += iDstStride * iDstStepY;
1233  }
1234}
1235
1236
1237Void TRenFilter::xSampleDownHor2( Pel* piSrc, Int iSrcStride, Int iSrcWidth, Int iHeight, Pel* piDst, Int iDstStride  )
1238{
1239  Int   iSum;
1240  Pel*  piSrcTmp;
1241
1242
1243  for ( Int y = iHeight; y != 0; y-- )
1244  {
1245    piSrcTmp = piSrc - 1 ;
1246    for ( Int x = 0; x < (iSrcWidth >> 1); x++ )
1247    {
1248      // { 1,2,1 }
1249      iSum = piSrcTmp[0] + piSrcTmp[2] +  (piSrcTmp[1] << 1);
1250      piDst[x] = Clip( (iSum +  2) >>  2 );
1251      piSrcTmp += 2;
1252    }
1253    piSrc += iSrcStride;
1254    piDst += iDstStride;
1255  }
1256};
1257
1258Void TRenFilter::xSampleDownVer2( Pel* piSrc, Int iSrcStride, Int iSrcWidth, Int iSrcHeight, Pel* piDst, Int iDstStride  )
1259{
1260  Int   iSum;
1261  Pel*  piSrcTmp;
1262
1263  for ( Int y = (iSrcHeight >> 1); y != 0; y-- )
1264  {
1265    piSrcTmp = piSrc -1 * iSrcStride;
1266    for ( Int x = 0; x < iSrcWidth; x++ )
1267    {
1268      // { 1,2,1 }
1269      iSum = piSrcTmp[0] + piSrcTmp[ iSrcStride << 1] +  (piSrcTmp[ iSrcStride ] << 1);
1270      piDst[x] = Clip( (iSum +  2) >>  2 );
1271      piSrcTmp += 1;
1272    }
1273    piSrc += (iSrcStride << 1);
1274    piDst += iDstStride;
1275  }
1276};
1277
1278Void TRenFilter::xSampleDownHor4( Pel* piSrc, Int iSrcStride, Int iSrcWidth, Int iHeight, Pel* piDst, Int iDstStride  )
1279{
1280  Int   iSum;
1281  Pel*  piSrcTmp;
1282
1283  Int iTmp0, iTmp1, iTmp2;
1284
1285  for ( Int y = iHeight; y != 0; y-- )
1286  {
1287    piSrcTmp = piSrc -2 ;
1288    for ( Int x = 0; x < (iSrcWidth >> 2); x++ )
1289    {
1290      // { 1,4,6,4,1 }
1291      iTmp0 = piSrcTmp[0] + piSrcTmp[4];
1292      iTmp1 = piSrcTmp[1] + piSrcTmp[3];
1293      iTmp2 = piSrcTmp[2];
1294
1295      iSum = iTmp0 +  (iTmp2 << 1) + ((iTmp1 + iTmp2) << 2);
1296      piDst[x] = Clip( (iSum +  8) >>  4 );
1297      piSrcTmp += 4;
1298    }
1299    piSrc += iSrcStride;
1300    piDst += iDstStride;
1301  }
1302};
1303
1304Void TRenFilter::xSampleDownHor8( Pel* piSrc, Int iSrcStride, Int iSrcWidth, Int iHeight, Pel* piDst, Int iDstStride  )
1305{
1306  Int   iSum;
1307  Pel*  piSrcTmp;
1308
1309  Int iTmp0, iTmp1, iTmp2, iTmp3;
1310
1311  for ( Int y = iHeight; y != 0; y-- )
1312  {
1313    piSrcTmp = piSrc -3;
1314    for ( Int x = 0; x < (iSrcWidth >> 3); x++ )
1315    {
1316      // { 1,6,15,20,15,6,1 }
1317      iTmp0 = piSrcTmp[0] + piSrcTmp[6];
1318      iTmp1 = piSrcTmp[1] + piSrcTmp[5];
1319      iTmp2 = piSrcTmp[2] + piSrcTmp[4];
1320      iTmp3 = piSrcTmp[3];
1321
1322      iSum = iTmp0 - iTmp2 + ( iTmp1  << 1) + ( (iTmp1 + iTmp3) << 2) + ((iTmp2 + iTmp3) << 4);
1323      piDst[x] = Clip( (iSum +  32) >>  6 );
1324      piSrcTmp += 8;
1325    }
1326    piSrc += iSrcStride;
1327    piDst += iDstStride;
1328  }
1329};
1330
1331Void TRenFilter::xDilate( Pel* piSrc, Int iSrcStride, Int iWidth, Int iHeight, Pel* piDst, Int iDstStride, Int iSize, Bool bVerticalDir, Bool bToTopOrLeft )
1332{
1333  Int iFDimStart   = 0;
1334  Int iInc         = 1;
1335  Int iSDimStart   = 0;
1336
1337  Int iFDimSrcStrd = bVerticalDir ? 1          : iSrcStride;
1338  Int iFDimDstStrd = bVerticalDir ? 1          : iDstStride;
1339
1340  Int iSDimSrcStrd = bVerticalDir ? iSrcStride : 1;
1341  Int iSDimDstStrd = bVerticalDir ? iDstStride : 1;
1342
1343  Int iFDimEnd     = bVerticalDir ? iWidth -1  : iHeight - 1;
1344  Int iSDimEnd     = bVerticalDir ? iHeight-1  : iWidth  - 1;
1345
1346  if ( bToTopOrLeft )
1347  {
1348    iSDimStart    = iSDimEnd;
1349    iSDimEnd      = 0;
1350    iInc         *= -1;
1351  }
1352
1353  for (Int iPosFDim = iFDimStart; iPosFDim <= iFDimEnd; iPosFDim++ )
1354  {
1355    Int  iCount      = 0;
1356    Bool bLastWasOne = false;
1357    Bool bDilate     = false;
1358    Int  iPosSDim    = iSDimStart;
1359    Bool bContinue   = true;
1360
1361    while ( bContinue )
1362    {
1363      if ( iCount == iSize )
1364      {
1365        iCount  = 0;
1366        bDilate = false;
1367      }
1368
1369      Pel iVal = piSrc[iPosSDim*iSDimSrcStrd];
1370      if( iVal == 0 && bLastWasOne )
1371      {
1372        iCount  = 0;
1373        bDilate = true;
1374      }
1375
1376      if( bDilate )
1377      {
1378        piDst[iPosSDim*iSDimDstStrd] = REN_USED_PEL;
1379        iCount++;
1380      }
1381      else
1382      {
1383        piDst[iPosSDim*iSDimDstStrd] = iVal;
1384      }
1385
1386
1387      bLastWasOne = (iVal == REN_USED_PEL);
1388      bContinue   = (iPosSDim != iSDimEnd);
1389      iPosSDim    += iInc;
1390    }
1391
1392    piSrc += iFDimSrcStrd;
1393    piDst += iFDimDstStrd;
1394  }
1395};
1396
1397
1398template Bool TRenFilter::compare   (TRenImage<Pel     >*, TRenImage<Pel>*      );
1399template Bool TRenFilter::compare   (TRenImagePlane<Pel>*, TRenImagePlane<Pel>* );
1400
1401template Void TRenFilter::mirrorHor(        TRenImage<Double>        *pcImage );
1402template Void TRenFilter::mirrorHor(        TRenImage<Pel>           *pcImage );
1403template Void TRenFilter::mirrorHor(        TRenImage<Int>           *pcImage );
1404template Void TRenFilter::mirrorHor(        TRenImagePlane<Pel>      *pcImagePlane );
Note: See TracBrowser for help on using the repository browser.