使用相同图像时锁定图像导致通用 GDI+ 错误

Locked image causing Generic GDI+ Error when using same image

我有一个应用程序正在读取图像的牌照。我有一个简单的 UI,用户可以在其中 select 使用 FilePicker 扫描图像。

所以出现问题的场景

  1. Select 图片 A
  2. 扫描图片A --> 成功
  3. Select 图片 B
  4. 扫描图像B --> 成功
  5. Select 图片 A
  6. 扫描图像 A --> 失败

我收到错误

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

我正在使用 WPF,因此图像组件使用 SourceImage 作为源。然后我进行转换。我找不到任何可以转换的东西 SourceImage --> SoftwareBitmap 所以我使用 Bitmap 作为 proxy object

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

代码示例

文件选择器

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;
            }

        }

转换为位图

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;

转换为 SoftwareBitmap 和 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";
            }

此处出现错误newBitmap.Save(stream.AsStream(), ImageFormat.Tiff); //choose the specific image format by your own bitmap source

我在网上阅读了有关此错误的信息,似乎某处可能有锁,但我不知道在哪里...我尝试处理所有可能的图像,我用 using 语句包装了所有内容。没有任何效果...

如有任何想法、建议,我们将不胜感激!

谢谢

您可以通过从单个 MemoryStream 创建两个位图来简化您的代码。将 stream.AsRandomAccessStream() 传递给 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())
        {
            // ...
        }
    }
}