c# only Second Bitmap.Save produce A generic error occurred in GDI+ exception

315 Views Asked by At

I am using the following code to compare between two images and save the result. In the first run I successfully create and save the result image, But in the second run I get the following exception:

An exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dll but was not handled in user code

Additional information: A generic error occurred in GDI+.

The code:

MagickImage magickBaseImg = new MagickImage(new Bitmap(baseImageFileName));
MagickImage magickTargetImg = new MagickImage(new Bitmap(targetImageFileName));

var diffImg = new MagickImage();
magickBaseImg.Compare(magickTargetImg, ErrorMetric.RootMeanSquared, diffImg, Channels.Red);

Bitmap ImgToSave = diffImg.ToBitmap();

DateTime currentTime = DateTime.Now;
String differencesImageSavingPath = @"C:\test\DiffImage" + currentTime.ToString("ddMMyyyyHHmm") + ".bmp";
**ImgToSave.Save(differencesImageSavingPath, System.Drawing.Imaging.ImageFormat.Bmp);**

differencesImageFileName = differencesImageSavingPath;
DiffrenceImage.Source = new BitmapImage(new Uri(differencesImageFileName));

The line that marks with ** is the line that throw the exception in the second run. Already read and tried fixing it with "using" and .dispose as written here: A Generic error occurred in GDI+ in Bitmap.Save method and here: A generic error occurred in GDI+, JPEG Image to MemoryStream

But it is not working.

For Example the following code doesn't work either:

MagickImage magickBaseImg = new MagickImage(new Bitmap(baseImageFileName));
MagickImage magickTargetImg = new MagickImage(new Bitmap(targetImageFileName));

var diffImg = new MagickImage();
magickBaseImg.Compare(magickTargetImg, ErrorMetric.RootMeanSquared, diffImg, Channels.Red);

Bitmap ImgToSave = diffImg.ToBitmap();

DateTime currentTime = DateTime.Now;
String differencesImageSavingPath = @"C:\test\DiffImage" + currentTime.ToString("ddMMyyyyHHmm") + ".bmp";

using (var tempImg = new Bitmap(ImgToSave)) {
    tempImg.Save(differencesImageSavingPath, System.Drawing.Imaging.ImageFormat.Bmp);
}

differencesImageFileName = differencesImageSavingPath;
DiffrenceImage.Source = new BitmapImage(new Uri(differencesImageFileName));
2

There are 2 best solutions below

0
On

I am not sure why saving the bitmap fails but don't need to make it a bitmap.The Magick.NET library has support for reading and writing BMP images. Below is an example of how you could change your code:

using (MagickImage magickBaseImg = new MagickImage(baseImageFileName))
using (MagickImage magickTargetImg = new MagickImage(targetImageFileName))
{
  using (var diffImg = new MagickImage())
  {
    magickBaseImg.Compare(magickTargetImg, ErrorMetric.RootMeanSquared, diffImg, Channels.Red);

    DateTime currentTime = DateTime.Now;
    string differencesImageSavingPath = @"C:\test\DiffImage" + currentTime.ToString("ddMMyyyyHHmm") + ".bmp";
    diffImg.Save(differencesImageSavingPath);

    differencesImageFileName = differencesImageSavingPath;
    DiffrenceImage.Source = new BitmapImage(new Uri(differencesImageFileName));
  }
}
0
On

I had this exact problem, and @dlemstra had a good clue: using .ToBitmap() solved my use case.

Before:

using (var image = new MagickImage(source))
using (var ms = new MemoryStream())
{
    image.Write(ms);
    ms.Position = 0;
    return (Bitmap)Image.FromStream(ms);
}

After:

using (var image = new MagickImage(source))
    return image.ToBitmap();