#include "stdafx.h" #include "ImageTransform.h" #include "ImageTransformIPP.h" float g_fCos[720]; float g_fSin[720]; BOOL g_bSinCosInit = FALSE; void InitSinCos() { if (g_bSinCosInit) return; for (int i=0;i<720;i++) { g_fCos[i] = cos(M_PI*i/360); g_fSin[i] = sin(M_PI*i/360); } } void IPPClearImage(void* pData, int nSize, DWORD nColor) { if (!pData) return; int* p = (int*)pData; int c = RGBA(GetBValue(nColor), GetGValue(nColor), GetRValue(nColor), 255); for (int index = 0; index < nSize; index += 4, ++p) *p = c; } BOOL IPPEffectBlur(LPBYTE pPixels, int nWidth, int nHeight, double Frame, double Level) { IppiSize roiSize; roiSize.width = nWidth; roiSize.height = nHeight; IppiSize kernelSize; kernelSize.width = 3; kernelSize.height = 3; Ipp32f* pKernel = new Ipp32f[kernelSize.width*kernelSize.height]; Ipp8u *pDst = new Ipp8u[4*(nWidth + 2)*(nHeight + 2)]; if (pKernel && pDst) { double dMatrixKoef = 1.0/((21 - 20.0*Frame*Level/100.0) + 8.0)*Frame; pKernel[0] = dMatrixKoef; pKernel[1] = dMatrixKoef; pKernel[2] = dMatrixKoef; pKernel[3] = dMatrixKoef; pKernel[4] = dMatrixKoef*(21 - 20.0*Frame*Level/100.0) + (1.0 - Frame); pKernel[5] = dMatrixKoef; pKernel[6] = dMatrixKoef; pKernel[7] = dMatrixKoef; pKernel[8] = dMatrixKoef; IppiPoint anchor; anchor.x = 1; anchor.y = 1; IppiSize roiDstSize; roiDstSize.width = nWidth + 2; roiDstSize.height = nHeight + 2; ippiCopyReplicateBorder_8u_AC4R((Ipp8u*)pPixels, 4*nWidth, roiSize, pDst, 4*nWidth + 8, roiDstSize, 1, 1); ippiFilter32f_8u_AC4R((Ipp8u*)(pDst + 4 + 4*roiDstSize.width), 4*roiDstSize.width, (Ipp8u*)pPixels, 4*nWidth, roiSize, pKernel, kernelSize, anchor); } if (pKernel) delete[] pKernel; if (pDst) delete[] pDst; return TRUE; } BOOL IPPEffectSharpen(LPBYTE pPixels, int nWidth, int nHeight, double Frame, double Level) { IppiSize roiSize; roiSize.width = nWidth; roiSize.height = nHeight; IppiSize kernelSize; kernelSize.width = 3; kernelSize.height = 3; Ipp32f* pKernel = new Ipp32f[kernelSize.width*kernelSize.height]; Ipp8u* pDst = new Ipp8u[4*(nWidth + 2)*(nHeight + 2)]; if (pKernel && pDst) { double dMatrixKoef = 1.0/(1.0 + 23.0*(1.0 - Frame*Level/100.0))*Frame; pKernel[0] = -dMatrixKoef; pKernel[1] = -dMatrixKoef; pKernel[2] = -dMatrixKoef; pKernel[3] = -dMatrixKoef; pKernel[4] = dMatrixKoef*(9.0 + 23.0*(1.0 - Frame*Level/100.0)) + (1.0 - Frame); pKernel[5] = -dMatrixKoef; pKernel[6] = -dMatrixKoef; pKernel[7] = -dMatrixKoef; pKernel[8] = -dMatrixKoef; IppiPoint anchor; anchor.x = 1; anchor.y = 1; IppiSize roiDstSize; roiDstSize.width = nWidth + 2; roiDstSize.height = nHeight + 2; ippiCopyReplicateBorder_8u_AC4R((Ipp8u*)pPixels, 4*nWidth, roiSize, pDst, 4*nWidth + 8, roiDstSize, 1, 1); ippiFilter32f_8u_AC4R((Ipp8u*)(pDst + 4 + 4*roiDstSize.width), 4*roiDstSize.width, (Ipp8u*)pPixels, 4*nWidth, roiSize, pKernel, kernelSize, anchor); } if (pKernel) delete[] pKernel; if (pDst) delete[] pDst; return TRUE; } BOOL IPPEffectMosaic(LPBYTE pPixels, int nWidth, int nHeight, double Frame, long Size, BOOL bSimple) { IppiSize roiSize; roiSize.width = nWidth; roiSize.height = nHeight; int nTilesX = nWidth/Size; int nTilesY = nHeight/Size; IppiSize roiCellSize; roiCellSize.width = Size; roiCellSize.height = Size; IppiSize roiRightBorderCellSize = roiCellSize; roiRightBorderCellSize.width = nWidth - nTilesX*Size; IppiSize roiBottomBorderCellSize = roiCellSize; roiBottomBorderCellSize.height = nHeight - nTilesY*Size; LPBYTE pPixelsP1 = pPixels; LPBYTE pPixelsP2 = pPixels; int nStep = 4*nWidth; int nStepH = 4*Size; int nStepV = nStep*Size; if (bSimple) { //значение левого верхнего угла Ipp8u min[3]; if (0 != roiBottomBorderCellSize.height) { for (int i = 0; i < nTilesX; i++) { pPixelsP2 = pPixelsP1; for (int j = 0; j < nTilesY; j++) { ippiMin_8u_AC4R(pPixelsP2, nStep, roiCellSize, min); ippiSet_8u_AC4R(min, pPixelsP2, nStep, roiCellSize); pPixelsP2 += nStepV; } ippiMin_8u_AC4R(pPixelsP2, nStep, roiBottomBorderCellSize, min); ippiSet_8u_AC4R(min, pPixelsP2, nStep, roiBottomBorderCellSize); pPixelsP1 += nStepH; } } else { for (int i = 0; i < nTilesX; i++) { pPixelsP2 = pPixelsP1; for (int j = 0; j < nTilesY; j++) { ippiMin_8u_AC4R(pPixelsP2, nStep, roiCellSize, min); ippiSet_8u_AC4R(min, pPixelsP2, nStep, roiCellSize); pPixelsP2 += nStepV; } pPixelsP1 += nStepH; } } if (0 != roiRightBorderCellSize.width) { pPixelsP2 = pPixelsP1; for (int j = 0; j < nTilesY; j++) { ippiMin_8u_AC4R(pPixelsP2, nStep, roiRightBorderCellSize, min); ippiSet_8u_AC4R(min, pPixelsP2, nStep, roiRightBorderCellSize); pPixelsP2 += nStepV; } IppiSize oRightBottomCellSize = {roiRightBorderCellSize.width, roiBottomBorderCellSize.height}; ippiMin_8u_AC4R(pPixelsP2, nStep, oRightBottomCellSize, min); ippiSet_8u_AC4R(min, pPixelsP2, nStep, oRightBottomCellSize); } } else {//среднее значение по ячейке Ipp64f sum[3]; Ipp8u value[3]; int nPixelInCell = roiCellSize.height * roiCellSize.width; if( 0 != nPixelInCell ) { if (0 != roiBottomBorderCellSize.height) { int nPixelInBottomCell = roiBottomBorderCellSize.height * roiBottomBorderCellSize.width; for (int i = 0; i < nTilesX; i++) { pPixelsP2 = pPixelsP1; for (int j = 0; j < nTilesY; j++) { ippiSum_8u_AC4R(pPixelsP2, nStep, roiCellSize, sum); value[0] = (Ipp8u)(sum[0]/nPixelInCell); value[1] = (Ipp8u)(sum[1]/nPixelInCell); value[2] = (Ipp8u)(sum[2]/nPixelInCell); ippiSet_8u_AC4R(value, pPixelsP2, nStep, roiCellSize); pPixelsP2 += nStepV; } if( 0 != nPixelInBottomCell ) { ippiSum_8u_AC4R(pPixelsP2, nStep, roiBottomBorderCellSize, sum); value[0] = sum[0]/nPixelInBottomCell; value[1] = sum[1]/nPixelInBottomCell; value[2] = sum[2]/nPixelInBottomCell; ippiSet_8u_AC4R(value, pPixelsP2, nStep, roiBottomBorderCellSize); } pPixelsP1 += nStepH; } } else { for (int i = 0; i < nTilesX; i++) { pPixelsP2 = pPixelsP1; for (int j = 0; j < nTilesY; j++) { ippiSum_8u_AC4R(pPixelsP2, nStep, roiCellSize, sum); value[0] = sum[0]/nPixelInCell; value[1] = sum[1]/nPixelInCell; value[2] = sum[2]/nPixelInCell; ippiSet_8u_AC4R(value, pPixelsP2, nStep, roiCellSize); pPixelsP2 += nStepV; } pPixelsP1 += nStepH; } } } if (0 != roiRightBorderCellSize.width) { int nPixelInRightCell = roiRightBorderCellSize.height * roiRightBorderCellSize.width; pPixelsP2 = pPixelsP1; if( 0 != nPixelInRightCell ) { for (int j = 0; j < nTilesY; j++) { ippiSum_8u_AC4R(pPixelsP2, nStep, roiRightBorderCellSize, sum); value[0] = sum[0]/nPixelInRightCell; value[1] = sum[1]/nPixelInRightCell; value[2] = sum[2]/nPixelInRightCell; ippiSet_8u_AC4R(value, pPixelsP2, nStep, roiRightBorderCellSize); pPixelsP2 += nStepV; } } IppiSize oRightBottomCellSize = {roiRightBorderCellSize.width, roiBottomBorderCellSize.height}; int nPixelInRightBottomCell = roiRightBorderCellSize.width * roiBottomBorderCellSize.height; if( 0 != nPixelInRightBottomCell ) { ippiSum_8u_AC4R(pPixelsP2, nStep, oRightBottomCellSize, sum); value[0] = sum[0]/nPixelInRightBottomCell; value[1] = sum[1]/nPixelInRightBottomCell; value[2] = sum[2]/nPixelInRightBottomCell; ippiSet_8u_AC4R(value, pPixelsP2, nStep, oRightBottomCellSize); } } } return TRUE; } BOOL IPPEffectGaussianBlur(LPBYTE pPixels, int nWidth, int nHeight, double Frame, long Size) { if(Size < 1) return TRUE; IppiSize roiSize; roiSize.width = nWidth; roiSize.height = nHeight; int nCount = 2*Size+1; Ipp32s* pKernel = new Ipp32s[nCount]; IppiSize roiBufferExtVSize; roiBufferExtVSize.width = nWidth; roiBufferExtVSize.height = nHeight + 2*Size; Ipp8u* pBufferExtV = new Ipp8u[4*roiBufferExtVSize.width*roiBufferExtVSize.height]; IppiSize roiBufferExtHSize; roiBufferExtHSize.width = nWidth + 2*Size; roiBufferExtHSize.height = nHeight; Ipp8u* pBufferExtH = new Ipp8u[4*roiBufferExtHSize.width*roiBufferExtHSize.height]; if (pKernel && pBufferExtV && pBufferExtH) { for (int i = 0; i < nCount; ++i) pKernel[i] = 1; ippiCopyReplicateBorder_8u_AC4R(pPixels, 4*nWidth, roiSize, pBufferExtV, 4*roiBufferExtVSize.width, roiBufferExtVSize, Size, 0); ippiFilterColumn_8u_AC4R((Ipp8u*)(pBufferExtV + Size*(4*roiBufferExtVSize.width)), 4*roiBufferExtVSize.width, pPixels, 4*nWidth, roiSize, pKernel, nCount, Size, nCount); ippiCopyReplicateBorder_8u_AC4R(pPixels, 4*nWidth, roiSize, pBufferExtH, 4*roiBufferExtHSize.width, roiBufferExtHSize, 0, Size); ippiFilterRow_8u_AC4R((Ipp8u*)(pBufferExtH + 4*Size), 4*roiBufferExtHSize.width, pPixels, 4*nWidth, roiSize, pKernel, nCount, Size, nCount); ippiCopyReplicateBorder_8u_AC4R(pPixels, 4*nWidth, roiSize, pBufferExtV, 4*roiBufferExtVSize.width, roiBufferExtVSize, Size, 0); ippiFilterColumn_8u_AC4R((Ipp8u*)(pBufferExtV + Size*(4*roiBufferExtVSize.width)), 4*roiBufferExtVSize.width, pPixels, 4*nWidth, roiSize, pKernel, nCount, Size, nCount); ippiCopyReplicateBorder_8u_AC4R(pPixels, 4*nWidth, roiSize, pBufferExtH, 4*roiBufferExtHSize.width, roiBufferExtHSize, 0, Size); ippiFilterRow_8u_AC4R((Ipp8u*)(pBufferExtH + 4*Size), 4*roiBufferExtHSize.width, pPixels, 4*nWidth, roiSize, pKernel, nCount, Size, nCount); } if (pBufferExtH) delete[] pBufferExtH; if (pBufferExtV) delete pBufferExtV; if (pKernel) delete pKernel; /* IppiSize kernelSize; kernelSize.width = 2*Size+1; kernelSize.height = kernelSize.width; int nCount = kernelSize.width*kernelSize.height; Ipp32s* pKernel = new Ipp32s[nCount]; pKernel[0] = 1; for (int i=1; ic_dFrameMax) { ippiCopy_8u_C1C4R(pChanel, nWidth, pPixels, 4*nWidth, roiSize); ippiCopy_8u_C1C4R(pChanel, nWidth, (Ipp8u*)(pPixels + 1), 4*nWidth, roiSize); ippiCopy_8u_C1C4R(pChanel, nWidth, (Ipp8u*)(pPixels + 2), 4*nWidth, roiSize); } else { Ipp8u* pBuffer = new Ipp8u[4*nWidth*nHeight]; if (!pBuffer) { delete []pChanel; return FALSE; } ippiCopy_8u_C1C4R(pChanel, nWidth, pBuffer, 4*nWidth, roiSize); ippiCopy_8u_C1C4R(pChanel, nWidth, (Ipp8u*)(pBuffer + 1), 4*nWidth, roiSize); ippiCopy_8u_C1C4R(pChanel, nWidth, (Ipp8u*)(pBuffer + 2), 4*nWidth, roiSize); Ipp8u alpha = Frame * 255; ippiAlphaCompC_8u_AC4R( pBuffer, 4*nWidth, alpha, pPixels, 4*nWidth, 255, pPixels, 4*nWidth, roiSize, ippAlphaOver); delete []pBuffer; } delete []pChanel; return TRUE; } BOOL IPPFilterSobel(LPBYTE pPixels, int nWidth, int nHeight, double Frame, long Type) { if (Framec_dFrameMax) { ippiCopy_8u_C1C4R(pChanel, nWidth, pPixels, 4*nWidth, roiSize); ippiCopy_8u_C1C4R(pChanel, nWidth, (Ipp8u*)(pPixels + 1), 4*nWidth, roiSize); ippiCopy_8u_C1C4R(pChanel, nWidth, (Ipp8u*)(pPixels + 2), 4*nWidth, roiSize); } else { Ipp8u* pBuffer = new Ipp8u[4*nWidth*nHeight]; if (!pBuffer) { delete []pChanel; return FALSE; } ippiCopy_8u_C1C4R(pChanel, nWidth, pBuffer, 4*nWidth, roiSize); ippiCopy_8u_C1C4R(pChanel, nWidth, (Ipp8u*)(pBuffer + 1), 4*nWidth, roiSize); ippiCopy_8u_C1C4R(pChanel, nWidth, (Ipp8u*)(pBuffer + 2), 4*nWidth, roiSize); Ipp8u alpha = Frame * 255; ippiAlphaCompC_8u_AC4R( pBuffer, 4*nWidth, alpha, pPixels, 4*nWidth, 255, pPixels, 4*nWidth, roiSize, ippAlphaOver); delete []pBuffer; } delete []pChanel; return TRUE; } BOOL IPPFilterSobelExt(LPBYTE pPixels, int nWidth, int nHeight, double Frame, long Type) { if (Frame= nWidth || BoundRect.y >= nHeight ) return TRUE; if( BoundRect.x < 0 ) { if( BoundRect.x + BoundRect.width <= 0 ) return TRUE; BoundRect.width += BoundRect.x; BoundRect.x = 0; } if( BoundRect.y < 0 ) { if( BoundRect.y + BoundRect.height <= 0 ) return TRUE; BoundRect.height += BoundRect.y; BoundRect.y = 0; } if( BoundRect.x + BoundRect.width > nWidth ) BoundRect.width = nWidth - BoundRect.x; if( BoundRect.y + BoundRect.height > nHeight ) BoundRect.height = nHeight - BoundRect.y; // определяем дополнительные переменные int nMaxRadius = max( nRadius.x, nRadius.y ); // создаём необходимые буфера Ipp8u* pBuffer = new Ipp8u[BoundRect.width*BoundRect.height*4]; Ipp32f* pMapX = new Ipp32f[BoundRect.width*BoundRect.height]; Ipp32f* pMapY = new Ipp32f[BoundRect.width*BoundRect.height]; Ipp32f* pOffset = new Ipp32f[nMaxRadius + 1]; //dRadiusX *= dRadiusX; //dRadiusY *= dRadiusY; dRadiusX = 1/(dRadiusX * dRadiusX); dRadiusY = 1/(dRadiusY * dRadiusY); if( pBuffer && pMapX && pMapY && pOffset ) { Degree /= 10; for( int i = 0; i <= nMaxRadius; i++ ) { //pOffset[i] = float(pow( double(i + 1) / (nMaxRadius + 1), Degree )); // чёткий контур pOffset[i] = float(pow( sin( double(i + 1) / (nMaxRadius + 1) * IPP_PI2 ), Degree )); // сглаженный контур } int nMaxRow = BoundRect.y + BoundRect.height; int nMaxPos = BoundRect.x + BoundRect.width; Ipp32f* pCurMapX = pMapX; Ipp32f* pCurMapY = pMapY; for( int nRow = BoundRect.y; nRow < nMaxRow; ++nRow ) { int nY = nRow - CenterY; double dFactor = nY * nY * dRadiusY; for( int nPos = BoundRect.x; nPos < nMaxPos; ++nPos, ++pCurMapX, ++pCurMapY ) { int nX = nPos - CenterX; double dR = nX * nX * dRadiusX + dFactor; if( dR < 1 ) { // ближайшее значение (без интерполяции) //int index = int(dR * nMaxRadius + 0.5); //*pCurMapX = float(nX * pOffset[index] + CenterX); //*pCurMapY = float(nY * pOffset[index] + CenterY); // интерполяция dR *= nMaxRadius; int index = int(dR); dR = (dR - index)*(pOffset[index + 1] - pOffset[index]) + pOffset[index]; *pCurMapX = float(nX * dR + CenterX); *pCurMapY = float(nY * dR + CenterY); } else { *pCurMapX = nPos; *pCurMapY = nRow; } } } // закрашиваем фоновым цветом IppiSize DstSize = {BoundRect.width, BoundRect.height}; Ipp8u Colors[4] = { GetBValue(dwBackColor), GetGValue(dwBackColor), GetRValue(dwBackColor), 255 }; ippiSet_8u_C4R( Colors, pBuffer, BoundRect.width*4, DstSize ); // ремэпим IppiSize SrcSize = {nWidth, nHeight}; IppiRect SrcRect = {0, 0, nWidth, nHeight}; ippiRemap_8u_C4R( pPixels, SrcSize, nWidth*4, SrcRect, pMapX, sizeof(Ipp32f)*BoundRect.width, pMapY, sizeof(Ipp32f)*BoundRect.width, pBuffer, BoundRect.width*4, DstSize, IPPI_INTER_LINEAR); // копируем полученную картинку обратно Ipp8u* pDstPixels = pPixels + (BoundRect.y * nWidth + BoundRect.x) * 4; ippiCopy_8u_C4R( pBuffer, BoundRect.width*4, pDstPixels, nWidth*4, DstSize ); } if (pOffset) delete []pOffset; if (pMapX) delete []pMapX; if (pMapY) delete []pMapY; if (pBuffer) delete []pBuffer; return TRUE; } BOOL IPPTransformCylinder(LPBYTE pPixels, int nWidth, int nHeight, double Frame, long Center, long Radius, double Degree, long nType, DWORD dwBackColor) { Degree *= Frame; double dRadius = Radius * Frame; int nMaxRadius = int(abs(dRadius)) + 1; if( nMaxRadius <= 1 ) return TRUE; IppiRect BoundRect = {0, 0, nWidth, nHeight}; if( c_nTransformCylinderHoriz == nType ) { BoundRect.y = Center - nMaxRadius; BoundRect.height = nMaxRadius * 2; if( BoundRect.y >= nHeight ) return TRUE; if( BoundRect.y < 0 ) { if( BoundRect.y + BoundRect.height <= 0 ) return TRUE; BoundRect.height += BoundRect.y; BoundRect.y = 0; } if( BoundRect.y + BoundRect.height > nHeight ) { BoundRect.height = nHeight - BoundRect.y; } } else { BoundRect.x = Center - nMaxRadius; BoundRect.width = nMaxRadius * 2; if( BoundRect.x >= nWidth ) return TRUE; if( BoundRect.x < 0 ) { if( BoundRect.x + BoundRect.width <= 0 ) return TRUE; BoundRect.width += BoundRect.x; BoundRect.x = 0; } if( BoundRect.x + BoundRect.width > nWidth ) { BoundRect.width = nWidth - BoundRect.x; } } Ipp8u* pBuffer = new Ipp8u[BoundRect.width*BoundRect.height*4]; Ipp32f* pMapX = new Ipp32f[BoundRect.width*BoundRect.height]; Ipp32f* pMapY = new Ipp32f[BoundRect.width*BoundRect.height]; dRadius = 1.0/(nMaxRadius * nMaxRadius); Degree /= 10; if( pBuffer && pMapX && pMapY ) { Ipp32f* pCurMapX = pMapX; Ipp32f* pCurMapY = pMapY; if( c_nTransformCylinderHoriz == nType ) { for( int nRow = BoundRect.y; nRow < BoundRect.y + BoundRect.height; ++nRow ) { int nY = nRow - Center; double dR = nY * nY * dRadius; *pCurMapY = float(nY * pow( dR + 0.0001, Degree ) + Center); *pCurMapX = 0; for( int nPos = 1; nPos < BoundRect.width; ++nPos, ++pCurMapX, ++pCurMapY ) { *pCurMapY = pCurMapY[-1]; *pCurMapX = nPos; } } } else { for( int nPos = BoundRect.x; nPos < BoundRect.x + BoundRect.width; ++nPos, ++pCurMapX, ++pCurMapY ) { int nX = nPos - Center; double dR = nX * nX * dRadius; *pCurMapX = float(nX * pow( dR + 0.0001, Degree ) + Center); *pCurMapY = 0; } for( int nRow = 1; nRow < BoundRect.height; ++nRow ) { for( int nPos = 0; nPos < BoundRect.width; ++nPos, ++pCurMapX, ++pCurMapY ) { *pCurMapX = pCurMapX[-BoundRect.width]; *pCurMapY = nRow; } } } // закрашиваем фоновым цветом IppiSize DstSize = {BoundRect.width, BoundRect.height}; Ipp8u Colors[4] = { GetBValue(dwBackColor), GetGValue(dwBackColor), GetRValue(dwBackColor), 255 }; ippiSet_8u_C4R( Colors, pBuffer, BoundRect.width*4, DstSize ); // ремэпим IppiSize SrcSize = {nWidth, nHeight}; IppiRect SrcRect = {0, 0, nWidth, nHeight}; ippiRemap_8u_C4R( pPixels, SrcSize, 4*nWidth, SrcRect, pMapX, sizeof(Ipp32f)*BoundRect.width, pMapY, sizeof(Ipp32f)*BoundRect.width, pBuffer, 4*BoundRect.width, DstSize, IPPI_INTER_LINEAR); // копируем полученную картинку обратно Ipp8u* pDstPixels = pPixels + (BoundRect.y * nWidth + BoundRect.x) * 4; ippiCopy_8u_C4R( pBuffer, BoundRect.width*4, pDstPixels, nWidth*4, DstSize ); } if (pMapX) delete []pMapX; if (pMapY) delete []pMapY; if (pBuffer) delete []pBuffer; return TRUE; } void IPP_BGRA_GaussianBlurHorizontal( Ipp16u* pMapBGR, Ipp8u* pDstBGRA, int nWidth, int nHeight, int nDstStride, int nMapStride, int nBlurSize ) { Ipp32u nFactor = nBlurSize * 2 + 1; nFactor *= nFactor; for( ; nHeight > 0; --nHeight, pDstBGRA += nDstStride, pMapBGR += nMapStride ) { Ipp8u* pDst = pDstBGRA; Ipp16u* pMap = pMapBGR; // подсчёт начальной суммы Ipp32u nB = Ipp32u(pMap[0] * (nBlurSize + 1)); Ipp32u nG = Ipp32u(pMap[1] * (nBlurSize + 1)); Ipp32u nR = Ipp32u(pMap[2] * (nBlurSize + 1)); int nLength = nBlurSize; for( ; nLength > 0; --nLength ) { pMap += 3; nB += pMap[0]; nG += pMap[1]; nR += pMap[2]; } // расчёт новых пикселов в строке pMap = pMapBGR; nLength = nWidth; for( ;; ) { pDst[0] = BYTE(nB / nFactor); pDst[1] = BYTE(nG / nFactor); pDst[2] = BYTE(nR / nFactor); // проверка на выход из цикла if( nLength <= 1 ) { break; } pDst += 4; // вычитаем крайнее левое значение int index = 3 * ((nLength > nWidth - nBlurSize) ? nWidth - nLength : nBlurSize); nB -= pMap[0 - index]; nG -= pMap[1 - index]; nR -= pMap[2 - index]; // переходим на следующий пиксел --nLength; pMap += 3; // прибавляем следующее крайнее правое значение index = 3 * (nLength > nBlurSize ? nBlurSize : nLength - 1); nB += pMap[0 + index]; nG += pMap[1 + index]; nR += pMap[2 + index]; } } } void IPP_BGRA_GaussianBlurVertical(Ipp8u* pSrcBGRA, Ipp16u* pMapBGR, int nWidth, int nHeight, int nSrcStride, int nMapStride, int nBlurSize ) { for( ; nWidth > 0; --nWidth, pSrcBGRA += 4, pMapBGR += 3 ) { Ipp8u* pSrc = pSrcBGRA; Ipp16u* pMap = pMapBGR; // подсчёт начальной суммы Ipp16u nB = Ipp16u(pSrc[0] * (nBlurSize + 1)); Ipp16u nG = Ipp16u(pSrc[1] * (nBlurSize + 1)); Ipp16u nR = Ipp16u(pSrc[2] * (nBlurSize + 1)); int nLength = nBlurSize; while( nLength-- > 0 ) { pSrc += nSrcStride; nB += pSrc[0]; nG += pSrc[1]; nR += pSrc[2]; } // расчёт новых пикселов в строке pSrc = pSrcBGRA; nLength = nHeight; for( ;; ) { pMap[0] = nB; pMap[1] = nG; pMap[2] = nR; // проверка на выход из цикла if( nLength <= 1 ) { break; } pMap += nMapStride; // вычитаем крайнее верхнее значение int index = nSrcStride * ((nLength > nHeight - nBlurSize) ? nHeight - nLength : nBlurSize); nB -= pSrc[0 - index]; nG -= pSrc[1 - index]; nR -= pSrc[2 - index]; // переходим на следующий пиксел --nLength; pSrc += nSrcStride; // прибавляем следующее крайнее нижнее значение index = nSrcStride * (nLength > nBlurSize ? nBlurSize : nLength - 1); nB += pSrc[0 + index]; nG += pSrc[1 + index]; nR += pSrc[2 + index]; } } } BOOL IPPEffectGaussianBlur2( BYTE* pPixels, int nWidth, int nHeight, double dFrame, long Size ) { // определяем размер блюра if( Size < 1 ) return TRUE; // создаём вспомогательный массив для ускоренного расчёта блюра Ipp16u* pMap = new Ipp16u[nWidth*nHeight*3]; if( !pMap ) return TRUE; int nImgStride = nWidth * 4; int nMapStride = nWidth * 3; // первый цикл IPP_BGRA_GaussianBlurVertical( pPixels, pMap, nWidth, nHeight, nImgStride, nMapStride, Size ); IPP_BGRA_GaussianBlurHorizontal( pMap, pPixels, nWidth, nHeight, nImgStride, nMapStride, Size ); // второй цикл IPP_BGRA_GaussianBlurVertical( pPixels, pMap, nWidth, nHeight, nImgStride, nMapStride, Size ); IPP_BGRA_GaussianBlurHorizontal( pMap, pPixels, nWidth, nHeight, nImgStride, nMapStride, Size ); delete [] pMap; return TRUE; }