user3905287 user3905287 - 3 months ago 18
C# Question

Generic Error in GDI+ when saving image

I am trying to save the Image of picEmployeeImage when a button is clicked. PicEmployeeImage streams a video so when take photo is pressed, it saves it to a file. Currently when I try it, it says "a generic error occured in GDI+"

How do I fix this?

Please Help.

Here is the code:

public void TakePhoto()
{
Bitmap bm = new Bitmap(picEmployeeImage.Width, picEmployeeImage.Height);
bm = (Bitmap) picEmployeeImage.Image;
bm.Save(@"\Images\" + currentlySelectedId + ".bmp", ImageFormat.Bmp);

}


private void btnCaptureNewImage_Click(object sender, EventArgs e)
{
if (btnCaptureNewImage.Text == "Capture New Image")
{
VideoShow();
btnCaptureNewImage.Text = "Take Photo";
} else
{
TakePhoto();
btnCaptureNewImage.Text = "Capture New Image";
}
}

void VideoShow()
{
VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
FinalVideoSource = new VideoCaptureDevice(VideoCaptureDevices[0].MonikerString);
FinalVideoSource.NewFrame += new NewFrameEventHandler(FinalVideoSource_NewFrame);
FinalVideoSource.Start();
}

void FinalVideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
image = (Bitmap)eventArgs.Frame.Clone();
image = CropBitmap(image, 150, 100, 300, 200);
picEmployeeImage.Image = image;
}


Update:
Error Information:

System.Runtime.InteropServices.ExternalException (0x80004005): A generic error occurred in GDI+.
at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
at BusinessSoftware.frmLoginPage.TakePhoto() in C:\Users\....cs:line 721
at BusinessSoftware.frmLoginPage.btnCaptureNewImage_Click(Object sender, EventArgs e) in C:\Users\....cs:line 705
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Answer

This is because GDI+ Image class is not thread safe.

Create a new bitmap image and draw the image you captured on this new Bitmap object and save this new object. Code below:

public void TakePhoto()
{
    Bitmap bm = new Bitmap(picEmployeeImage.Width, picEmployeeImage.Height);
    bm = (Bitmap)picEmployeeImage.Image;

    Bitmap bmp = new Bitmap(bm.Width, bm.Height);
    Graphics g = Graphics.FromImage(bmp);
    g.DrawImage(bm, 0, 0, bmp.Width, bmp.Height);
    bmp.Save(@"\Images\" + currentlySelectedId + ".bmp", ImageFormat.Bmp);
}

Also, I would suggest you to stop the FinalVideoSource when "Take Photo" button is clicked

private void btnCaptureNewImage_Click(object sender, EventArgs e)
{
    if (btnCaptureNewImage.Text == "Capture New Image")
    {
        VideoShow();
        btnCaptureNewImage.Text = "Take Photo";
    }
    else
    {
        FinalVideoSource.Stop();
        TakePhoto();
        btnCaptureNewImage.Text = "Capture New Image";
    }
}

HTH.