Aforge.net Camera Capture & Save image to directory

el psy Congroo picture el psy Congroo · Jul 16, 2014 · Viewed 28.7k times · Source

everyone. I have been stuck here dealing with this bugs for days, but I still couldn't figure it out. My guess: I think my code has some problem as I did not dispose the object properly after using it, (I'm not very familiar with these concepts of releasing resources, threading) . I got these code by taking reference of what people did on youtube, but despite me doing exactly the same thing, my code didn't work out nicely.

SITUATION: I have two picture boxes, left one can take video of me, right one take the snapshot, if you press button1 , you will start the video, clone_button will copy a image i.e. take a snapshot, and save_image should save it to the path reference, however, i get a generic error occured in GDI+ again and again while I'm trying to save it. Also, my debugger seemed to get crazy (i.e. failed to terminate the vshost.exe ) once I ran this program, I have to restart the computer to get my code running again, which is bleak and frustrating.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Imaging;
//AForge.Video dll
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge;


namespace WebCameraCapture
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private FilterInfoCollection CaptureDevice; // list of webcam
        private VideoCaptureDevice FinalFrame;

        private void Form1_Load(object sender, EventArgs e)
       {
            CaptureDevice = new FilterInfoCollection(FilterCategory.VideoInputDevice);//constructor
            foreach (FilterInfo Device in CaptureDevice)
            {
                comboBox1.Items.Add(Device.Name);
            }

            comboBox1.SelectedIndex = 0; // default
            FinalFrame = new VideoCaptureDevice();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            FinalFrame = new VideoCaptureDevice(CaptureDevice[comboBox1.SelectedIndex].MonikerString);// specified web cam and its filter moniker string
            FinalFrame.NewFrame += new NewFrameEventHandler(FinalFrame_NewFrame);// click button event is fired, 
            FinalFrame.Start();
        }

        void FinalFrame_NewFrame(object sender, NewFrameEventArgs eventArgs) // must be void so that it can be accessed everywhere.
    // New Frame Event Args is an constructor of a class
        {     
            pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();// clone the bitmap
        }

        private void From1_CLosing(object sender, EventArgs e)
        {
            if (FinalFrame.IsRunning==true) FinalFrame.Stop();
        }

        private void save_Click(object sender, EventArgs e)
        {
            if (pictureBox2.Image != null)
            {
                Bitmap varBmp = new Bitmap(pictureBox2.Image);
                Bitmap newBitmap = new Bitmap(varBmp);
                varBmp.Dispose();
                varBmp = null;
                varBmp.Save(@"C:\a.png", ImageFormat.Png);
            }
            else
            { MessageBox.Show("null exception"); }
        }

        private void clone_Click(object sender, EventArgs e)
        {
            pictureBox2.Image = (Bitmap)pictureBox1.Image.Clone();
        }
   }
}

Any AForge.net user can just PRESS the LINK below and try it out. Thanks!

SAMPLE

Answer

Chris picture Chris · Aug 24, 2014

After having a look at your code, to me it appears that you are disposing of your image right before you save it. Meaning that your program can't save the image, because it doesn't exist anymore. Actually it reads that you've essentially removed the captured image twice, once on dispose, the second when you set it as null.

So if you move the two code segments after the save, it should be working. Granted without using a dialog box to change the name of the file, you'll surely receive an error unless you remove that file after each time it has been created.

private void save_Click(object sender, EventArgs e)
    {
        if (pictureBox2.Image != null)
        {
            //Save First
            Bitmap varBmp = new Bitmap(pictureBox2.Image);
            Bitmap newBitmap = new Bitmap(varBmp);
            varBmp.Save(@"C:\a.png", ImageFormat.Png);
            //Now Dispose to free the memory
            varBmp.Dispose();
            varBmp = null;
        }
        else
        { MessageBox.Show("null exception"); }
    }

If you open the task manager, you can watch how much memory your program is soaking up. Disposing of the memory after you're done using it, gives it back to the system. You don't have a dispose inside your FinalFrame_NewFrame thread, so when the camera is reading images, you should see the memory usage continue to climb until you stop the program.

I've added dispose to my thread, putting the memory usage under control, but now I'm debugging my image saves. Because I'm disposing, I can't save the image lol. My program ends up trying to save a null image file and throws the appropriate error.

I'm using a 2nd picurebox just as you are, but using for example, pbox2.image = pbox1.image, doesn't copy the data, it copies the memory location with the image data, so when I dispose pbox1 to free memory, the image data disappears with the memory location.