Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
21 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
Highlighted
Beginner
3 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
Highlighted
3 Views

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

Regards,
Vladimir
0 Kudos
Highlighted
Beginner
3 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
Highlighted
3 Views

Yeah, thanks, we will correct these mistakes

Regards,
Vladimir
0 Kudos