Home > Back-end >  Locked image causing Generic GDI Error when using same image
Locked image causing Generic GDI Error when using same image

Time:06-01

I have an application that is reading registration plates of an image. I have a simple UI where user can select image to scan using FilePicker.

So scenario where the problem occurs

  1. Select image A
  2. Scan image A --> Success
  3. Select image B
  4. Scan image B --> Success
  5. Select image A
  6. Scan image A --> Fail

Error I receive

System.Runtime.InteropServices.ExternalException: 'A generic error occurred in GDI .'

I'm using WPF so Image component is using SourceImage as source. I then do conversion. I couldn't find anything to convert SourceImage --> SoftwareBitmap so I use Bitmap as proxy object

SourceImage --> Bitmap --> SoftwareImage (used by Microsoft OCR)

Code samples

File Picker

OpenFileDialog openFileDialog = new OpenFileDialog()
        {
            InitialDirectory = @"c:\Temp",
            Filter = "Image files (*.jpg;*.jpeg;*.png)|*.jpg;*.jpeg;*.png",
            FilterIndex = 0,
            RestoreDirectory = true,
            Multiselect = false
        };
        
        if (openFileDialog.ShowDialog() == true)
        {
            img = new BitmapImage();
            img.BeginInit();
            img.CacheOption = BitmapCacheOption.OnLoad;
            img.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
            img.UriSource = new Uri(openFileDialog.FileName);
            img.EndInit();

            if(img != null)
            {
                ANPR_image.Source = img;
            }

        }

Convert to Bitmap

Bitmap bmp = new Bitmap(
          source.PixelWidth,
          source.PixelHeight,
          System.Drawing.Imaging.PixelFormat.Format32bppArgb
          );

        BitmapData data = bmp.LockBits(
          new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size),
          ImageLockMode.WriteOnly,
          System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

        source.CopyPixels(
          Int32Rect.Empty,
          data.Scan0,
          data.Height * data.Stride,
          data.Stride);

        bmp.UnlockBits(data);

        return bmp;

Convert to SoftwareBitmap and OCR

using (Windows.Storage.Streams.InMemoryRandomAccessStream stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
        {
            if(newBitmap != null)
            {
               
                newBitmap.Save(stream.AsStream(), ImageFormat.Tiff); //choose the specific image format by your own bitmap source
                BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
                using (SoftwareBitmap s_Bitmap = await decoder.GetSoftwareBitmapAsync())
                {
                    try
                    {
                        result = await ocr.RecognizeAsync(s_Bitmap);
                        newBitmap.Dispose();
                        image.Dispose();
                        
                        return result is null ? "" : result.Text;
                    }
                    catch(Exception e)
                    {
                        return "Error";
                    }
                
                }
            }
            else
            {
                return "Image is null";
            }

The error occurs here newBitmap.Save(stream.AsStream(), ImageFormat.Tiff); //choose the specific image format by your own bitmap source

I read online about this error and it seems there may be a lock somewhere but I can't figure out where... I tried disposing of all possible images, I wrapped everything with using statements. Nothing works...

Any ideas, suggestion would be appreciated!

Thanks

CodePudding user response:

You may simplify your code by creating both bitmaps from a single MemoryStream. Pass stream.AsRandomAccessStream() to the BitmapDecoder.

var buffer = await File.ReadAllBytesAsync(openFileDialog.FileName);

using (var stream = new MemoryStream(buffer))
{
    ANPR_image.Source = BitmapFrame.Create(
        stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);

    using (var randomAccessStream = stream.AsRandomAccessStream())
    {
        Windows.Graphics.Imaging.BitmapDecoder decoder =
            await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(
                randomAccessStream);

        using (var softwareBitmap = await decoder.GetSoftwareBitmapAsync())
        {
            // ...
        }
    }
}
  • Related