source: SHVCSoftware/branches/SHM-upgrade/source/App/TAppDownConvert/DownConvert.cpp @ 918

Last change on this file since 918 was 595, checked in by seregin, 11 years ago

merge with SHM-5.0-dev branch

File size: 26.5 KB
Line 
1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
4 * granted under this license. 
5 *
6 * Copyright (c) 2010-2014, ITU/ISO/IEC
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include "DownConvert.h"
35
36#include <cmath>
37#include <cstring>
38
39
40#define  TMM_TABLE_SIZE          512
41
42
43//=================================================
44//
45//   G E N E R A L   M A I N   F U N C T I O N S
46//
47//=================================================
48
49DownConvert::DownConvert()
50: m_iImageStride            ( 0 )
51, m_paiImageBuffer          ( 0 )
52, m_paiTmp1dBuffer          ( 0 )
53{
54}
55 
56DownConvert::~DownConvert()
57{
58  xDestroy();
59}
60
61bool
62DownConvert::init( int iMaxWidth, int iMaxHeight, int iMaxMargin )
63{
64  xDestroy();
65
66  iMaxWidth                += 2 * iMaxMargin;
67  iMaxHeight               += 2 * iMaxMargin;
68  int iPicSize              =   iMaxWidth * iMaxHeight;
69  int iMaxDim               = ( iMaxWidth > iMaxHeight ? iMaxWidth : iMaxHeight );
70  m_iImageStride            = iMaxWidth;
71  m_paiImageBuffer          = new int [ iPicSize ];
72  m_paiTmp1dBuffer          = new int [ iMaxDim ];
73
74  ROFRS( m_paiImageBuffer,          true );
75  ROFRS( m_paiTmp1dBuffer,          true );
76
77  return false;
78}
79
80void
81DownConvert::destroy()
82{
83  delete this;
84}
85
86//===========================================================================
87//
88//   M A I N   F U N C T I O N S   F O R   D O W N C O N V E R T   T O O L
89//
90//===========================================================================
91
92
93void
94DownConvert::downsamplingSVC( unsigned char*    pucBufferY,   int   iStrideY,
95                              unsigned char*    pucBufferU,   int   iStrideU,
96                              unsigned char*    pucBufferV,   int   iStrideV,
97                              ResizeParameters* pcParameters, bool  bBotCoincided )
98{
99  int   iBaseW                  =   pcParameters->m_iFrameWidth;
100  int   iBaseH                  =   pcParameters->m_iFrameHeight;
101  int   iCurrW                  =   pcParameters->m_iRefLayerFrmWidth;
102  int   iCurrH                  =   pcParameters->m_iRefLayerFrmHeight;
103  bool  bTopAndBottomResampling = ( pcParameters->m_bRefLayerFrameMbsOnlyFlag == false  &&
104                                    pcParameters->m_bRefLayerFieldPicFlag     == false  &&
105                                    pcParameters->m_bFrameMbsOnlyFlag         == false  &&
106                                    pcParameters->m_bFieldPicFlag             == false    );
107  bool  bVerticalDownsampling   = ( pcParameters->m_bFrameMbsOnlyFlag         == true   &&
108                                    pcParameters->m_bRefLayerFieldPicFlag     == true     );
109  bool  bCurrBotField           = ( pcParameters->m_bFieldPicFlag             == true   &&
110                                    pcParameters->m_bBotFieldFlag             == true     );
111  bool  bBotFieldFlag           = ( pcParameters->m_bRefLayerFrameMbsOnlyFlag ?  false
112                                  : pcParameters->m_bFieldPicFlag             ?  pcParameters->m_bBotFieldFlag
113                                  : pcParameters->m_bRefLayerFieldPicFlag     ?  pcParameters->m_bRefLayerBotFieldFlag
114                                  : false );
115  int   iBaseField              = ( pcParameters->m_bRefLayerFrameMbsOnlyFlag ?  0 : 1 );
116  int   iCurrField              = ( pcParameters->m_bFieldPicFlag             ?  1 : 0 );
117  int   iBaseBot                = ( bBotFieldFlag ? 1 : 0 );
118  int   iCurrBot                = ( bCurrBotField ? 1 : 0 );
119
120  //==== check bot field coincided parameter for interlaced to progressive resampling =====
121  if( pcParameters->m_bRefLayerFrameMbsOnlyFlag && ! pcParameters->m_bFrameMbsOnlyFlag )
122  {
123    bBotFieldFlag = bBotCoincided;
124  }
125
126  //=======================
127  //=====   L U M A   =====
128  //=======================
129  assert( bTopAndBottomResampling == false );
130  if( !bTopAndBottomResampling )
131  {
132    unsigned char* pSrc = pucBufferY + iStrideY * iCurrBot;
133    unsigned char* pDes = pucBufferY + iStrideY * iBaseBot;
134    xCopyToImageBuffer  ( pSrc,         iCurrW, iCurrH >> iCurrField, iStrideY << iCurrField );
135    xCompDownsampling   ( pcParameters, false,  bBotFieldFlag,        bVerticalDownsampling  );
136    xCopyFromImageBuffer( pDes,         iBaseW, iBaseH >> iBaseField, iStrideY << iBaseField );
137  }
138
139  iBaseW >>= 1;
140  iBaseH >>= 1;
141  iCurrW >>= 1;
142  iCurrH >>= 1;
143
144  //===========================
145  //=====   C H R O M A   =====
146  //===========================
147  if( !bTopAndBottomResampling )
148  {
149    //===== U =====
150    unsigned char* pSrc = pucBufferU + iStrideU * iCurrBot;
151    unsigned char* pDes = pucBufferU + iStrideU * iBaseBot;
152    xCopyToImageBuffer  ( pSrc,         iCurrW, iCurrH >> iCurrField, iStrideU << iCurrField );
153    xCompDownsampling   ( pcParameters, true,   bBotFieldFlag,        bVerticalDownsampling  );
154    xCopyFromImageBuffer( pDes,         iBaseW, iBaseH >> iBaseField, iStrideU << iBaseField );
155
156    //===== V =====
157    pSrc = pucBufferV + iStrideV * iCurrBot;
158    pDes = pucBufferV + iStrideV * iBaseBot;
159    xCopyToImageBuffer  ( pSrc,         iCurrW, iCurrH >> iCurrField, iStrideV << iCurrField );
160    xCompDownsampling   ( pcParameters, true,   bBotFieldFlag,        bVerticalDownsampling  );
161    xCopyFromImageBuffer( pDes,         iBaseW, iBaseH >> iBaseField, iStrideV << iBaseField );
162  }
163}
164
165
166//======================================================
167//
168//   G E N E R A L   H E L P E R    F U N C T I O N S
169//
170//======================================================
171
172void
173DownConvert::xDestroy()
174{
175  delete [] m_paiImageBuffer;
176  delete [] m_paiTmp1dBuffer;
177  m_paiImageBuffer          = 0;
178  m_paiTmp1dBuffer          = 0;
179}
180
181int
182DownConvert::xClip( int iValue, int imin, int imax )
183{
184  ROTRS( iValue < imin, imin );
185  ROTRS( iValue > imax, imax );
186  return iValue;
187}
188
189
190//===============================================================================
191//
192//   H E L P E R   F U N C T I O N S   F O R   D O W N C O N V E R T   T O O L
193//
194//===============================================================================
195
196void
197DownConvert::xCopyToImageBuffer( unsigned char* pucSrc, int iWidth, int iHeight, int iStride )
198{
199  int* piDes = m_paiImageBuffer;
200  for( int j = 0; j < iHeight; j++ )
201  {
202    for( int i = 0; i < iWidth;  i++ )
203    {
204      piDes[i] = (int)pucSrc[i];
205    }
206    piDes   += m_iImageStride;
207    pucSrc  += iStride;
208  }
209}
210
211void
212DownConvert::xCopyFromImageBuffer( unsigned char* pucDes, int iWidth, int iHeight, int iStride )
213{
214  int* piSrc = m_paiImageBuffer;
215  for( int j = 0; j < iHeight; j++ )
216  {
217    for( int i = 0; i < iWidth;  i++ )
218    {
219      pucDes[i] = (unsigned char)piSrc[i];
220    }
221    pucDes  += iStride;
222    piSrc   += m_iImageStride;
223  }
224}
225
226void
227DownConvert::xCompDownsampling( ResizeParameters* pcParameters, bool bChroma, bool bBotFlag, bool bVerticalDownsampling )
228{
229  //===== set general parameters =====
230  int   iBotField   = ( bBotFlag ? 1 : 0 );
231  int   iFactor     = ( !bChroma ? 1 : 2 );
232  int   iRefPhaseX  = ( !bChroma ? 0 : pcParameters->m_iChromaPhaseX );
233  int   iRefPhaseY  = ( !bChroma ? 0 : pcParameters->m_iChromaPhaseY );
234  int   iPhaseX     = ( !bChroma ? 0 : pcParameters->m_iRefLayerChromaPhaseX );
235  int   iPhaseY     = ( !bChroma ? 0 : pcParameters->m_iRefLayerChromaPhaseY );
236  int   iRefW       = pcParameters->m_iFrameWidth         / iFactor;  // reference layer frame width
237  int   iRefH       = pcParameters->m_iFrameHeight        / iFactor;  // reference layer frame height
238  int   iOutW       = pcParameters->m_iScaledRefFrmWidth  / iFactor;  // scaled reference layer frame width
239  int   iOutH       = pcParameters->m_iScaledRefFrmHeight / iFactor;  // scaled reference layer frame height
240  int   iGlobalW    = pcParameters->m_iRefLayerFrmWidth   / iFactor;  // current frame width
241  int   iGlobalH    = pcParameters->m_iRefLayerFrmHeight  / iFactor;  // current frame height
242  int   iLeftOffset = pcParameters->m_iLeftFrmOffset      / iFactor;  // current left frame offset
243  int   iTopOffset  = pcParameters->m_iTopFrmOffset       / iFactor;  // current  top frame offset
244
245  //===== set input/output size =====
246  int   iBaseField  = ( pcParameters->m_bRefLayerFrameMbsOnlyFlag ? 0 : 1 );
247  int   iCurrField  = ( pcParameters->m_bRefLayerFrameMbsOnlyFlag && pcParameters->m_bFrameMbsOnlyFlag ? 0 : 1 );
248  int   iBaseW      = iRefW;
249  int   iBaseH      = iRefH       >> iBaseField;
250  int   iCurrW      = iGlobalW;
251  int   iCurrH      = iGlobalH    >> iCurrField;
252  int   iLOffset    = iLeftOffset;
253  int   iTOffset    = iTopOffset  >> iCurrField;
254  int   iROffset    = iCurrW - iLOffset -   iOutW;
255  int   iBOffset    = iCurrH - iTOffset - ( iOutH >> iCurrField );
256
257  //===== set position calculation parameters =====
258  int   iScaledW    = iOutW;
259  int   iScaledH    = ( ! pcParameters->m_bRefLayerFrameMbsOnlyFlag || pcParameters->m_bFrameMbsOnlyFlag ? iOutH : iOutH / 2 );
260  int   iShiftX     = ( pcParameters->m_iLevelIdc <= 30 ? 16 : 31 - CeilLog2( iScaledW ) );
261  int   iShiftY     = ( pcParameters->m_iLevelIdc <= 30 ? 16 : 31 - CeilLog2( iScaledH ) );
262  int   iScaleX     = ( ( (unsigned int)iScaledW << iShiftX ) + ( iRefW >> 1 ) ) / iRefW;
263  int   iScaleY     = ( ( (unsigned int)iScaledH << iShiftY ) + ( iRefH >> 1 ) ) / iRefH;
264  if( ! pcParameters->m_bFrameMbsOnlyFlag || ! pcParameters->m_bRefLayerFrameMbsOnlyFlag )
265  {
266    if( pcParameters->m_bRefLayerFrameMbsOnlyFlag )
267    {
268      iPhaseY       = iPhaseY + 4 * iBotField + ( 3 - iFactor );
269#if ZERO_PHASE
270      iRefPhaseY    = 2 * iRefPhaseY + 0;
271#else
272      iRefPhaseY    = 2 * iRefPhaseY + 2;
273#endif
274    }
275    else
276    {
277      iPhaseY       = iPhaseY    + 4 * iBotField;
278      iRefPhaseY    = iRefPhaseY + 4 * iBotField;
279    }
280  }
281#if ZERO_PHASE
282  int   iAddX       = ( ( ( iScaledW * ( 0 + iRefPhaseX ) ) << ( iShiftX - 2 ) ) + ( iRefW >> 1 ) ) / iRefW + ( 1 << ( iShiftX - 5 ) );
283  int   iAddY       = ( ( ( iScaledH * ( 0 + iRefPhaseY ) ) << ( iShiftY - 2 ) ) + ( iRefH >> 1 ) ) / iRefH + ( 1 << ( iShiftY - 5 ) );
284  int   iDeltaX     = 4 * ( 0 + iPhaseX ) - ( iLeftOffset << 4 );
285  int   iDeltaY     = 4 * ( 0 + iPhaseY ) - ( iTopOffset  << 4 );
286#else
287  int   iAddX       = ( ( ( iScaledW * ( 2 + iRefPhaseX ) ) << ( iShiftX - 2 ) ) + ( iRefW >> 1 ) ) / iRefW + ( 1 << ( iShiftX - 5 ) );
288  int   iAddY       = ( ( ( iScaledH * ( 2 + iRefPhaseY ) ) << ( iShiftY - 2 ) ) + ( iRefH >> 1 ) ) / iRefH + ( 1 << ( iShiftY - 5 ) );
289  int   iDeltaX     = 4 * ( 2 + iPhaseX ) - ( iLeftOffset << 4 );
290  int   iDeltaY     = 4 * ( 2 + iPhaseY ) - ( iTopOffset  << 4 );
291#endif
292  if( ! pcParameters->m_bFrameMbsOnlyFlag || ! pcParameters->m_bRefLayerFrameMbsOnlyFlag )
293  {
294#if ZERO_PHASE
295    iAddY           = ( ( ( iScaledH * ( 0 + iRefPhaseY ) ) << ( iShiftY - 3 ) ) + ( iRefH >> 1 ) ) / iRefH + ( 1 << ( iShiftY - 5 ) );
296    iDeltaY         = 2 * ( 0 + iPhaseY ) - ( iTopOffset  << 3 );
297#else
298    iAddY           = ( ( ( iScaledH * ( 2 + iRefPhaseY ) ) << ( iShiftY - 3 ) ) + ( iRefH >> 1 ) ) / iRefH + ( 1 << ( iShiftY - 5 ) );
299    iDeltaY         = 2 * ( 2 + iPhaseY ) - ( iTopOffset  << 3 );
300#endif
301  }
302
303  //===== vertical downsampling to generate a field signal from a progressive frame =====
304  if( bVerticalDownsampling )
305  {
306    xVertDownsampling( iCurrW, iCurrH, bBotFlag );
307  }
308
309  //===== basic downsampling of a frame or field =====
310  xBasicDownsampling( iBaseW,   iBaseH,   iCurrW,   iCurrH,
311                      iLOffset, iTOffset, iROffset, iBOffset,
312                      iShiftX,  iShiftY,  iScaleX,  iScaleY,
313                      iAddX,    iAddY,    iDeltaX,  iDeltaY );
314}
315
316void
317DownConvert::xVertDownsampling( int   iBaseW,
318                                int   iBaseH,
319                                bool  bBotFlag )
320{
321  int aiVertFilter[13]  = { 2, 0, -4, -3, 5, 19, 26, 19, 5, -3, -4, 0, 2 };
322  int iBotField         = ( bBotFlag ? 1 : 0 );
323  int iCurrW            = iBaseW;
324  int iCurrH            = iBaseH << 1;
325
326  //===== vertical downsampling =====
327  for( int j = 0; j < iCurrW; j++ )
328  {
329    int* piSrc = &m_paiImageBuffer[j];
330    for( int i = 0; i < iBaseH; i++ )
331    {
332      m_paiTmp1dBuffer[i] = 0;
333      for( int k = 0; k < 13; k++ )
334      {
335        int m = xClip( 2 * i + iBotField + k - 6, 0, iCurrH - 1 );
336        m_paiTmp1dBuffer[i] += aiVertFilter[k] * piSrc[m*m_iImageStride];
337      }
338      m_paiTmp1dBuffer[i] = ( m_paiTmp1dBuffer[i] + 32 ) >> 6;
339    }
340    //--- clip and copy back to image buffer ---
341    for( int n = 0; n < iBaseH; n++ )
342    {
343      piSrc[n*m_iImageStride] = xClip( m_paiTmp1dBuffer[n], 0, 255 );
344    }
345  }
346}
347
348void
349DownConvert::xBasicDownsampling( int iBaseW,   int iBaseH,   int iCurrW,   int iCurrH,
350                                 int iLOffset, int iTOffset, int iROffset, int iBOffset,
351                                 int iShiftX,  int iShiftY,  int iScaleX,  int iScaleY,
352                                 int iAddX,    int iAddY,    int iDeltaX,  int iDeltaY )
353{
354  const int filter16[8][16][12] =
355  {
356    { // D = 1
357      {   0,   0,   0,   0,   0, 128,   0,   0,   0,   0,   0,   0 },
358      {   0,   0,   0,   2,  -6, 127,   7,  -2,   0,   0,   0,   0 },
359      {   0,   0,   0,   3, -12, 125,  16,  -5,   1,   0,   0,   0 },
360      {   0,   0,   0,   4, -16, 120,  26,  -7,   1,   0,   0,   0 },
361      {   0,   0,   0,   5, -18, 114,  36, -10,   1,   0,   0,   0 },
362      {   0,   0,   0,   5, -20, 107,  46, -12,   2,   0,   0,   0 },
363      {   0,   0,   0,   5, -21,  99,  57, -15,   3,   0,   0,   0 },
364      {   0,   0,   0,   5, -20,  89,  68, -18,   4,   0,   0,   0 },
365      {   0,   0,   0,   4, -19,  79,  79, -19,   4,   0,   0,   0 },
366      {   0,   0,   0,   4, -18,  68,  89, -20,   5,   0,   0,   0 },
367      {   0,   0,   0,   3, -15,  57,  99, -21,   5,   0,   0,   0 },
368      {   0,   0,   0,   2, -12,  46, 107, -20,   5,   0,   0,   0 },
369      {   0,   0,   0,   1, -10,  36, 114, -18,   5,   0,   0,   0 },
370      {   0,   0,   0,   1,  -7,  26, 120, -16,   4,   0,   0,   0 },
371      {   0,   0,   0,   1,  -5,  16, 125, -12,   3,   0,   0,   0 },
372      {   0,   0,   0,   0,  -2,   7, 127,  -6,   2,   0,   0,   0 }
373    },
374    { // D = 1.5
375      {   0,   2,   0, -14,  33,  86,  33, -14,   0,   2,   0,   0 },
376      {   0,   1,   1, -14,  29,  85,  38, -13,  -1,   2,   0,   0 },
377      {   0,   1,   2, -14,  24,  84,  43, -12,  -2,   2,   0,   0 },
378      {   0,   1,   2, -13,  19,  83,  48, -11,  -3,   2,   0,   0 },
379      {   0,   0,   3, -13,  15,  81,  53, -10,  -4,   3,   0,   0 },
380      {   0,   0,   3, -12,  11,  79,  57,  -8,  -5,   3,   0,   0 },
381      {   0,   0,   3, -11,   7,  76,  62,  -5,  -7,   3,   0,   0 },
382      {   0,   0,   3, -10,   3,  73,  65,  -2,  -7,   3,   0,   0 },
383      {   0,   0,   3,  -9,   0,  70,  70,   0,  -9,   3,   0,   0 },
384      {   0,   0,   3,  -7,  -2,  65,  73,   3, -10,   3,   0,   0 },
385      {   0,   0,   3,  -7,  -5,  62,  76,   7, -11,   3,   0,   0 },
386      {   0,   0,   3,  -5,  -8,  57,  79,  11, -12,   3,   0,   0 },
387      {   0,   0,   3,  -4, -10,  53,  81,  15, -13,   3,   0,   0 },
388      {   0,   0,   2,  -3, -11,  48,  83,  19, -13,   2,   1,   0 },
389      {   0,   0,   2,  -2, -12,  43,  84,  24, -14,   2,   1,   0 },
390      {   0,   0,   2,  -1, -13,  38,  85,  29, -14,   1,   1,   0 }
391    },
392    { // D = 2
393      {   0,   5,   -6,  -10,  37,  76,   37,  -10,  -6,    5,  0,   0}, //0
394      {   0,   5,   -4,  -11,  33,  76,   40,  -9,    -7,    5,  0,   0}, //1
395      //{   0,   5,   -3,  -12,  28,  75,   44,  -7,    -8,    5,  1,   0}, //2
396      {  -1,   5,   -3,  -12,  29,  75,   45,  -7,    -8,   5,  0,   0}, //2 new coefficients in m24499
397      {  -1,   4,   -2,  -13,  25,  75,   48,  -5,    -9,    5,  1,   0}, //3
398      {  -1,   4,   -1,  -13,  22,  73,   52,  -3,    -10,  4,  1,   0}, //4
399      {  -1,   4,   0,    -13,  18,  72,   55,  -1,    -11,  4,  2,  -1}, //5
400      {  -1,   4,   1,    -13,  14,  70,   59,  2,    -12,  3,  2,  -1}, //6
401      {  -1,   3,   1,    -13,  11,  68,   62,  5,    -12,  3,  2,  -1}, //7
402      {  -1,   3,   2,    -13,  8,  65,   65,  8,    -13,  2,  3,  -1}, //8
403      {  -1,   2,   3,    -12,  5,  62,   68,  11,    -13,  1,  3,  -1}, //9
404      {  -1,   2,   3,    -12,  2,  59,   70,  14,    -13,  1,  4,  -1}, //10
405      {  -1,   2,   4,    -11,  -1,  55,   72,  18,    -13,  0,  4,  -1}, //11
406      {   0,   1,   4,    -10,  -3,  52,   73,  22,    -13,  -1,  4,  -1}, //12
407      {   0,   1,   5,    -9,    -5,  48,   75,  25,    -13,  -2,  4,  -1}, //13
408      //{   0,   1,   5,    -8,    -7,  44,   75,  28,    -12,  -3,  5,   0}, //14
409      {    0,   0,   5,    -8,   -7,  45,   75,  29,    -12,  -3,  5,  -1}  , //14 new coefficients in m24499 
410      {   0,   0,   5,    -7,    -9,  40,   76,  33,    -11,  -4,  5,   0}, //15
411    },
412    { // D = 2.5
413      {   2,  -3,   -9,  6,   39,  58,   39,  6,   -9,  -3,    2,    0}, // 0
414      {   2,  -3,   -9,  4,   38,  58,   43,  7,   -9,  -4,    1,    0}, // 1
415      {   2,  -2,   -9,  2,   35,  58,   44,  9,   -8,  -4,    1,    0}, // 2
416      {   1,  -2,   -9,  1,   34,  58,   46,  11,   -8,  -5,    1,    0}, // 3
417      //{   1,  -1,   -8,  -1,   31,  57,   48,  13,   -8,  -5,    1,    0}, // 4
418      {   1,  -1,   -8,  -1,   31,  57,   47,  13,   -7,  -5,    1,    0},  // 4 new coefficients in m24499 
419      {   1,  -1,   -8,  -2,   29,  56,   49,  15,   -7,  -6,    1,    1}, // 5
420      {   1,  0,   -8,  -3,   26,  55,   51,  17,   -7,  -6,    1,    1}, // 6
421      {   1,  0,   -7,  -4,   24,  54,   52,  19,   -6,  -7,    1,    1}, // 7
422      {   1,  0,   -7,  -5,   22,  53,   53,  22,   -5,  -7,    0,    1}, // 8
423      {   1,  1,   -7,  -6,   19,  52,   54,  24,   -4,  -7,    0,    1}, // 9
424      {   1,  1,   -6,  -7,   17,  51,   55,  26,   -3,  -8,    0,    1}, // 10
425      {   1,  1,   -6,  -7,   15,  49,   56,  29,   -2,  -8,    -1,    1}, // 11
426      //{   0,  1,   -5,  -8,   13,  48,   57,  31,   -1,  -8,    -1,    1}, // 12 new coefficients in m24499
427      {   0,  1,   -5,  -7,   13,  47,  57,  31,  -1,    -8,   -1,    1}, // 12   
428      {   0,  1,   -5,  -8,   11,  46,   58,  34,   1,    -9,    -2,    1}, // 13
429      {   0,  1,   -4,  -8,   9,    44,   58,  35,   2,    -9,    -2,    2}, // 14
430      {   0,  1,   -4,  -9,   7,    43,   58,  38,   4,    -9,    -3,    2}, // 15
431    },
432    { // D = 3
433      {  -2,  -7,   0,  17,  35,  43,  35,  17,   0,  -7,  -5,   2 },
434      {  -2,  -7,  -1,  16,  34,  43,  36,  18,   1,  -7,  -5,   2 },
435      {  -1,  -7,  -1,  14,  33,  43,  36,  19,   1,  -6,  -5,   2 },
436      {  -1,  -7,  -2,  13,  32,  42,  37,  20,   3,  -6,  -5,   2 },
437      {   0,  -7,  -3,  12,  31,  42,  38,  21,   3,  -6,  -5,   2 },
438      {   0,  -7,  -3,  11,  30,  42,  39,  23,   4,  -6,  -6,   1 },
439      {   0,  -7,  -4,  10,  29,  42,  40,  24,   5,  -6,  -6,   1 },
440      {   1,  -7,  -4,   9,  27,  41,  40,  25,   6,  -5,  -6,   1 },
441      {   1,  -6,  -5,   7,  26,  41,  41,  26,   7,  -5,  -6,   1 },
442      {   1,  -6,  -5,   6,  25,  40,  41,  27,   9,  -4,  -7,   1 },
443      {   1,  -6,  -6,   5,  24,  40,  42,  29,  10,  -4,  -7,   0 },
444      {   1,  -6,  -6,   4,  23,  39,  42,  30,  11,  -3,  -7,   0 },
445      {   2,  -5,  -6,   3,  21,  38,  42,  31,  12,  -3,  -7,   0 },
446      {   2,  -5,  -6,   3,  20,  37,  42,  32,  13,  -2,  -7,  -1 },
447      {   2,  -5,  -6,   1,  19,  36,  43,  33,  14,  -1,  -7,  -1 },
448      {   2,  -5,  -7,   1,  18,  36,  43,  34,  16,  -1,  -7,  -2 }
449    },
450    { // D = 3.5
451      {  -6,  -3,   5,  19,  31,  36,  31,  19,   5,  -3,  -6,   0 },
452      {  -6,  -4,   4,  18,  31,  37,  32,  20,   6,  -3,  -6,  -1 },
453      {  -6,  -4,   4,  17,  30,  36,  33,  21,   7,  -3,  -6,  -1 },
454      {  -5,  -5,   3,  16,  30,  36,  33,  22,   8,  -2,  -6,  -2 },
455      {  -5,  -5,   2,  15,  29,  36,  34,  23,   9,  -2,  -6,  -2 },
456      {  -5,  -5,   2,  15,  28,  36,  34,  24,  10,  -2,  -6,  -3 },
457      {  -4,  -5,   1,  14,  27,  36,  35,  24,  10,  -1,  -6,  -3 },
458      {  -4,  -5,   0,  13,  26,  35,  35,  25,  11,   0,  -5,  -3 },
459      {  -4,  -6,   0,  12,  26,  36,  36,  26,  12,   0,  -6,  -4 },
460      {  -3,  -5,   0,  11,  25,  35,  35,  26,  13,   0,  -5,  -4 },
461      {  -3,  -6,  -1,  10,  24,  35,  36,  27,  14,   1,  -5,  -4 },
462      {  -3,  -6,  -2,  10,  24,  34,  36,  28,  15,   2,  -5,  -5 },
463      {  -2,  -6,  -2,   9,  23,  34,  36,  29,  15,   2,  -5,  -5 },
464      {  -2,  -6,  -2,   8,  22,  33,  36,  30,  16,   3,  -5,  -5 },
465      {  -1,  -6,  -3,   7,  21,  33,  36,  30,  17,   4,  -4,  -6 },
466      {  -1,  -6,  -3,   6,  20,  32,  37,  31,  18,   4,  -4,  -6 }
467    },
468    { // D = 4
469      {  -9,   0,   9,  20,  28,  32,  28,  20,   9,   0,  -9,   0 },
470      {  -9,   0,   8,  19,  28,  32,  29,  20,  10,   0,  -4,  -5 },
471      {  -9,  -1,   8,  18,  28,  32,  29,  21,  10,   1,  -4,  -5 },
472      {  -9,  -1,   7,  18,  27,  32,  30,  22,  11,   1,  -4,  -6 },
473      {  -8,  -2,   6,  17,  27,  32,  30,  22,  12,   2,  -4,  -6 },
474      {  -8,  -2,   6,  16,  26,  32,  31,  23,  12,   2,  -4,  -6 },
475      {  -8,  -2,   5,  16,  26,  31,  31,  23,  13,   3,  -3,  -7 },
476      {  -8,  -3,   5,  15,  25,  31,  31,  24,  14,   4,  -3,  -7 },
477      {  -7,  -3,   4,  14,  25,  31,  31,  25,  14,   4,  -3,  -7 },
478      {  -7,  -3,   4,  14,  24,  31,  31,  25,  15,   5,  -3,  -8 },
479      {  -7,  -3,   3,  13,  23,  31,  31,  26,  16,   5,  -2,  -8 },
480      {  -6,  -4,   2,  12,  23,  31,  32,  26,  16,   6,  -2,  -8 },
481      {  -6,  -4,   2,  12,  22,  30,  32,  27,  17,   6,  -2,  -8 },
482      {  -6,  -4,   1,  11,  22,  30,  32,  27,  18,   7,  -1,  -9 },
483      {  -5,  -4,   1,  10,  21,  29,  32,  28,  18,   8,  -1,  -9 },
484      {  -5,  -4,   0,  10,  20,  29,  32,  28,  19,   8,   0,  -9 }
485    },
486    { // D = 5.5
487      {  -8,   7,  13,  18,  22,  24,  22,  18,  13,   7,   2, -10 },
488      {  -8,   7,  13,  18,  22,  23,  22,  19,  13,   7,   2, -10 },
489      {  -8,   6,  12,  18,  22,  23,  22,  19,  14,   8,   2, -10 },
490      {  -9,   6,  12,  17,  22,  23,  23,  19,  14,   8,   3, -10 },
491      {  -9,   6,  12,  17,  21,  23,  23,  19,  14,   9,   3, -10 },
492      {  -9,   5,  11,  17,  21,  23,  23,  20,  15,   9,   3, -10 },
493      {  -9,   5,  11,  16,  21,  23,  23,  20,  15,   9,   4, -10 },
494      {  -9,   5,  10,  16,  21,  23,  23,  20,  15,  10,   4, -10 },
495      { -10,   5,  10,  16,  20,  23,  23,  20,  16,  10,   5, -10 },
496      { -10,   4,  10,  15,  20,  23,  23,  21,  16,  10,   5,  -9 },
497      { -10,   4,   9,  15,  20,  23,  23,  21,  16,  11,   5,  -9 },
498      { -10,   3,   9,  15,  20,  23,  23,  21,  17,  11,   5,  -9 },
499      { -10,   3,   9,  14,  19,  23,  23,  21,  17,  12,   6,  -9 },
500      { -10,   3,   8,  14,  19,  23,  23,  22,  17,  12,   6,  -9 },
501      { -10,   2,   8,  14,  19,  22,  23,  22,  18,  12,   6,  -8 },
502      { -10,   2,   7,  13,  19,  22,  23,  22,  18,  13,   7,  -8 }
503    }
504  };
505
506  //===== determine filter sets =====
507  int iCropW      = iCurrW - iLOffset - iROffset;
508  int iCropH      = iCurrH - iTOffset - iBOffset;
509  int iVerFilter  = 0;
510  int iHorFilter  = 0;
511  if      (  4 * iCropH > 15 * iBaseH )   iVerFilter  = 7;
512  else if (  7 * iCropH > 20 * iBaseH )   iVerFilter  = 6;
513  else if (  2 * iCropH >  5 * iBaseH )   iVerFilter  = 5;
514  else if (  1 * iCropH >  2 * iBaseH )   iVerFilter  = 4;
515  else if (  3 * iCropH >  5 * iBaseH )   iVerFilter  = 3;
516  else if (  4 * iCropH >  5 * iBaseH )   iVerFilter  = 2;
517  else if ( 19 * iCropH > 20 * iBaseH )   iVerFilter  = 1;
518  if      (  4 * iCropW > 15 * iBaseW )   iHorFilter  = 7;
519  else if (  7 * iCropW > 20 * iBaseW )   iHorFilter  = 6;
520  else if (  2 * iCropW >  5 * iBaseW )   iHorFilter  = 5;
521  else if (  1 * iCropW >  2 * iBaseW )   iHorFilter  = 4;
522  else if (  3 * iCropW >  5 * iBaseW )   iHorFilter  = 3;
523  else if (  4 * iCropW >  5 * iBaseW )   iHorFilter  = 2;
524  else if ( 19 * iCropW > 20 * iBaseW )   iHorFilter  = 1;
525
526  int iShiftXM4 = iShiftX - 4;
527  int iShiftYM4 = iShiftY - 4;
528
529  //===== horizontal downsampling =====
530  {
531    for( int j = 0; j < iCurrH; j++ )
532    {
533      int* piSrc = &m_paiImageBuffer[j*m_iImageStride];
534      for( int i = 0; i < iBaseW; i++ )
535      {
536        int iRefPos16 = (int)( (unsigned int)( i * iScaleX + iAddX ) >> iShiftXM4 ) - iDeltaX;
537        int iPhase    = iRefPos16  & 15;
538        int iRefPos   = iRefPos16 >>  4;
539
540        m_paiTmp1dBuffer[i] = 0;
541        for( int k = 0; k < 12; k++ )
542        {
543          int m = xClip( iRefPos + k - 5, 0, iCurrW - 1 );
544          m_paiTmp1dBuffer[i] += filter16[iHorFilter][iPhase][k] * piSrc[m];
545        }
546      }
547      //--- copy row back to image buffer ---
548      memcpy( piSrc, m_paiTmp1dBuffer, iBaseW*sizeof(int) );
549    }
550  }
551
552  //===== vertical downsampling =====
553  {
554    for( int i = 0; i < iBaseW; i++ )
555    {
556      int* piSrc = &m_paiImageBuffer[i];
557      for( int j = 0; j < iBaseH; j++ )
558      {
559        int iRefPos16 = (int)( (unsigned int)( j * iScaleY + iAddY ) >> iShiftYM4 ) - iDeltaY;
560        int iPhase    = iRefPos16  & 15;
561        int iRefPos   = iRefPos16 >>  4;
562
563        m_paiTmp1dBuffer[j] = 0;
564        for( int k = 0; k < 12; k++ )
565        {
566          int m = xClip( iRefPos + k - 5, 0, iCurrH - 1 );
567          m_paiTmp1dBuffer[j] += filter16[iVerFilter][iPhase][k] * piSrc[m*m_iImageStride];
568        }
569        m_paiTmp1dBuffer[j] = ( m_paiTmp1dBuffer[j] + 8192 ) >> 14;
570      }
571      //--- clip and copy back to image buffer ---
572      for( int n = 0; n < iBaseH; n++ )
573      {
574        piSrc[n*m_iImageStride] = xClip( m_paiTmp1dBuffer[n], 0, 255 );
575      }
576    }
577  }
578}
579
580
581
582
Note: See TracBrowser for help on using the repository browser.