Loading an Ippi Image

Loading an Ippi Image

I always have this pesky problem of loading the image created after using ippiMalloc(). Have done it in the past on IPPI 3 but can't find the code. This time I have a webcam image with its window so I have the window handle and can get the HDC using GetWindowDC() but what is the mechanism for transferring the image to the ippi image? Lost in the details. Have tried memcpy() and BitBlt() but may have done it incorrectly, or should I use something else? Not using MFC for this app and have checked all the Forum here with no luck. Thanks for any assistance.
Rick

8 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

HI,

May be you can use Win32 GetDIBits function?

Anyway, it wouild be great if someone can share here such a code or just link to where people can find it. Let's collect some simple tips&tricks!

From my side, I can share here part of my old sample, which demonstrate how to use IJL to compress desktop window. (you need get access to the pixel data by HDC of desktop window) So, here is the function which do actual work

static BOOL sshOnScreenshot(
PAPP_DATA)
{
int ires;
int width;
int height;
int pad_bytes;
int line_width;
int nChannels;
BOOL bres = FALSE;
HDC hdesktopDC = NULL;
HDC hmemDC = NULL;
HWND hWndDesktop = NULL;
HBITMAP holdBmp = NULL;
HBITMAP hdesktopBmp = NULL;
BYTE* dibits = NULL;
BITMAPINFO bmi;
BITMAPINFOHEADER bmih;
IJLERR jerr;
JPEG_CORE_PROPERTIES jcprops;
ZeroMemory(&bmi,sizeof(BITMAPINFO));
ZeroMemory(&bmih,sizeof(BITMAPINFOHEADER));
ZeroMemory(&jcprops,sizeof(JPEG_CORE_PROPERTIES));
hWndDesktop = GetDesktopWindow();
if(NULL == hWndDesktop)
{
bres = FALSE;
goto Exit;
}
hdesktopDC = GetDC(hWndDesktop);
if(NULL == hdesktopDC)
{
bres = FALSE;
goto Exit;
}
hmemDC = CreateCompatibleDC(hdesktopDC);
if(NULL == hmemDC)
{
bres = FALSE;
goto Exit;
}
width = GetSystemMetrics(SM_CXSCREEN);
height = GetSystemMetrics(SM_CYSCREEN);
if(width == 0 || height == 0)
{
bres = FALSE;
goto Exit;
}
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = width;
bmih.biHeight = height;
bmih.biPlanes = 1;
bmih.biBitCount = 24;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
hdesktopBmp = CreateDIBitmap(hdesktopDC,&bmih,0,NULL,NULL,DIB_RGB_COLORS);
if(NULL == hdesktopBmp)
{
bres = FALSE;
goto Exit;
}
holdBmp = (HBITMAP)SelectObject(hmemDC,hdesktopBmp);
if(NULL == holdBmp)
{
bres = FALSE;
goto Exit;
}
bres = BitBlt(hmemDC,0,0,width,height,hdesktopDC,0,0,SRCCOPY);
if(FALSE == bres)
{
goto Exit;
}
// we want 3 channel dib data
nChannels = 3;
pad_bytes = IJL_DIB_PAD_BYTES(width,nChannels);
line_width = (width * nChannels) + pad_bytes;
dibits = new BYTE [line_width * height];
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter
= 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
ires = GetDIBits(hdesktopDC,hdesktopBmp,0,height,dibits,&bmi,DIB_RGB_COLORS);
if(ires == 0)
{
bres = FALSE;
goto Exit;
}
// now we have 24 bpp bitmap data
jerr = ijlInit(&jcprops);
if(IJL_OK != jerr)
{
bres = FALSE;
goto Exit;
}
jcprops.DIBWidth = width;
jcprops.DIBHeight = -height;
jcprops.DIBChannels = nChannels;
jcprops.DIBPadBytes = IJL_DIB_PAD_BYTES(width,3);
jcprops.DIBColor = IJL_BGR;
jcprops.DIBSubsampling = IJL_NONE;
jcprops.DIBBytes = dibits;
jcprops.JPGWidth = width;
jcprops.JPGHeight = height;
jcprops.JPGChannels = nChannels;
jcprops.JPGColor = IJL_YCBCR;
jcprops.JPGSubsampling = IJL_411;
jcprops.JPGBytes = NULL;
jcprops.JPGSizeBytes = 0;
jcprops.JPGFile = "desktop.jpg";
jcprops.jquality = 75;
jerr = ijlWrite(&jcprops,IJL_JFILE_WRITEWHOLEIMAGE);
if(IJL_OK != jerr)
{
bres = FALSE;
goto Exit;
}
bres = TRUE;
Exit:
ijlFree(&jcprops);
if(NULL != dibits)
{
delete [] dibits;
}
if(NULL != holdBmp && NULL != hmemDC)
{
SelectObject(hmemDC,holdBmp);
}
if(NULL != hdesktopBmp)
{
DeleteObject(hdesktopBmp);
}
if(NULL != hmemDC)
{
DeleteDC(hmemDC);
}
if(NULL != hWndDesktop && NULL != hdesktopDC)
{
ReleaseDC(hWndDesktop,hdesktopDC);
}
return bres;
} // sshOnScreenshot()

Regards,
Vladimir

Vladimir,
Thank you very much for your quick response and code example. It looks promising and I'll let you know how that approach works.

On a prior project I used the ippiSample file as a starting place and read .bmp files to load images and that worked OK for that project. I like the ippiSample as there are several useful C++ classes ready to use and I couldadd others for printing etc.

Vladimir,
I used pieces of your example code in my webcam application. Thanks for that, it helped see the process requirements. I couldn't get the GetDIBits() call to function, everything before that seemed OK. I found some similar code at mathtools.net that uses the Clipboard and that works! OK for now as I would like to eliminate that requirement later. I used the ippiSample MFC project included with IPPI 4.0 as that provides a comple MFC framework. (But adding printing with that is a big problem, why didn't they check off the printing support when creating the application with the MFC Wizard?). Simple code is below. Iput the standard capCreateCaptureWindow() and capDriverConnect() callsin CIppiSampleApp::InitInstance to set up the camera. Then I used the MFC wizard to add a menu item link to the CSampleView to grab an image from the camera to the ippiImage (ie the CSampleDoc).

void CSampleView::OnGrabframe()
{
bool bAns;

HBITMAPm_hBmp = NULL;
CBitmap m_bmp; //bitmap object
BITMAP bm;
CPaintDC dc(this); // device context for painting

bAns = capGrabFrame(hWndC); // grab an image from the camera to the MDI doc.

capEditCopy(hWndC); // copies the frame to the clipboard
bAns = OpenClipboard(); //like virtual memory.

m_hBmp = (HBITMAP)::GetClipboardData(CF_BITMAP); //m_hBmp is a Handle to clipboard Bitmap.

CloseClipboard(); // free it up
m_bmp.Detach(); //cleaning the bitmap.
m_bmp.Attach(m_hBmp); //connecting the bitmap, throw the handle.

this->Invalidate(true);
m_bmp.GetBitmap(&bm);

bAns = m_ImageDC.DeleteDC();
m_ImageDC.CreateCompatibleDC(&dc);
m_ImageDC.SelectObject(&m_bmp);
dc.StretchBlt(0, 0, 640,480,
&m_ImageDC,0,0,bm.bmWidth,bm.bmHeight, SRCCOPY);

}

Vladimir,
OK, here is a rudimentary "rest of the solution" to grab a frame from a Logitech webcam and put it into an Ippi image ready for the Ippi suite of processing algorithms available. My previous post merely copies the webcam image to the CSampleView window and displays it. More work has to be done, using the GetDIBits() to copy the image to an Ippi image buffer. To test it is working (just because no ippiErr is returned doesn't mean an image was copied) I added another menu itemto cause the image to rotate 45 degrees about its center. CSampleView::OnProcessRot45(). I still don't see a way to eliminate copying the webcam image to the Clipboard.

*****************************************************************************
void CSampleView::OnGrabframe()
{
bool bAns;
int iAns;
IppStatus rslt;

HBITMAPm_hBmp = NULL;
CBitmapm_bmp; //bitmap object
BITMAPbm;
CPaintDC dc(this); // device context for painting

bAns = capGrabFrame(hWndC); // grab an image from the camera to the MDI doc.
capEditCopy(hWndC); // copies the frame to the clipboard
bAns = OpenClipboard(); //like virtual memory.

m_hBmp = (HBITMAP)::GetClipboardData(CF_BITMAP); //m_hBmp is a Handle to clipboard Bitmap.
CloseClipboard(); // free it up
m_bmp.Detach(); //cleaning the bitmap.
m_bmp.Attach(m_hBmp); //connecting the bitmap, throw the handle.

this->Invalidate(true);
iAns = m_bmp.GetBitmap(&bm);
bAns = m_ImageDC.DeleteDC();//m_ImageDC is DC for the SampleView
m_ImageDC.CreateCompatibleDC(&dc);
m_ImageDC.SelectObject(&m_bmp);
bAns = dc.StretchBlt(0, 0, 640,480, // dc is Paint object for this SampleView
&m_ImageDC,0,0,bm.bmWidth,bm.bmHeight, SRCCOPY);//uses CDC*

//****************** done copying camera image to window
int totl;
BITMAPINFObmi;
BITMAPINFOHEADER bmih;
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = 640;
bmih.biHeight = 480;
bmih.biPlanes = 1;
bmih.biBitCount = 24;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = 640;
bmi.bmiHeader.biHeight = 480;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
totl = GetDIBits( m_ImageDC, // handle to device context
m_hBmp, // handle to bitmap
0, // first scan line to set in destination bitmap
480, // number of scan lines to copy
(void*)p_mem, // address of array for bitmap bits, our ipp8u memory
&bmi, // address of structure with bitmap data
DIB_RGB_COLORS // RGB or palette index
);
DeleteObject(m_hBmp);
}
void CSampleView::OnProcessRot45()
{
IppStatus rslt;
CSampleDoc* thedoc;
CIppiImage* thisimg;
IppiRecttheRO
I;
IppiSize imgsz;
CDC*pdc;
CIppiImageDC viewIppiDC;
thedoc = this->GetDocument();
thisimg = thedoc;
pdc = this->GetDC();
theROI.height = 480;
theROI.width = 640;
theROI.x= 0;
theROI.y= 0;
imgsz.height = 480;
imgsz.width = 640;
rslt = ippiRotateCenter_8u_C3R((Ipp8u*) p_mem, imgsz, thisimg->Step(), theROI,
(Ipp8u*) thisimg->DataPtr(), thisimg->Step(), theROI,
45, 320, 240, IPPI_INTER_NN);

m_ImageDC.SetData();// put img to device context
this->Invalidate(true);// repaint

}// end ::OnProcessRot(45)

Hi,

As I understand you can get access to captured frame pixels when you use grabber callback function. Can you get pointer to LPVIDEOHDR structure which describes captured frame?

Regards,
Vladimir

Vladimir,
Thanks for the tip and I got the callback to work:
///////////
.
.
capSetCallbackOnFrame(hWndC,capVideoStreamCallback); // callbak for GrabFrame
.
bAns = capGrabFrame(hWndC); // grab an image from the camera to the MDI doc.
.
.
/////////

callback:
LRESULT CALLBACK capVideoStreamCallback(HWND hWnd, LPVIDEOHDR lpVHdr)
{
p_videodat = lpVHdr->lpData;
videodatlngth = lpVHdr->dwBufferLength;
return true;
}

Now I just have to figure out again how to use this pointer to copy the image data to the View......

Rick

Hi Rick

actually it is pointer to DIB pixels. Only thing you need - to get format of these data with couple of functions:
capGetVideoFormatSize
capGetVideoFormat

DWORD capGetVideoFormat(
  hwnd,           
  psVideoFormat,  
  wSize           
);
 

hwnd
Handle of a capture window.
psVideoFormat
Address of a
BITMAPINFO structure. You can also specify NULL to retrieve the number of bytes needed by BITMAPINFO.
wSize
Size, in bytes, of the structure referenced by s.
Regards,
Vladimir

Leave a Comment

Please sign in to add a comment. Not a member? Join today