Search code examples
c#webcampictureboxwebcam-capture

Webcam image differ from printed image


I am busy with a C# winform software. I use webcam to take a picture which display in a pictureBox.

When I capture the image with the webcam, it captures a zoomed image, and when printing, it is a stretched image. I have tried a variety of SizeMode settings.All give the same result

Because I am not sure where the fault is, I will include as much detail as possible:

Using

using AForge.Video;
using AForge.Video.DirectShow;

Selecting Camera:

webcam = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            foreach (FilterInfo VideoCaptureDevice in webcam)
            {
                cmbVideoList.Items.Add(VideoCaptureDevice.Name);
            }

Using camera (btn click):

cam = new VideoCaptureDevice(webcam[cmbVideoList.SelectedIndex].MonikerString);
        cam.NewFrame += new NewFrameEventHandler(cam_NewFrame);
        cam.Start();
        if (cam.IsRunning)
        {
            btnStart.Hide();
        }
        btnStop.Show();

    }
    void cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        Bitmap bit = (Bitmap)eventArgs.Frame.Clone();
        pboxPhoto.Image = bit;
    }

PictureBox size:

Width: 226

Height: 328

Printing code:

 PictureBox pict = (PictureBox)pboxPhoto;
        pict.SizeMode = PictureBoxSizeMode.Zoom;
        e.Graphics.DrawImage(pict.Image, 20, 416, 305, 328);

Here is a sample of the image on software: enter image description here

Sample of printed image. enter image description here


Solution

  • The simplest way is to tell the PictureBox to draw itself to a Bitmap.

    This can be done with all Controls and the result will include not just the Image and maybe BackgroundImage but also anything drawn in the Paint event as well as any nested Controls.

    Here is a simple example:

    Size sz = pictureBox1.ClientSize;
    using (Bitmap bmp = new Bitmap(sz.Width, sz.Height))
    {
        pictureBox1.DrawToBitmap(bmp, pictureBox1.ClientRectangle);
        // save the image..
        bmp.Save(yourfilepath, ImageFormat.Png);
        // ..or print it!
    }
    

    A few notes:

    • Due to the using clause the Bitmap get disposed after the last curly, so you would either make use of it inside scope or change to a pattern that disposes of the Bitmap at a later point in time.

    • The nested Controls will be drawn a reverse order which will cause problem if they are overlapping!

    • Only nested, not overlayed Controls will be included. Since PictureBox is not a Container (as opposed to e.g. a Panel) it won't do to simply placea, say Label, over it; instead you need to nest it in code, i.e. make the PictureBox its Parent and also set a suitable relative Location..

    • By default the Bitmap will have the current machine's screen dpi resolution. You cold change it afterwards with bmp.SetResolution()..