PDA

View Full Version : Simple Windows Forms-Application with pictureBox and livestream



sas
June 29, 2010, 12:28:09
Hello there,

I am trying to set up a Windows Forms-Application in Visual Studio 2008, where there is just a pictureBox in the Form. In the pictureBox I want to see a livestream of the Camera (USB Camera 41BUC02).

In the documentation there is a step by step guide how to create an MFC application. I tried to do the same steps with creating a Windows Forms-Application. The problems come up with the functions:

m_pGrabber->setHWND( ??? )

I dont know how to connect this function with the pictureBox. Looking at the ID Dialog Applications which are available as Project in VS after installing Imaging Control, the image is shown in a component called "Text Control", but "Text Control" is not to be found in the toolbox.

Another problem is created by:

atexit(DShowLib::ExitLibrary)

This causes an error "Debug Assertion Failed".

If both of the funtioncalls are uncommented, the program starts and shows a livestream on the full screen. In the front is the empty form.

Unfortunately im not very experienced with GUI applications, in particular MFC Applications. If I should send you the application please let me know. I hope you can help me, thanks!

Stefan Geissler
June 29, 2010, 13:35:43
Hello,

you can not pass the HWND member of a PictureBox to the Grabber. This works with CStatic. However, you can try

m_pGrabber->setHWND( MyPictureBox.m_hWnd );

or

m_pGrabber->setHWND( MyCStatic.m_hWnd );

Regarding the Debug Assertion, I must get some more information about this.

sas
June 29, 2010, 14:27:03
Hallo Stefan,

Thank you for the answer. The pictureBox only has an Attribute "Handle" which can not be casted to HWND. It seems that once the Application is not based on MFC Classes there is no hWnd handles. CStatic is a MFC Class. I dont know how to include the MFC classes or if it is good to mix them with a Windows Forms-Application.

Are there any sample programmes not based on MFC but are Windows Forms-Applications?

Stefan Geissler
June 29, 2010, 16:21:27
Hello,

The "Handle" should be the HWnd Window Handle. You may cast it to IntPtr and pass it to setHWnd.

If you want to create an MFC application, then look into the "samples\vc*" directory of your IC Imaging Control installation. If you use IC Imaging Control 3.1, then look into your "My Documents" directory for "IC Imaging Control 3.1".

However, if you use Visual Studio non express, then you can create a new MFC project using the IC Imaging Control project wizards.

sas
June 30, 2010, 15:36:40
Hi, thank you very much. I now solved the problem by using following lines:

HWND xhwnd;
xhwnd = (HWND)pictureBox1->Handle.ToPointer();
m_pGrabber->setHWND(xhwnd);

After this the livestream is shown in the pictureBox. The Attributes of the pictureBox to center the Image or to stretch it are not working now. There is only a top left portion of the Livestream shown. I used some parts of the Scroll and Zoom sample to manually change the size of the stream.

Now there is a problem with the snapping of Images from the stream. I have 3 Buttons, one for starting the stream, one for stopping the stream and one for snapping an image. For the snapping of images I used the code from the MembufferCollection sample. I changed it to only snap a single image. This image is stored in a local directory. Unfortunately I have to to load the image form the disk to be shown in an other pictureBox instead of having access to it directly after the snap. Well the problem now is: I have the grabber as pointer attribute of the Form class:

DShowLib::Grabber* m_pGrabber;

and in the constructor the memory is allocated:

m_pGrabber = new DShowLib::Grabber();

In the Function responsible for the snapping, there is a functioncall:

setupDeviceFromFile(grabber)

It needs an Object of Grabber but the grabber is only available as pointer.

I dont know how to pass the grabber to the function. If the setupDeviceFromFile call is not used, the grabber.prepareLive( false ) function fails.

If you want the programm to take a look, please let me know where to send it. Thank you!

sas
June 30, 2010, 19:03:43
I think I solved this problem:

setupDeviceFromFile(dynamic_cast<Grabber&>(*m_pGrabber)))

One problem solved, another problem comes up:

For snapping images from the livestream while the stream is displayed, I have to use the sequence:


startLive() //shows livestream in picturebox

//snapping

stopLive()

...

m_pGrabber->prepareLive(false))

...

startLive()

snapImages(1)

stopLive()

startLive()


I dont think this a good way of programming. The Livestream must be stopped if you dont want prepareLive to fail. And if the livestream isnt stopped and started after snapImages, the livestream wont be shown. Is there a way to do this more efficient?

Another problem is that only the first image can be saved, all following are not saved. I have no ideo where this problem comes from. (save returns true the first time, then false)

And another question: Is there a good reason to use grabber.showDevicePage instead of setupDeviceFromFile (cmdhelper.h)? If I dont use setupDeviceFromFile, the function grabber.prepareLive fails.


Sorry for so many questions!

Stefan Geissler
July 1, 2010, 08:47:21
Hello,

First of all, you can call snapImages() as long as the live video has been started. You do not need to stop the live video. Your problem is, you want to you the same PictureBox control for the live video and the still image. For doing so, you may use two PictureBoxes on the same position. While the still image is valid, you show the PictureBox with the still image. If you want to show the live video again, you simply hide the still image PictureBox. (BTW: I have no idea, how to pass an ImageBuffer directly into the PictureBox using the Classlibrary. The IC Imaging Control .NET component has the "System.Drawing.Bitmap ImageBuffer.Bitmap" for doing this.)

Another problem is that only the first image can be saved, all following are not saved. I have no ideo where this problem comes from. (save returns true the first time, then false)
Maybe you need to call "snapImages" more often? To be honest, I do not understand your question.

And another question: Is there a good reason to use grabber.showDevicePage instead of setupDeviceFromFile (cmdhelper.h)? If I dont use setupDeviceFromFile, the function grabber.prepareLive fails.
Maybe you did not open a device using "Grabber.openDev("Insert device name here")? In this case startLive fails.

However, you should consider using C# and the IC Imaging Control .NET component, because handling PictureBoxes is much simpler in there.

sas
July 1, 2010, 10:34:58
Hi,

I have 2 pictureBoxes, one for showing the livestream, and one for showing the snapped and saved image.

On starting the programm, the constructor calls

InitLibrary(), creates the grabber and calls openDev().


The Livestream is started by calling

setupDeviceFromFile
setHWND
startLive


After this the livestream is shown in one of the pictureBoxes.

For each snap I set up a new sink, maybe this is wrong. The snapped image will be shown in the other pictureBox.


Maybe you need to call "snapImages" more often? To be honest, I do not understand your question.

I call snapImages for every snap, but the function for saving the image only returns true the first time it is called.

Its not so easy to explain. I attached my programm to this post. If you could take a look at it, that would be great. Maybe it becomes more clear if you see the programm.

Stefan Geissler
July 1, 2010, 14:08:40
Hello,

you are right, the FrameHandlerSink needs to be created only once! You only need these lines:


pSink->snapImages(1);
pSink->getLastAcqMemBuffer()->save( "C:\\temp.bmp");
System::Drawing::Bitmap ^tempBitmap = gcnew System::Drawing::Bitmap("C:\\temp.bmp");
pictureBox2->Image = tempBitmap;



The variable "tFrameHandlerSinkPtr pSink" should be a member of your class and not be declared local. Declare it directly near the grabber.

In the constructor you do following


Form1(void)
{
InitializeComponent();

if( ! DShowLib::InitLibrary( 0 ) )
{
MessageBox::Show("InitLibrary failed!");
return;
}

m_pGrabber = new DShowLib::Grabber();

m_pGrabber->openDev("DMx 41BUC02");

assert(m_pGrabber);

tFrameHandlerSinkPtr pSink = FrameHandlerSink::create(eY800, 5);

// We use snap mode.
pSink->setSnapMode(true);

// Set the sink.
m_pGrabber->setSinkType(pSink);
}


Now you can use the pSink whenever you want the the live video is running.

sas
July 4, 2010, 21:18:28
Hi, thank you for the answer. With the sink only created once it should work.

I have to admit that I changed to C#. Everything is so much easier there. The application I was trying to setup in C++, is now reduced to only two lines of Code (C#).

z-man
August 6, 2010, 16:51:53
Hi

I'm trying to do something similar. Can you please share the "two lines of code"?

Thanks,
Zvonko

Stefan Geissler
August 16, 2010, 16:33:34
Hello,

You use the Bitmap property of the ImageBuffer:
http://www.imagingcontrol.com/en_US/support/documentation/dotnet/prop_descImageBuffer_Bitmap.htm

IcImagingControl.MemorySnapImage();
PixtureBox.Image = IcImagingControl.ImageActiveBuffer.Bitmap;

These are the two lines :-)