In the code below, the resulting reconstruction is perfect, except for the first two rows and columns. This is the case regardless of the source image or image extension (e.g., ippiCopyMirrorBorder method), and is also present in the case of 3 channel images. For larger wavelet filter kernels, the imperfection is along a larger number of the first rows and columns. Is there an issue with usage below?
Thanks,
Ben
int main( int argc, char *argv[] ) { // db2 const int kernelFwdLowLen = 4; const int kernelFwdLowAnchor = 3; const float kernelFwdLow[kernelFwdLowLen] = { -0.12940952255092145f, 0.22414386804185735f, 0.83651630373746900f, 0.48296291314469025f }; const int kernelFwdHighLen = 4; const int kernelFwdHighAnchor = 3; const float kernelFwdHigh[kernelFwdHighLen] = { -0.48296291314469025f, 0.83651630373746900f, -0.22414386804185735f, -0.12940952255092145f }; const int kernelInvLowLen = 4; const int kernelInvLowAnchor = 0; const float kernelInvLow[kernelInvLowLen] = { 0.48296291314469025f, 0.83651630373746900f, 0.22414386804185735f, -0.12940952255092145f }; const int kernelInvHighLen = 4; const int kernelInvHighAnchor = 0; const float kernelInvHigh[kernelInvHighLen] = { -0.12940952255092145f, -0.22414386804185735f, 0.83651630373746900f, -0.48296291314469025f }; const int borderSize = 3; // Max size of all borders // Larger than needed for transform results, but is fine const int srcWidth = 8; const int srcHeight = 6; const float pSrc[srcWidth * srcHeight] = { 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 31, 32, 33, 34, 35, 36, 37, 38, 41, 42, 43, 44, 45, 46, 47, 48, 51, 52, 53, 54, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68 }; const int srcStep = sizeof( float ) * srcWidth; const IppiSize srcSize = { srcWidth, srcHeight }; const int srcBorderedWidth = srcWidth + borderSize * 2; const int srcBorderedHeight = srcHeight + borderSize * 2; float pSrcBordered[srcBorderedWidth * srcBorderedHeight]; const int srcBorderedStep = sizeof( float ) * srcBorderedWidth; const IppiSize srcBorderedSize = { srcBorderedWidth, srcBorderedHeight }; ippiCopyMirrorBorder_32f_C1R( pSrc, srcStep, srcSize, pSrcBordered, srcBorderedStep, srcBorderedSize, borderSize, borderSize ); int specSize = 0; int bufferSize = 0; ippiWTFwdGetSize_32f( 1, kernelFwdLowLen, kernelFwdLowAnchor, kernelFwdHighLen, kernelFwdHighAnchor, &specSize, &bufferSize ); IppiWTFwdSpec_32f_C1R* pSpecFwd = (IppiWTFwdSpec_32f_C1R*)ippMalloc( specSize ); unsigned char* pBufferFwd = ippsMalloc_8u( bufferSize ); ippiWTFwdInit_32f_C1R( pSpecFwd, kernelFwdLow, kernelFwdLowLen, kernelFwdLowAnchor, kernelFwdHigh, kernelFwdHighLen, kernelFwdHighAnchor ); const int width = srcWidth / 2; const int height = srcHeight / 2; float pApprox[width * height]; const int approxStep = sizeof( float ) * width; float pHdetail[width * height]; const int HdetailStep = sizeof( float ) * width; float pVdetail[width * height]; const int VdetailStep = sizeof( float ) * width; float pDdetail[width * height]; const int DdetailStep = sizeof( float ) * width; const IppiSize size = { width, height }; ippiWTFwd_32f_C1R( pSrcBordered + borderSize * srcBorderedWidth + borderSize, srcBorderedStep, pApprox, approxStep, pHdetail, HdetailStep, pVdetail, VdetailStep, pDdetail, DdetailStep, size, pSpecFwd, pBufferFwd ); const int borderedWidth = width + borderSize * 2; const int borderedHeight = height + borderSize * 2; const IppiSize borderedSize = { borderedWidth, borderedHeight }; float pApproxBordered[borderedWidth * borderedHeight]; const int approxBorderedStep = sizeof( float ) * borderedWidth; ippiCopyMirrorBorder_32f_C1R( pApprox, approxStep, size, pApproxBordered, approxBorderedStep, borderedSize, borderSize, borderSize ); float pHdetailBordered[borderedWidth * borderedHeight]; const int HdetailBorderedStep = sizeof( float ) * borderedWidth; ippiCopyMirrorBorder_32f_C1R( pHdetail, HdetailStep, size, pHdetailBordered, HdetailBorderedStep, borderedSize, borderSize, borderSize ); float pVdetailBordered[borderedWidth * borderedHeight]; const int VdetailBorderedStep = sizeof( float ) * borderedWidth; ippiCopyMirrorBorder_32f_C1R( pVdetail, VdetailStep, size, pVdetailBordered, VdetailBorderedStep, borderedSize, borderSize, borderSize ); float pDdetailBordered[borderedWidth * borderedHeight]; const int DdetailBorderedStep = sizeof( float ) * borderedWidth; ippiCopyMirrorBorder_32f_C1R( pDdetail, DdetailStep, size, pDdetailBordered, DdetailBorderedStep, borderedSize, borderSize, borderSize ); specSize = 0; bufferSize = 0; ippiWTInvGetSize_32f( 1, kernelInvLowLen, kernelInvLowAnchor, kernelInvHighLen, kernelInvHighAnchor, &specSize, &bufferSize ); IppiWTInvSpec_32f_C1R* pSpecInv = (IppiWTInvSpec_32f_C1R*)ippMalloc( specSize ); unsigned char* pBufferInv = ippsMalloc_8u( bufferSize ); ippiWTInvInit_32f_C1R( pSpecInv, kernelInvLow, kernelInvLowLen, kernelInvLowAnchor, kernelInvHigh, kernelInvHighLen, kernelInvHighAnchor ); float pReconstructed[srcWidth * srcHeight]; const int reconstructedStep = sizeof( float ) * srcWidth; ippiWTInv_32f_C1R( pApproxBordered + borderSize * borderedWidth + borderSize, approxBorderedStep, pHdetailBordered + borderSize * borderedWidth + borderSize, HdetailBorderedStep, pVdetailBordered + borderSize * borderedWidth + borderSize, VdetailBorderedStep, pDdetailBordered + borderSize * borderedWidth + borderSize, DdetailBorderedStep, size, pReconstructed, reconstructedStep, pSpecInv, pBufferInv ); // Perfect reconstruction, except for first two rows and columns ippsFree( pBufferInv ); ippFree( pSpecInv ); ippsFree( pBufferFwd ); ippFree( pSpecFwd ); return 0; }