- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
// 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
{
*pClsid = pImageCodecInfo
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;
}
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Anyway I'm glad you solve the issue
Regards,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Anyway I'm glad you solve the issue
Regards,
Vladimir
There are a number of issues highlighted by this code. IPP step size is incorrectly caclulated for small bitmap sizes. I'm not entirely sure why theincorrectly cacluated IPPvalue works for larger bitmaps, though the fix shown here seems to work in all cases.
The docs do not adequately explain border handling considerations.
Why is IPPI_INTER_SUPER not supported by the ippiResizeSqrPixelGetBufSize() function? You made reference to it in other posts as being one of the valid options.
Lastly, the provided Intel documentation needs an overhaul. I hate to say it Vladimir ... but the English languageis a second class citizen here. Since English is the language of discourse, I would expect nothing less than first caliber diction from those supporting this forum and writing the IPP documentation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well let's try to improve the things together. If you canrefer me to the specific examples of bad written phrases in documentation I will submit this as a bug report to product bug tracker. Of course you also may do thisthrough Intel Premier Support channel.
It is also not clear for me how do you conclude IPPI_INTER_SUPER does not work? Did you notice a code example in ippiman.pdf file on page 937 (I am referring to the documents available in Inel Compiler 11.1 beta).
While English is not my native language I hope engineers may understand each other in the most of cases. Although there are native english speaking persons who provide support on this forum.
Regarding step calculation I just provided comment in your another post. If you took attention to ippiMalloc description you may notice that this fuction do align memory buffer it allocates and so it returns step for this 2D memory buffer. Soyou have to use this instead of replacing it with your own value whichdoes not take into account actual aligment done at allocation.
What exactly document do you mean saying it does not adequately explain borders? I am still hoping chapter 2 "Inte IPP Concepts" of Image processing Manual (ippiman.pdf) is quite well in explanation of these basic things.
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well let's try to improve the things together. If you canrefer me to the specific examples of bad written phrases in documentation I will submit this as a bug report to product bug tracker. Of course you also may do thisthrough Intel Premier Support channel.
It is also not clear for me how do you conclude IPPI_INTER_SUPER does not work? Did you notice a code example in ippiman.pdf file on page 937 (I am referring to the documents available in Inel Compiler 11.1 beta).
While English is not my native language I hope engineers may understand each other in the most of cases. Although there are native english speaking persons who provide support on this forum.
Regarding step calculation I just provided comment in your another post. If you took attention to ippiMalloc description you may notice that this fuction do align memory buffer it allocates and so it returns step for this 2D memory buffer. Soyou have to use this instead of replacing it with your own value whichdoes not take into account actual aligment done at allocation.
What exactly document do you mean saying it does not adequately explain borders? I am still hoping chapter 2 "Inte IPP Concepts" of Image processing Manual (ippiman.pdf) is quite well in explanation of these basic things.
Vladimir
I am making the assumption that your released product is complete in terms of the way it is documented; "beta" documentation references are out of scope for us given we are trying to produce a production grade solution based on your products.
The IPP generated step calculation, when fed back to IPP API's produces incorrect results for small bitmaps. It would also be helpful to have some guidance on mixingIPP data buffers with other libraries such as GDI+ and OpenGL textures.
I appreciate the intent Vladimir. It's all good. Just be thankful you don't have to read my French.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, I just made an assumption you use IPP 6.1 beta from Intel Parallel Composer beta.You may accessIPP 6.0producton the IPP Home page.
IPP generated step itself can't cause incorrect results regardless of image size. I'm sure the reason is some other mistake in IPP function use.
Did you take a look at IPP samples? We provide plenty of different applications in source code to demonstrate how to use IPP functions or how to build different media codecs based on IPP functions.
Regards,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, I just made an assumption you use IPP 6.1 beta from Intel Parallel Composer beta.You may accessIPP 6.0producton the IPP Home page.
IPP generated step itself can't cause incorrect results regardless of image size. I'm sure the reason is some other mistake in IPP function use.
Did you take a look at IPP samples? We provide plenty of different applications in source code to demonstrate how to use IPP functions or how to build different media codecs based on IPP functions.
Regards,
Vladimir
bool CGenerate2xSubsample::Reduce_2D_Intel(eReductionType inWhichReduction,
Ipp32f *In, int NxIn, int NyIn,
Ipp32f *Out, int NxOut, int NyOut)
{
WriteMammoLogFileString("tttReduce 2d startedn");
IppiSize size = {NxIn,NyIn};
IppiRect srect = {0,0,NxIn,NyIn};
IppiRect drect = {0,0,NxOut,NyOut};
int bufsize;
Ipp8u* buf;
IppStatus status = ippStsNoErr;
/* calculation of work buffer size */
int theType = IPPI_INTER_NN;
switch (inWhichReduction){
case EReduceNearest:
theType = IPPI_INTER_NN;
break;
case EReduceLinear:
theType = IPPI_INTER_LINEAR;
break;
case EReduceCubic:
theType = IPPI_INTER_CUBIC;
break;
case EReduceLanczos:
theType = IPPI_INTER_LANCZOS;
break;
case EReduceCubicBSpline:
theType = IPPI_INTER_CUBIC2P_BSPLINE;
break;
case EReduceCubicCatMullrom:
theType = IPPI_INTER_CUBIC2P_CATMULLROM;
break;
case EReduceSuper:
theType = IPPI_INTER_SUPER;
break;
}
ippiResizeGetBufSize( srect, drect, 1, theType, &bufsize );
/* memory allocate */
buf = ippsMalloc_8u( bufsize );
if( NULL != buf )
status = ippiResizeSqrPixel_32f_C1R(
In, size, NxIn*sizeof(Ipp32f), srect,
Out, NxOut*sizeof(Ipp32f), drect,
((float)NxOut)/((float)NxIn), ((float)NyOut)/((float)NyIn),
0, 0, theType, buf );
/* memory free */
if( NULL != buf ) ippsFree( buf );
WriteMammoLogFileString("tttReduce 2d donen");
if (status == ippStsNoErr)
return true;
else return false;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
bool CGenerate2xSubsample::Reduce_2D_Intel(eReductionType inWhichReduction,
Ipp32f *In, int NxIn, int NyIn,
Ipp32f *Out, int NxOut, int NyOut)
{
WriteMammoLogFileString("tttReduce 2d startedn");
IppiSize size = {NxIn,NyIn};
IppiRect srect = {0,0,NxIn,NyIn};
IppiRect drect = {0,0,NxOut,NyOut};
int bufsize;
Ipp8u* buf;
IppStatus status = ippStsNoErr;
/* calculation of work buffer size */
int theType = IPPI_INTER_NN;
switch (inWhichReduction){
case EReduceNearest:
theType = IPPI_INTER_NN;
break;
case EReduceLinear:
theType = IPPI_INTER_LINEAR;
break;
case EReduceCubic:
theType = IPPI_INTER_CUBIC;
break;
case EReduceLanczos:
theType = IPPI_INTER_LANCZOS;
break;
case EReduceCubicBSpline:
theType = IPPI_INTER_CUBIC2P_BSPLINE;
break;
case EReduceCubicCatMullrom:
theType = IPPI_INTER_CUBIC2P_CATMULLROM;
break;
case EReduceSuper:
theType = IPPI_INTER_SUPER;
break;
}
ippiResizeGetBufSize( srect, drect, 1, theType, &bufsize );
/* memory allocate */
buf = ippsMalloc_8u( bufsize );
if( NULL != buf )
status = ippiResizeSqrPixel_32f_C1R(
In, size, NxIn*sizeof(Ipp32f), srect,
Out, NxOut*sizeof(Ipp32f), drect,
((float)NxOut)/((float)NxIn), ((float)NyOut)/((float)NyIn),
0, 0, theType, buf );
/* memory free */
if( NULL != buf ) ippsFree( buf );
WriteMammoLogFileString("tttReduce 2d donen");
if (status == ippStsNoErr)
return true;
else return false;
}
The issue as identified in my code sample and a previous one I posted that operates on a smallish bitmap is the step value calculaton made by IPP. If you substitute the correct value rather than the one calculated by the IPP malloc functions, the other API's perform as expected. There are even instances where IPP will crash your app if you use its step value calculations. At some point Vladamir will eventually listen, I'm sure of that.
Some of the underlying tech of IPPis VERY good indeed. That's why we're using it. I've decided to look at the obfuscations of the IPP docs and the failings of some of the APIsas a good thing. It will prevent many from doing anything useful with the API thus giving the few that get past it an advantage.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The issue is not in calculation of step in IPP. The problem is that you ignore actual data layout in your code and assume there is no padding in bitmap data you obtain through Windows API.
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This discussion alsowas recorded to IPP KB. Please see
http://software.intel.com/en-us/articles/resize-function-ippiresizesqrpixel-crashed-for-small-image/ and it includes one ippiResizeSqrPixelC sample code.
Best Regards,
Ying
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The issue is not in calculation of step in IPP. The problem is that you ignore actual data layout in your code and assume there is no padding in bitmap data you obtain through Windows API.
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
regardless of what you are going to override you have to use IPP function with correct and valid parameters. In case of correct usage IPP functions will work with array of any size.
Regards,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
regardless of what you are going to override you have to use IPP function with correct and valid parameters. In case of correct usage IPP functions will work with array of any size.
Regards,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Regards,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Very thanks for an example. Yes, really, we had an error :(
It will be corrected in following release.
Now I recommend to you the workaround - to change interpolation type to increase very small source images:
if (size.NxIn < 6 || size.NyIn < 6) {
if (theType == IPPI_INTER_LANCZOS)
theType = IPPI_INTER_CUBIC;
if (size.NxIn < 4 || size.NyIn < 4) {
if ((theType == IPPI_INTER_CUBIC) ||
(theType == IPPI_INTER_CUBIC2P_BSPLINE) ||
(theType == IPPI_INTER_CUBIC2P_CATMULLROM) ||
(theType == IPPI_INTER_CUBIC2P_B05C03))
theType = IPPI_INTER_LINEAR;
}
}
I think that it's quite correct for such small sizes.
Thanks,
Yuri
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Very thanks for an example. Yes, really, we had an error :(
It will be corrected in following release.
Now I recommend to you the workaround - to change interpolation type to increase very small source images:
if (size.NxIn < 6 || size.NyIn < 6) {
if (theType == IPPI_INTER_LANCZOS)
theType = IPPI_INTER_CUBIC;
if (size.NxIn < 4 || size.NyIn < 4) {
if ((theType == IPPI_INTER_CUBIC) ||
(theType == IPPI_INTER_CUBIC2P_BSPLINE) ||
(theType == IPPI_INTER_CUBIC2P_CATMULLROM) ||
(theType == IPPI_INTER_CUBIC2P_B05C03))
theType = IPPI_INTER_LINEAR;
}
}
I think that it's quite correct for such small sizes.
Thanks,
Yuri
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
you probably may try ippiPyramidLayerDown/Up functions from ipp computer vision library (ippcv). These functions support Ipp32f data type
Regards,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
you probably may try ippiPyramidLayerDown/Up functions from ipp computer vision library (ippcv). These functions support Ipp32f data type
Regards,
Vladimir
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Very thanks for an example. Yes, really, we had an error :(
It will be corrected in following release.
Now I recommend to you the workaround - to change interpolation type to increase very small source images:
if (size.NxIn < 6 || size.NyIn < 6) {
if (theType == IPPI_INTER_LANCZOS)
theType = IPPI_INTER_CUBIC;
if (size.NxIn < 4 || size.NyIn < 4) {
if ((theType == IPPI_INTER_CUBIC) ||
(theType == IPPI_INTER_CUBIC2P_BSPLINE) ||
(theType == IPPI_INTER_CUBIC2P_CATMULLROM) ||
(theType == IPPI_INTER_CUBIC2P_B05C03))
theType = IPPI_INTER_LINEAR;
}
}
I think that it's quite correct for such small sizes.
Thanks,
Yuri
An udpate about this bug: it was fixed in the IPP 6.1 update 2 release.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
/* 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 */
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page