/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2011, ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ // Include files #include "CommonDef.h" #include "TComYuv.h" #include "TComWedgelet.h" #include #include using namespace std; #if H_3D_DIM_DMM TComWedgelet::TComWedgelet( UInt uiWidth, UInt uiHeight ) : m_uhXs ( 0 ), m_uhYs ( 0 ), m_uhXe ( 0 ), m_uhYe ( 0 ), m_uhOri ( 0 ), m_eWedgeRes( FULL_PEL ), m_bIsCoarse( false ) { create( uiWidth, uiHeight ); } TComWedgelet::TComWedgelet( const TComWedgelet &rcWedge ) : m_uhXs ( rcWedge.m_uhXs ), m_uhYs ( rcWedge.m_uhYs ), m_uhXe ( rcWedge.m_uhXe ), m_uhYe ( rcWedge.m_uhYe ), m_uhOri ( rcWedge.m_uhOri ), m_eWedgeRes( rcWedge.m_eWedgeRes ), m_bIsCoarse( rcWedge.m_bIsCoarse ), m_uiAng ( rcWedge.m_uiAng ), m_uiWidth ( rcWedge.m_uiWidth ), m_uiHeight ( rcWedge.m_uiHeight ), m_pbPattern( (Bool*)xMalloc( Bool, (m_uiWidth * m_uiHeight) ) ) #if SHARP_DMM1_I0110 ,m_pbScaledPattern( g_wedgePattern ) #endif { ::memcpy( m_pbPattern, rcWedge.m_pbPattern, sizeof(Bool) * (m_uiWidth * m_uiHeight)); } TComWedgelet::~TComWedgelet(void) { destroy(); } Void TComWedgelet::create( UInt uiWidth, UInt uiHeight ) { assert( uiWidth > 0 && uiHeight > 0 ); m_uiWidth = uiWidth; m_uiHeight = uiHeight; m_pbPattern = (Bool*)xMalloc( Bool, (m_uiWidth * m_uiHeight) ); #if SHARP_DMM1_I0110 m_pbScaledPattern = g_wedgePattern; #endif } Void TComWedgelet::destroy() { if( m_pbPattern ) { xFree( m_pbPattern ); m_pbPattern = NULL; } } Void TComWedgelet::clear() { ::memset( m_pbPattern, 0, (m_uiWidth * m_uiHeight) * sizeof(Bool) ); } Void TComWedgelet::findClosestAngle() { UInt uiAng=0,uiOptAng=0; UInt uiMinD=MAX_UINT; UInt uiTmpD=0; Int angTable[9] = {0, 2, 5, 9, 13, 17, 21, 26, 32}; UChar uhXs = m_uhXs; UChar uhYs = m_uhYs; UChar uhXe = m_uhXe; UChar uhYe = m_uhYe; for(uiAng=2; uiAng<=34; uiAng++) { Int iSign = (uiAngHOR_IDX ) ? -1 : 1; Int iVer = uiAng>17 ? 32 : angTable[(uiAng>10) ? (uiAng-10) : (10-uiAng)]; Int iHor = uiAng<19 ? 32 : angTable[(uiAng>26) ? (uiAng-26) : (26-uiAng)]; uiTmpD = abs(iVer*iSign*(uhXs-uhXe) - iHor*(uhYe-uhYs)); if( uiTmpD < uiMinD ) { uiMinD = uiTmpD; uiOptAng = uiAng; } } m_uiAng = uiOptAng; } Void TComWedgelet::setWedgelet( UChar uhXs, UChar uhYs, UChar uhXe, UChar uhYe, UChar uhOri, WedgeResolution eWedgeRes, Bool bIsCoarse ) { m_uhXs = uhXs; m_uhYs = uhYs; m_uhXe = uhXe; m_uhYe = uhYe; m_uhOri = uhOri; m_eWedgeRes = eWedgeRes; m_bIsCoarse = bIsCoarse; xGenerateWedgePattern(); } Bool TComWedgelet::checkNotPlain() { for( UInt k = 1; k < (m_uiWidth * m_uiHeight); k++ ) { if( m_pbPattern[0] != m_pbPattern[k] ) { return true; } } return false; } Bool TComWedgelet::checkIdentical( Bool* pbRefPattern ) { for( UInt k = 0; k < (m_uiWidth * m_uiHeight); k++ ) { if( m_pbPattern[k] != pbRefPattern[k] ) { return false; } } return true; } Bool TComWedgelet::checkInvIdentical( Bool* pbRefPattern ) { for( UInt k = 0; k < (m_uiWidth * m_uiHeight); k++ ) { if( m_pbPattern[k] == pbRefPattern[k] ) { return false; } } return true; } Void TComWedgelet::xGenerateWedgePattern() { UInt uiTempBlockSize = 0; UChar uhXs = 0, uhYs = 0, uhXe = 0, uhYe = 0; switch( m_eWedgeRes ) { #if !SHARP_DMM1_I0110 case( DOUBLE_PEL ): { uiTempBlockSize = m_uiWidth; uhXs = (m_uhXs<<1); uhYs = (m_uhYs<<1); uhXe = (m_uhXe<<1); uhYe = (m_uhYe<<1); } break; #endif case( FULL_PEL ): { uiTempBlockSize = m_uiWidth; uhXs = m_uhXs; uhYs = m_uhYs; uhXe = m_uhXe; uhYe = m_uhYe; } break; case( HALF_PEL ): { uiTempBlockSize = (m_uiWidth<<1); uhXs = m_uhXs; uhYs = m_uhYs; uhXe = m_uhXe; uhYe = m_uhYe; } break; } #if !SHARP_DMM1_I0110 if( m_eWedgeRes == DOUBLE_PEL) // adjust line-end for DOUBLE_PEL resolution { if( m_uhOri == 1 ) { uhXs = uiTempBlockSize-1; } if( m_uhOri == 2 ) { uhXe = uiTempBlockSize-1; uhYs = uiTempBlockSize-1; } if( m_uhOri == 3 ) { uhYe = uiTempBlockSize-1; } if( m_uhOri == 4 ) { uhYe = uiTempBlockSize-1; } if( m_uhOri == 5 ) { uhXs = uiTempBlockSize-1; } } #endif Bool* pbTempPattern = new Bool[ (uiTempBlockSize * uiTempBlockSize) ]; ::memset( pbTempPattern, 0, (uiTempBlockSize * uiTempBlockSize) * sizeof(Bool) ); Int iTempStride = uiTempBlockSize; xDrawEdgeLine( uhXs, uhYs, uhXe, uhYe, pbTempPattern, iTempStride ); switch( m_uhOri ) { case( 0 ): { for( UInt iX = 0; iX < uhXs; iX++ ) { UInt iY = 0; while( pbTempPattern[(iY * iTempStride) + iX] == false ) { pbTempPattern[(iY * iTempStride) + iX] = true; iY++; } } } break; case( 1 ): { for( UInt iY = 0; iY < uhYs; iY++ ) { UInt iX = uiTempBlockSize-1; while( pbTempPattern[(iY * iTempStride) + iX] == false ) { pbTempPattern[(iY * iTempStride) + iX] = true; iX--; } } } break; case( 2 ): { for( UInt iX = uiTempBlockSize-1; iX > uhXs; iX-- ) { UInt iY = uiTempBlockSize-1; while( pbTempPattern[(iY * iTempStride) + iX] == false ) { pbTempPattern[(iY * iTempStride) + iX] = true; iY--; } } } break; case( 3 ): { for( UInt iY = uiTempBlockSize-1; iY > uhYs; iY-- ) { UInt iX = 0; while( pbTempPattern[(iY * iTempStride) + iX] == false ) { pbTempPattern[(iY * iTempStride) + iX] = true; iX++; } } } break; case( 4 ): { if( (uhXs+uhXe) < uiTempBlockSize ) { for( UInt iY = 0; iY < uiTempBlockSize; iY++ ) { UInt iX = 0; while( pbTempPattern[(iY * iTempStride) + iX] == false ) { pbTempPattern[(iY * iTempStride) + iX] = true; iX++; } } } else { for( UInt iY = 0; iY < uiTempBlockSize; iY++ ) { UInt iX = uiTempBlockSize-1; while( pbTempPattern[(iY * iTempStride) + iX] == false ) { pbTempPattern[(iY * iTempStride) + iX] = true; iX--; } } } } break; case( 5 ): { if( (uhYs+uhYe) < uiTempBlockSize ) { for( UInt iX = 0; iX < uiTempBlockSize; iX++ ) { UInt iY = 0; while( pbTempPattern[(iY * iTempStride) + iX] == false ) { pbTempPattern[(iY * iTempStride) + iX] = true; iY++; } } } else { for( UInt iX = 0; iX < uiTempBlockSize; iX++ ) { UInt iY = uiTempBlockSize-1; while( pbTempPattern[(iY * iTempStride) + iX] == false ) { pbTempPattern[(iY * iTempStride) + iX] = true; iY--; } } } } } clear(); switch( m_eWedgeRes ) { #if !SHARP_DMM1_I0110 case( DOUBLE_PEL ): { for( UInt k = 0; k < (m_uiWidth * m_uiHeight); k++ ) { m_pbPattern[k] = pbTempPattern[k]; }; } break; #endif case( FULL_PEL ): { for( UInt k = 0; k < (m_uiWidth * m_uiHeight); k++ ) { m_pbPattern[k] = pbTempPattern[k]; }; } break; case( HALF_PEL ): // sub-sampling by factor 2 { Int iStride = getStride(); UInt uiOffX, uiOffY; switch( m_uhOri ) { case( 0 ): { uiOffX = 0; uiOffY = 0; } break; case( 1 ): { uiOffX = 1; uiOffY = 0; } break; case( 2 ): { uiOffX = 1; uiOffY = 1; } break; case( 3 ): { uiOffX = 0; uiOffY = 1; } break; case( 4 ): { if( (uhXs+uhXe) < uiTempBlockSize ) { uiOffX = 0; uiOffY = 0; } else { uiOffX = 1; uiOffY = 0; } } break; case( 5 ): { if( (uhYs+uhYe) < uiTempBlockSize ) { uiOffX = 0; uiOffY = 0; } else { uiOffX = 0; uiOffY = 1; } } break; default: { uiOffX = 0; uiOffY = 0; } break; } for(Int iY = 0; iY < m_uiHeight; iY++) { for(Int iX = 0; iX < m_uiWidth; iX++) { m_pbPattern[(iY * iStride) + iX] = pbTempPattern[(((iY<<1)+uiOffY) * iTempStride) + ((iX<<1)+uiOffX)]; } } } break; } if( pbTempPattern ) { delete [] pbTempPattern; pbTempPattern = NULL; } } Void TComWedgelet::xDrawEdgeLine( UChar uhXs, UChar uhYs, UChar uhXe, UChar uhYe, Bool* pbPattern, Int iPatternStride ) { Int x0 = (Int)uhXs; Int y0 = (Int)uhYs; Int x1 = (Int)uhXe; Int y1 = (Int)uhYe; // direction independent Bresenham line bool steep = (abs(y1 - y0) > abs(x1 - x0)); if( steep ) { std::swap( x0, y0 ); std::swap( x1, y1 ); } bool backward = ( x0 > x1 ); if( backward ) { std::swap( x0, x1 ); std::swap( y0, y1 ); } Int deltax = x1 - x0; Int deltay = abs(y1 - y0); Int error = 0; Int deltaerr = (deltay<<1); Int ystep; Int y = y0; if( y0 < y1 ) ystep = 1; else ystep = -1; for( Int x = x0; x <= x1; x++ ) { if( steep ) { pbPattern[(x * iPatternStride) + y] = true; } else { pbPattern[(y * iPatternStride) + x] = true; } error += deltaerr; if( error >= deltax ) { y += ystep; error = error - (deltax<<1); } } } #if SHARP_DMM1_I0110 Bool* TComWedgelet::getScaledPattern(UInt uiDstSize) { Bool *pbSrcPat = this->getPattern(); UInt uiSrcSize = this->getStride(); Int scale = (g_aucConvertToBit[uiDstSize] - g_aucConvertToBit[uiSrcSize]); assert(scale>=0); for (Int y=0; y>scale; Int srcY = y>>scale; m_pbScaledPattern[y*uiDstSize + x] = pbSrcPat[ srcY*uiSrcSize + srcX ]; } } return m_pbScaledPattern; } #endif TComWedgeNode::TComWedgeNode() { m_uiPatternIdx = DMM_NO_WEDGEINDEX; for( UInt uiPos = 0; uiPos < DMM_NUM_WEDGE_REFINES; uiPos++ ) { m_uiRefineIdx[uiPos] = DMM_NO_WEDGEINDEX; } } UInt TComWedgeNode::getPatternIdx() { return m_uiPatternIdx; } UInt TComWedgeNode::getRefineIdx( UInt uiPos ) { assert( uiPos < DMM_NUM_WEDGE_REFINES ); return m_uiRefineIdx[uiPos]; } Void TComWedgeNode::setPatternIdx( UInt uiIdx ) { m_uiPatternIdx = uiIdx; } Void TComWedgeNode::setRefineIdx( UInt uiIdx, UInt uiPos ) { assert( uiPos < DMM_NUM_WEDGE_REFINES ); m_uiRefineIdx[uiPos] = uiIdx; } #endif //H_3D_DIM_DMM