1

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));
Community
  • 1
  • 1
Yuval Levy
  • 2,397
  • 10
  • 44
  • 73
  • Sure the image isnt open somewhere else? – BugFinder Dec 19 '16 at 10:57
  • tempImg can't be opened - I created a new instance and invoking it also inside"using" statement – Yuval Levy Dec 19 '16 at 11:02
  • that still doesnt preclude you from using it somewhere else – BugFinder Dec 19 '16 at 11:17
  • You read about it but it is still the same reason. Using using and Dispose does indeed not help. - See [here](http://stackoverflow.com/questions/37736815/overwrite-image-picturebox-in-c-sharp/37741101?s=25|0.0842#37741101) – TaW Dec 19 '16 at 11:26
  • How often do you call that method? As you are saving the image to a filename with minutes and assign it to the DifferenceImage.Source it might be open and therefore writeprotected. The error might not occure if you call the method in different minutes. – Thomas Voß Dec 26 '16 at 20:56

2 Answers2

1

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));
  }
}
dlemstra
  • 7,813
  • 2
  • 27
  • 43
0

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();
Dinosaure
  • 125
  • 10