Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Beginner
64 Views

Fixed IPP crash problems. If only Intel provided something like this as an example. This covers many use cases (resize, filter, etc.). Would have saved me half a day of trial and error.

// 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;

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)
{
Ipp8u *pad;
int nPad, step;
IppiSize padSize;
Ipp8u *pBorderOffset;
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 = srcSize.width + (2 * nPad);
padSize.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);
}
else if (nChannels == 3)
{
pad = ippiMalloc_8u_C3(padSize.width, padSize.height, &step);
}
else if (nChannels == 4)
{
pad = ippiMalloc_8u_AC4(padSize.width, padSize.height, &step);
}
else
return ippStsNotSupportedModeErr;

if ( !pad )
goto Fault;

// Note: Intel IPP seems to incorrectly caclulate the step value!!! Why??? Especially bad for small bitmap sizes (< 10 bytes wide)
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_AC4R(pSrc, srcSize.width * nChannels, srcSize, pad, step, padSize, nPad, nPad);
}

if ( status )
goto Fault;

// The docs do not provide any clarity on the need to do this. None of the samples I've seen suggest this is required.
// Half a day blown because of poor documentation!
pBorderOffset = &pad[(padSize.width * nPad * nChannels) + (nPad * nChannels)];

if (nChannels == 1)
{
status = ippiFilterGauss_8u_C1R(pBorderOffset, step, pSrc, srcSize.width * nChannels, srcSize, op);
}
else if (nChannels == 3)
{
status = ippiFilterGauss_8u_C3R(pBorderOffset, step, pSrc, srcSize.width * nChannels, srcSize, op);
}
else if (nChannels == 4)
{
status = ippiFilterGauss_8u_AC4R(pBorderOffset, step, pSrc, srcSize.width * nChannels, srcSize, op);
}

if ( status )
goto Fault;

Fault:
if ( pad )
ippiFree(pad);

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_LANCZOS; // Is this the best IPP has to offer when downsampling?

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

if ( status )
goto Fault;

pshrinkBuffer = (Ipp8u *)ippMalloc(bufferSize);

if ( !pshrinkBuffer )
goto Fault;

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

if ( status )
goto Fault;

pgrowBuffer = (Ipp8u *)ippMalloc(bufferSize);

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;

// Blur upscaled bitmap so that we downscale more smoothly.
status = GaussBmp((Ipp8u*)growData.Scan0, growSize, nChannel, ippMskSize5x5);

if ( status )
goto Fault;

// Blur some more ...
status = GaussBmp((Ipp8u*)growData.Scan0, growSize, nChannel, ippMskSize5x5);

if ( status )
goto Fault;

// Sadly, Photoshop does a way better job. To my eyes, it's at least twice as good.
// To equal its quality we need to pull a couple more tricks before getting to here.
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
23 Replies
Beginner
8 Views

Some examples of marginal English from IPP manual- just a few of many - FYI

/* Query how big can be max output bitstream */
/* Learn how many memory block needed for the decoder */
/* Query how big has to be each block */
0 Kudos
8 Views

Thanks for report, do you mean IPP manual or UMC/UIC manual?

Regards,
Vladimir
0 Kudos
Beginner
8 Views

Thanks for report, do you mean IPP manual or UMC/UIC manual?

Regards,
Vladimir

This one...
Intel Integrated Performance
Primitives for Intel Architecture
Unified Speech Component Interface

Basically one who speaks native english "can get it" but I think, as others seem to, that Intel should make these issues go away. For those OTHER ESL (English is a Second Language) folks, reading this may not quite get the meaning if the English is distorted.
0 Kudos
8 Views

Yeah, thanks, we will correct these mistakes

Regards,
Vladimir
0 Kudos