[595] | 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 | |
---|
| 49 | DownConvert::DownConvert() |
---|
| 50 | : m_iImageStride ( 0 ) |
---|
| 51 | , m_paiImageBuffer ( 0 ) |
---|
| 52 | , m_paiTmp1dBuffer ( 0 ) |
---|
| 53 | { |
---|
| 54 | } |
---|
| 55 | |
---|
| 56 | DownConvert::~DownConvert() |
---|
| 57 | { |
---|
| 58 | xDestroy(); |
---|
| 59 | } |
---|
| 60 | |
---|
| 61 | bool |
---|
| 62 | DownConvert::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 | |
---|
| 80 | void |
---|
| 81 | DownConvert::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 | |
---|
| 93 | void |
---|
| 94 | DownConvert::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 | |
---|
| 172 | void |
---|
| 173 | DownConvert::xDestroy() |
---|
| 174 | { |
---|
| 175 | delete [] m_paiImageBuffer; |
---|
| 176 | delete [] m_paiTmp1dBuffer; |
---|
| 177 | m_paiImageBuffer = 0; |
---|
| 178 | m_paiTmp1dBuffer = 0; |
---|
| 179 | } |
---|
| 180 | |
---|
| 181 | int |
---|
| 182 | DownConvert::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 | |
---|
| 196 | void |
---|
| 197 | DownConvert::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 | |
---|
| 211 | void |
---|
| 212 | DownConvert::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 | |
---|
| 226 | void |
---|
| 227 | DownConvert::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 | |
---|
| 316 | void |
---|
| 317 | DownConvert::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 | |
---|
| 348 | void |
---|
| 349 | DownConvert::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 | |
---|