HEVC 帧内预测xPredIntraAng

帧内预测
xPredIntraAng:传入34种帧内预测模式的模式索引,得到预测图像
pSrc:重建序列的指针
pTrueDst:预测样本的指针
pDst:临时存储预测值指针
 
(1)if (modeDC),所有像素赋值dcval = predIntraGetPredValDC(pSrc, srcStride, width, height)
(2)else:
(a)if(角度偏移为负):*填写refAbove后半部分的值,用pSrc[x-srcStride-1]
*填写refLeft后半部分的值,用pSrc[(y-1)*srcStride-1]
*偏移refMain、refSide
*根据计算出来的截距将side reference对应的样点值投影给refMainrefMain[k] = refSide[invAngleSum>>8]
(对于模式18~25,须将左侧参考像素按给定方向投影至上方参考像素的左侧,对于模式11~17,须将上方参考像素按给定方向投影至左侧参考像素的上方)
 
(b)else:refAbove[x] = pSrc[x-srcStride-1]
refLeft[y] = pSrc[(y-1)*srcStride-1]
(角度为正时,对于垂直方向的角度预测来说,只参考上方邻点的样点值;对于水平方向的角度预测来说,只参考左方邻点的样点值 )
(c)如果是horizontal mode,width/height互换
(d)if纯水平或竖直方向,pDst[y*dstStride+x] = refMain[x+1]
(e)else:有加权因子pDsty[x+0] = (Pel) ( ((32-deltaFract)*lastRefMainPel + deltaFract*thisRefMainPel +16) >> 5 )
没有加权因子pDsty[x] = refMain[x+deltaInt+1](deltaInt当前像素对应参考像素在Ref中的位置)
(f)水平模式翻转pTrueDst[x*dstStrideTrue] = pDst[x]
 
Void TComPrediction::xPredIntraAng( Int bitDepth, const Pel* pSrc, Int srcStride, Pel* pTrueDst, Int dstStrideTrue, UInt uiWidth, UInt uiHeight, ChannelType channelType, UInt dirMode, const Bool bEnableEdgeFilters ) { Int width=Int(uiWidth); Int height=Int(uiHeight); // Map the mode index to main prediction direction and angle assert( dirMode != PLANAR_IDX ); //no planar const Bool modeDC = dirMode==DC_IDX; // Do the DC prediction if (modeDC) { const Pel dcval = predIntraGetPredValDC(pSrc, srcStride, width, height);//计算dcval值 for (Int y=height;y>0;y--, pTrueDst+=dstStrideTrue) { for (Int x=0; x<width;) // width is always a multiple of 4. { pTrueDst[x++] = dcval;//DC模式全用dcval这个值 } } } else // Do angular predictions { const Bool bIsModeVer = (dirMode >= 18);//判断是否为垂直模式 const Int intraPredAngleMode = (bIsModeVer) ? (Int)dirMode - VER_IDX : -((Int)dirMode - HOR_IDX);//与水平(垂直)模式的偏移量 const Int absAngMode = abs(intraPredAngleMode); const Int signAng = intraPredAngleMode < 0 ? -1 : 1; const Bool edgeFilter = bEnableEdgeFilters && isLuma(channelType) && (width <= MAXIMUM_INTRA_FILTERED_WIDTH) && (height <= MAXIMUM_INTRA_FILTERED_HEIGHT); // Set bitshifts and scale the angle parameter to block size static const Int angTable[9] = {0, 2, 5, 9, 13, 17, 21, 26, 32}; static const Int invAngTable[9] = {0, 4096, 1638, 910, 630, 482, 390, 315, 256}; // (256 * 32) / Angle Int invAngle = invAngTable[absAngMode]; Int absAng = angTable[absAngMode]; Int intraPredAngle = signAng * absAng; Pel* refMain; Pel* refSide; Pel refAbove[2*MAX_CU_SIZE+1]; Pel refLeft[2*MAX_CU_SIZE+1]; // Initialize the Main and Left reference array. if (intraPredAngle < 0) { const Int refMainOffsetPreScale = (bIsModeVer ? height : width ) - 1; const Int refMainOffset = height - 1; for (Int x=0;x<width+1;x++) { refAbove[x+refMainOffset] = pSrc[x-srcStride-1];//填写refAbove后半部分的值 } for (Int y=0;y<height+1;y++) { refLeft[y+refMainOffset] = pSrc[(y-1)*srcStride-1]; } refMain = (bIsModeVer ? refAbove : refLeft) + refMainOffset;//添加偏移,将refAbove前半部分索引变为负值 refSide = (bIsModeVer ? refLeft : refAbove) + refMainOffset; // Extend the Main reference to the left. Int invAngleSum = 128; // rounding for (shift by 8) for (Int k=-1; k>(refMainOffsetPreScale+1)*intraPredAngle>>5; k--) { invAngleSum += invAngle;// 等价于k * invAngle,即求出在side reference上的截距 refMain[k] = refSide[invAngleSum>>8];//根据计算出来的截距将side reference对应的样点值投影给main reference } } else { for (Int x=0;x<2*width+1;x++) { refAbove[x] = pSrc[x-srcStride-1]; } for (Int y=0;y<2*height+1;y++) { refLeft[y] = pSrc[(y-1)*srcStride-1]; } //角度为正时,对于垂直方向的角度预测来说,只参考上方邻点的样点值;对于水平方向的角度预测来说,只参考左方邻点的样点值 refMain = bIsModeVer ? refAbove : refLeft ; refSide = bIsModeVer ? refLeft : refAbove; } // swap width/height if we are doing a horizontal mode: Pel tempArray[MAX_CU_SIZE*MAX_CU_SIZE]; const Int dstStride = bIsModeVer ? dstStrideTrue : MAX_CU_SIZE; Pel *pDst = bIsModeVer ? pTrueDst : tempArray;//ModeVer直接将预测样本存入pTrueDst,ModeHor先将预测样本存入tempArray,最后转置 if (!bIsModeVer) { std::swap(width, height);//为了代码简便,下面将ModeHor和ModeVer的操作代码合并,所以交换width/height } if (intraPredAngle == 0) // pure vertical or pure horizontal { for (Int y=0;y<height;y++) { for (Int x=0;x<width;x++) { pDst[y*dstStride+x] = refMain[x+1]; } } if (edgeFilter) { for (Int y=0;y<height;y++) { pDst[y*dstStride] = Clip3 (0, ((1 << bitDepth) - 1), pDst[y*dstStride] + (( refSide[y+1] - refSide[0] ) >> 1) ); } } } else { Pel *pDsty=pDst; for (Int y=0, deltaPos=intraPredAngle; y<height; y++, deltaPos+=intraPredAngle, pDsty+=dstStride) { const Int deltaInt = deltaPos >> 5;//计算当前像素对应参考像素在Ref中的位置 const Int deltaFract = deltaPos & (32 - 1);//计算加权因子 if (deltaFract) { // Do linear filtering const Pel *pRM=refMain+deltaInt+1; Int lastRefMainPel=*pRM++; for (Int x=0;x<width;pRM++,x++) { Int thisRefMainPel=*pRM; pDsty[x+0] = (Pel) ( ((32-deltaFract)*lastRefMainPel + deltaFract*thisRefMainPel +16) >> 5 );//计算当前像素的预测值 lastRefMainPel=thisRefMainPel; } } else { // Just copy the integer samples for (Int x=0;x<width; x++) { pDsty[x] = refMain[x+deltaInt+1]; } } } } // Flip the block if this is the horizontal mode ,ModeHor就将pDst转置 if (!bIsModeVer) { for (Int y=0; y<height; y++) { for (Int x=0; x<width; x++) { pTrueDst[x*dstStrideTrue] = pDst[x]; } pTrueDst++; pDst+=dstStride; } } } }
 
 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值