Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.
6766 Discussions

IPP Crashes, please look at comments marked with !!! or ???

noemata
Beginner
586 Views
// Authored by: Mario Pintaric

// ippTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include
#include
#include

#pragma comment(lib, "gdiplus")

#include "ipp.h"

#pragma comment(lib, "ippcore.lib")
#pragma comment(lib, "ippi.lib")

using namespace Gdiplus;

class GdiplusInit
{
public:
GdiplusInit()
{
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
}
~GdiplusInit()
{
GdiplusShutdown(gdiplusToken);
}
protected:
private:
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
};

GdiplusInit InitGDIPlus;

Bitmap *imgPage1Big;

void ResizeBitmap(Bitmap **bmpInput, int newWidth, int newHeight)
{
Bitmap *bmpTemp=(*bmpInput)->Clone(0, 0, newWidth, newHeight, PixelFormat32bppRGB);
delete *bmpInput;
*bmpInput = bmpTemp;
}

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array
// in bytes
Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;

Gdiplus::GetImageEncodersSize(&num, &size);
if(size == 0)
return -1;

pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1;

GetImageEncoders(num, size, pImageCodecInfo);

for(UINT j = 0; j < num; ++j)
{
if( wcscmp(pImageCodecInfo.MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo.Clsid;
free(pImageCodecInfo);
return j; // Success
}
}

free(pImageCodecInfo);
return -1;
}

IppStatus GaussBmp(Ipp8u *pSrc, IppiSize srcSize, int nChannels, IppiMaskSize op)
{
int nPad, step;
IppiSize padSize, fltSize;
Ipp8u *pad, *flt;
IppStatus status = ippStsNoMemErr;

// Set mask operation. Intel IPP docs do not provide an adequate explanation of border value condition handling.
// Overall, the docs are riddled with mistakes, poor grammar and incomplete explanations.
if ( op == ippMskSize3x3 )
{
nPad = 3;
}
else if ( op == ippMskSize5x5 )
{
nPad = 5; // Crashes when set to 5. Why???
}
else
return ippStsNotSupportedModeErr;

// Calculate padded and filtered bitmap sizes.
padSize.width = fltSize.width = srcSize.width + (2 * nPad);
padSize.height = fltSize.height = srcSize.height + (2 * nPad);

// Allocate padded bitmap that will contain replicated border of source bitmap and corresponding filter target bitmap.
if (nChannels == 1)
{
pad = ippiMalloc_8u_C1(padSize.width, padSize.height, &step);
if ( !pad )
goto Fault;
flt = ippiMalloc_8u_C1(fltSize.width, fltSize.height, &step);
if ( !flt )
goto Fault;
}
else if (nChannels == 3)
{
pad = ippiMalloc_8u_C3(padSize.width, padSize.height, &step);
if ( !pad )
goto Fault;
flt = ippiMalloc_8u_C3(fltSize.width, fltSize.height, &step);
if ( !flt )
goto Fault;
}
else if (nChannels == 4)
{
pad = ippiMalloc_8u_C4(padSize.width, padSize.height, &step);
if ( !pad )
goto Fault;
flt = ippiMalloc_8u_C4(fltSize.width, fltSize.height, &step);
if ( !flt )
goto Fault;
}
else
return ippStsNotSupportedModeErr;

// Note: Intel IPP seems to incorrectly caclulate the step value!!! Why???
step = padSize.width * nChannels;

if (nChannels == 1)
{
status = ippiCopyReplicateBorder_8u_C1R(pSrc, srcSize.width * nChannels, srcSize, pad, step, padSize, nPad, nPad);
}
else if (nChannels == 3)
{
status = ippiCopyReplicateBorder_8u_C3R(pSrc, srcSize.width * nChannels, srcSize, pad, step, padSize, nPad, nPad);
}
else if (nChannels == 4)
{
status = ippiCopyReplicateBorder_8u_C4R(pSrc, srcSize.width * nChannels, srcSize, pad, step, padSize, nPad, nPad);
}

if ( status )
goto Fault;

// If we do not increase value of buffersize calculated by ippiResizeSqrPixelGetBufSize, we crash ...
// Depending on image size, Intel IPP crashes here!!! Why??? Crashes are also random, in other words, not every time for same operation!!!!!
if (nChannels == 1)
{
status = ippiFilterGauss_8u_C1R(pad, step, flt, step, fltSize, op);
}
else if (nChannels == 3)
{
status = ippiFilterGauss_8u_C3R(pad, step, flt, step, fltSize, op);
}
else if (nChannels == 4)
{
status = ippiFilterGauss_8u_C4R(pad, step, flt, step, fltSize, op);
}

if ( status )
goto Fault;

// Copy filtered bitmap back to source. We need to set the row and colomn of the filtered
// bitmap so that it starts at the offset that corresponds to our border padding value.
if (nChannels == 1)
{
status = ippiCopy_8u_C1R(&flt[(fltSize.width * nPad * nChannels) + (nPad * nChannels)], step, pSrc, srcSize.width * nChannels, srcSize);
}
else if (nChannels == 3)
{
status = ippiCopy_8u_C3R(&flt[(fltSize.width * nPad * nChannels) + (nPad * nChannels)], step, pSrc, srcSize.width * nChannels, srcSize);
}
else if (nChannels == 4)
{
status = ippiCopy_8u_C4R(&flt[(fltSize.width * nPad * nChannels) + (nPad * nChannels)], step, pSrc, srcSize.width * nChannels, srcSize);
}

Fault:
if ( pad )
ippiFree(pad);
if ( flt )
ippiFree(flt);

return status;
}

int _tmain(int argc, _TCHAR* argv[])
{
const IppLibraryVersion* ippVersion = ippiGetLibVersion();

printf("IPP: [ %s %s ]\n", ippVersion->Name, ippVersion->Version);

Bitmap inBmp(L"bg.bmp");

if ( inBmp.GetLastStatus() == Ok )
{
PixelFormat fmt = inBmp.GetPixelFormat();

if ( PixelFormat24bppRGB == fmt )
{
BitmapData InData, growData, shrinkData;

int growwidth = inBmp.GetWidth() * 4;
int growheight = inBmp.GetHeight() * 4;

int shrinkwidth = growwidth / 8;
int shrinkheight = growheight / 8;

Bitmap growBmp(growwidth, growheight, PixelFormat24bppRGB);
Bitmap shrinkBmp(shrinkwidth, shrinkheight, PixelFormat24bppRGB);

inBmp.LockBits(0, ImageLockModeRead, PixelFormat24bppRGB, &InData);
growBmp.LockBits(0, ImageLockModeWrite, PixelFormat24bppRGB, &growData);
shrinkBmp.LockBits(0, ImageLockModeWrite, PixelFormat24bppRGB, &shrinkData);

IppStatus status;
IppiSize inSize = { inBmp.GetWidth(), inBmp.GetHeight() };
IppiRect inRect = { 0, 0, inBmp.GetWidth(), inBmp.GetHeight() };
IppiSize shrinkSize = { shrinkwidth, shrinkheight };
IppiRect shrinkRect = { 0, 0, shrinkwidth, shrinkheight };
IppiSize growSize = { growwidth, growheight };
IppiRect growRect = { 0, 0, growwidth, growheight };

double xgrowFactor = growwidth / (double)inBmp.GetWidth();
double ygrowFactor = growheight / (double)inBmp.GetHeight();
double xshrinkFactor = shrinkwidth / (double)growwidth;
double yshrinkFactor = shrinkheight / (double)growheight;
double xShift = 0.0;
double yShift = 0.0;
int nChannel = 3;

int bufferSize = 0;
Ipp8u *pshrinkBuffer = NULL, *pgrowBuffer = NULL;

// IPPI_INTER_NN
// IPPI_INTER_LINEAR
// IPPI_INTER_CUBIC
// IPPI_INTER_CUBIC2P_BSPLINE
// IPPI_INTER_CUBIC2P_CATMULLROM
// IPPI_INTER_CUBIC2P_B05C03
// IPPI_INTER_SUPER
// IPPI_INTER_LANCZOS
int interpolation = IPPI_INTER_CUBIC;

double xgrowF, ygrowF;
status = ippiGetResizeFract(growSize, growRect, xgrowFactor, ygrowFactor, &xgrowF, &ygrowF, interpolation);

// Note: docs imply IPPI_INTER_SUPER is supported by ippiResizeSqrPixel, but it is not???
status = ippiResizeSqrPixelGetBufSize(shrinkSize, nChannel, interpolation, &bufferSize);

if ( status )
goto Fault;

// Note: increasing bufferSize resolves crash problem, why???
pshrinkBuffer = (Ipp8u *)ippMalloc(bufferSize * 2);

if ( !pshrinkBuffer )
goto Fault;

status = ippiResizeSqrPixelGetBufSize(growSize, nChannel, interpolation, &bufferSize);

if ( status )
goto Fault;

// Note: increasing bufferSize resolves crash problem, why???
pgrowBuffer = (Ipp8u *)ippMalloc(bufferSize * 2);

// Guess: just as with step size, bufferSize is probably not caclulated correctly.

if ( !pgrowBuffer )
goto Fault;

status = ippiResizeSqrPixel_8u_C3R((Ipp8u*)InData.Scan0, inSize, inBmp.GetWidth() * nChannel, inRect, (Ipp8u*)growData.Scan0, growwidth * nChannel, growRect, xgrowFactor, ygrowFactor, 0, 0, interpolation, pgrowBuffer);

if ( status )
goto Fault;

status = GaussBmp((Ipp8u*)growData.Scan0, growSize, nChannel, ippMskSize5x5);

if ( status )
goto Fault;

status = GaussBmp((Ipp8u*)growData.Scan0, growSize, nChannel, ippMskSize5x5);

if ( status )
goto Fault;

status = ippiResizeSqrPixel_8u_C3R((Ipp8u*)growData.Scan0, growSize, growBmp.GetWidth() * nChannel, growRect, (Ipp8u*)shrinkData.Scan0, shrinkwidth * nChannel, shrinkRect, xshrinkFactor, yshrinkFactor, 0, 0, interpolation, pshrinkBuffer);

Fault:
if ( status == ippStsInterpolationErr )
printf("Invalid interpolation mode!\n");

if ( pshrinkBuffer )
ippFree(pshrinkBuffer);

if ( pgrowBuffer )
ippFree(pgrowBuffer);

inBmp.UnlockBits(&InData);
growBmp.UnlockBits(&growData);
shrinkBmp.UnlockBits(&shrinkData);

if ( status == ippStsNoErr )
{
CLSID clsidBMP;

GetEncoderClsid(L"image/bmp", &clsidBMP);

growBmp.Save(L"grow.bmp", &clsidBMP);
shrinkBmp.Save(L"shrink.bmp", &clsidBMP);
}
}
}

return 0;
}


0 Kudos
5 Replies
Vladimir_Dudnik
Employee
586 Views
I think you have some bugs (well, mistakes) in provided code snipped. Did you try IPP gauss filter in ippiDemo application ? I do not think this will crash..

Regards,
Vladimir

0 Kudos
shrieks
Beginner
586 Views
I think you have some bugs (well, mistakes) in provided code snipped. Did you try IPP gauss filter in ippiDemo application ? I do not think this will crash..

Regards,
Vladimir

I am also getting similar crash when using IPP Gauss filter with 5x5 mask and its random. I have seen documentation of these 2 functions ("ippiCopyReplicateBorder_8u_C1R" and "ippiFilterGauss_8u_C1R"), for Gauss filter there is no provision of ROI start coordinates, it directly takes ROI-width and ROI-height.I guess this is the reason of the crash.

Can you please provide a proper use of this pair with example?
0 Kudos
Vladimir_Dudnik
Employee
586 Views
We do provide a bunch on examplefor IPP. Please check IPP Samples page for download. You might be interested to take a look at image processing samples within this samples package.

Regards,
Vladimir
0 Kudos
shrieks
Beginner
586 Views
We do provide a bunch on examplefor IPP. Please check IPP Samples page for download. You might be interested to take a look at image processing samples within this samples package.

Regards,
Vladimir
Thanks for the quick reply! I have seen those samples and debugged them. There are lines of code for the functions I mentioned in previous post. But I want the implementation of the function pair. I could use those functions successfully when used separately but I am getting crash when I provide output of one function (ippiCopyReplicateBorder_8u_C1R) to the input of another function (ippiFilterGauss_8u_C1R). The source code is as similar as in the first post of this thread.
0 Kudos
matthieu_darbois
New Contributor III
586 Views
Hi,

I could find many issues in the GaussBMP function in the first post :

1 - Regarding padding to handle borders when filtering :
For a 3x3 kernel, you use a padding of 3 pixel in each direction (that is top - bottom - left - right). You should use a padding size of 1 pixel in this case or, in a general case, (kernel_size - 1)/2 when kernel_size is odd and the anchor point is centered.

2 - When applying the filter, you should apply it to the ROI on which the anchor point should be, that is :
status = ippiFilterGauss_8u_C1R(pad + nPad + nPad * step, step, flt, step, srcSize, op);

3 - the flt image can be the exact same size as the source and you can even not use that temp image writing directly into the source image

4 - regarding the comment // Note: Intel IPP seems to incorrectly caclulate the step value!!! Why??? :
the step isn't necessarily width * nbChannels. It is the row size in bytes. for example, BMP images require that the step is aligned on 32bits. For more efficiency, IPP aligned rows on 32 bytes boundaries (if I'm not mistaken). There are just some unused bytes in the buffer. It gives more performance but sometimes require more memory (if you try ippiMalloc... with width multiple of 32, you'll find that step = width * nbChannels)

regards,
Matthieu
0 Kudos
Reply