使用相同图像时锁定图像导致通用 GDI+ 错误
Locked image causing Generic GDI+ Error when using same image
我有一个应用程序正在读取图像的牌照。我有一个简单的 UI,用户可以在其中 select 使用 FilePicker 扫描图像。
所以出现问题的场景
- Select 图片 A
- 扫描图片A --> 成功
- Select 图片 B
- 扫描图像B --> 成功
- Select 图片 A
- 扫描图像 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())
{
// ...
}
}
}
我有一个应用程序正在读取图像的牌照。我有一个简单的 UI,用户可以在其中 select 使用 FilePicker 扫描图像。
所以出现问题的场景
- Select 图片 A
- 扫描图片A --> 成功
- Select 图片 B
- 扫描图像B --> 成功
- Select 图片 A
- 扫描图像 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())
{
// ...
}
}
}