繁体   English   中英

在生成条码时修复“GDI+ 中发生一般错误”

[英]Fixing "Generic error occurred in GDI+" while generating a Barcode

我正在用 C# 编写条形码生成器我可以将条形码生成为位图,并可以在图片框(WindowsForms)中显示它们。 另一方面,我无法将条形码保存为 gif 或 jpeg 文件。 我的条形码是位图文件,这是我的代码

Bitmap barCode = CreateBarCode("*"+txtBarCodeStr.Text+"*");
barCode.Save(@"C:\barcode.gif", ImageFormat.gif);
picBox.Image = barCode;            
MessageBox.Show("Created");

我得到以下异常; GDI+ 中出现一般错误。

注意:标题具有误导性,因为没有描述与创建条形码相关的问题,而是关于保存图像/位图。 我只能假设赏金提供者 Puthiyedath 先生有同样的错误,因为没有提供进一步的信息。


generic error occurred in GDI+问题中generic error occurred in GDI+generic error occurred in GDI+通常意味着以下两种情况之一:
A) 您正在尝试写入已打开位图图像的文件。 MSDN

不允许将图像保存到构建它的同一文件中,并引发异常。

因此,如果您在应用程序的其他地方有从文件创建的位图,则在位图被释放之前,您无法将其保存回同一个文件。 显而易见的解决方案是创建一个新的位图并保存它。

B) 您可能无权访问该文件夹/文件

这是更有可能出现的问题,因为根据操作系统、安全设置、权限等,可能不允许对引导驱动器根文件夹中的文件执行文件 IO(如 OP 的示例代码中所示)。

在下面的代码中,如果我尝试保存到"C:\\ziggybarcode.gif"而不是\\Temp文件夹,则什么也不会发生 也不例外,但也不会创建图像。 在不同的条件下可能会导致异常,但通常这些似乎被报告为通用错误。 解决方案:不要将根文件夹用于文件。 Users\\USERNAME\\...仅用于此目的。

C) 文件夹/文件名可能不合法

如果文件名在代码中被人为设计,则可能是该文件或路径是非法的。 使用文字、合法的路径(例如@"C:\\Temp\\mybarcode.gif" (对于 VB,省略@ )来测试它。

使用Path.Combine()构造合法路径; 并确保文件名不包含非法字符。


另一个有时会出现并且可能会引起兴趣的异常Out Of Memory Exception 这通常意味着图像格式有问题。 我有几个应用程序在图像上做了很多工作,但发现跟踪格式或假设图像可以在任何给定机器上保存为特定格式是有问题的。 条码生成器可能有类似的问题。

对于简单的应用程序或仅处理单一标准格式的应用程序,简单的Bitmap.Save方法通常会很好:

myBmp.Save(@"C:\Temp\mybarcode.gif", ImageFormat.Gif);

但是当您的应用程序处理不同的格式时,最好对图像进行显式编码:

public static bool SaveImageFile(string fileName, ImageFormat format, Image img, 
              Int64 quality)
{
    ImageCodecInfo codec = GetEncoder(format);
    EncoderParameter qParam = new EncoderParameter(Encoder.Quality, quality);

    EncoderParameters encoderParams = new EncoderParameters(1);
    encoderParams.Param[0] = qParam;
    try
    {
        img.Save(fileName, codec, encoderParams);
        return true;
    }
    catch
    {
        return false;
    }
}

private static ImageCodecInfo GetEncoder(ImageFormat format)
{
    var codecs = ImageCodecInfo.GetImageDecoders();
    foreach (var codec in codecs)
    {
        if (codec.FormatID == format.Guid)
        {
            return codec;
        }
    }
    return null;
}

将它们放在 DLL 中或使它们扩展,它们变得同样易于使用:

SaveImageFile(@"c:\Temp\myBarCode.gif",
                  ImageFormat.Gif, myBmp, 100);

特别是在处理 JPG 时,管理压缩/质量参数变得特别容易。 我并不是说这是首选方法,只是通过显式编码图像在复杂应用程序中遇到的问题要少得多。

创建条码 GIF 的测试代码

private void button1_Click(object sender, EventArgs e)
{
    Bitmap bmp = CreateBarcode("Ziggy12345");
    this.pb.Image = bmp;

    try { 
    // save to root of boot drive
    // does nothing on my system: no Error, No File
     bmp.Save(@"C:\zBarCodeDIRECT.gif", ImageFormat.Gif);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    // save BMP to file
    SaveImageFile(@"c:\Temp\zBarCodeBITMAP.gif",
                      ImageFormat.Gif, bmp, 100);

    // save PicBox image
    SaveImageFile(@"c:\Temp\zBarCodePICBOX.gif",
                ImageFormat.Gif, this.pb.Image, 100);

    // Try to save to same file while a bmp is open on it
    Bitmap myBmp = (Bitmap)Image.FromFile(@"c:\Temp\zBarCodeBITMAP.gif");
    // A generic Error in GDI
    myBmp.Save(@"c:\Temp\zBarCodeBITMAP.gif", ImageFormat.Gif);
}

最后一个失败并显示Generic GDI error即使它看起来应该是 IO 或 UnAuthorizedAccess 相关异常。

输出:

在此处输入图片说明在此处输入图片说明

由于上述原因和代码注释中的原因,第一张和最后一张图像不会保存。

我以前遇到过这个问题,我能够使用中间位图对象来解决它,如下所示:

Bitmap barCode = CreateBarCode("*"+txtBarCodeStr.Text+"*");

//Use an intermediate bitmap object
Bitmap bm = new Bitmap(barCode);

bm.Save(@"C:\barcode.gif", ImageFormat.gif);
picBox.Image = barCode;            
MessageBox.Show("Created");

我在这里找到了这个解决方案/解决方法

原因是因为“您正在尝试写入一个已经打开了位图图像的文件”,正如前面提到的@Plutonix。

Gif 是一种索引调色板格式。

将其保存为用于创建Bitmap实例的兼容格式。

你的问题是权限。 允许网络服务完全访问您保存文件的路径,看看是否有帮助

祝你好运!

我找到了一个简单的解决方案:

  1. 在解决方案中创建一个文件夹,例如,我在解决方案(项目内部)中创建了模板文件夹。
  2. 然后尝试使用 Server.MapPath 将文件保存到该文件夹​​中,例如Bitmap.Save(HttpContext.Current.Server.MapPath("/Template/3777.jpeg"), System.Drawing.Imaging.ImageFormat.Jpeg);
  3. 最后返回HttpContext.Current.Server.MapPath("/Template/3777.jpeg");
  4. 对我来说它运行良好,这种方法的优点是您要保存的文件,而不是保存到文件夹中,但是当您返回时,它会获取文件

你也可以试试Aspose.BarCode for .NET 该组件允许您从头开始创建条码并使用现有条码。 它为创建各种条码图像提供了极大的灵活性。 您可以将它用于任何类型的 .NET 应用程序。 请在你的最后尝试,看看这是否对你的场景有帮助。

披露:我在 Aspose 担任开发人员布道者。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM