简体   繁体   English

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

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

I am writing a barcode generator in C# I can generate barcodes as bitmaps and can show them in a Picturebox(WindowsForms).我正在用 C# 编写条形码生成器我可以将条形码生成为位图,并可以在图片框(WindowsForms)中显示它们。 On the other hand I could not save my barcode as a gif or jpeg file.另一方面,我无法将条形码保存为 gif 或 jpeg 文件。 My barcode is a bitmap file and here is my code我的条形码是位图文件,这是我的代码

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

I get the following exception;我得到以下异常; A generic error occurred in GDI+. GDI+ 中出现一般错误。

Note: the title is misleading since no problem relating to creating BarCodes is described, instead it is about saving images/bitmaps.注意:标题具有误导性,因为没有描述与创建条形码相关的问题,而是关于保存图像/位图。 I can only assume Mr Puthiyedath, the bounty provider, is having the same error since no further information is provided.我只能假设赏金提供者 Puthiyedath 先生有同样的错误,因为没有提供进一步的信息。


The generic error occurred in GDI+ problem usually means one of two things: generic error occurred in GDI+问题中generic error occurred in GDI+generic error occurred in GDI+通常意味着以下两种情况之一:
A) You are trying to write to a file which already has a bitmap image open on it. A) 您正在尝试写入已打开位图图像的文件。 FromMSDN :MSDN

Saving the image to the same file it was constructed from is not allowed and throws an exception.不允许将图像保存到构建它的同一文件中,并引发异常。

So, if you have a bitmap elsewhere in the app created from a file, you cannot save back to that same file until the bitmap is disposed.因此,如果您在应用程序的其他地方有从文件创建的位图,则在位图被释放之前,您无法将其保存回同一个文件。 The obvious solution is to create a new bitmap and save it.显而易见的解决方案是创建一个新的位图并保存它。

B) You may not have access to the folder/file B) 您可能无权访问该文件夹/文件

This is the more likely problem because performing File IO to a file in the root folder of the boot drive (as in the sample code by the OP), may be disallowed depending on the OS, security settings, permissions etc etc etc.这是更有可能出现的问题,因为根据操作系统、安全设置、权限等,可能不允许对引导驱动器根文件夹中的文件执行文件 IO(如 OP 的示例代码中所示)。

In the code below, if I try to save to "C:\\ziggybarcode.gif" rather than the \\Temp folder, nothing happens .在下面的代码中,如果我尝试保存到"C:\\ziggybarcode.gif"而不是\\Temp文件夹,则什么也不会发生 There is no exception but no image is created either.也不例外,但也不会创建图像。 Under different conditions an exception can result, but often these seem to be reported as the Generic Error.在不同的条件下可能会导致异常,但通常这些似乎被报告为通用错误。 Solution: Don't use the root folder for files.解决方案:不要将根文件夹用于文件。 Users\\USERNAME\\... is intended for just this purpose. Users\\USERNAME\\...仅用于此目的。

C) The folder/file name may not be legal C) 文件夹/文件名可能不合法

If the filename is contrived in code, it may be that the file or path is illegal.如果文件名在代码中被人为设计,则可能是该文件或路径是非法的。 Test this using a literal, legal path such as @"C:\\Temp\\mybarcode.gif" (omit the @ for VB).使用文字、合法的路径(例如@"C:\\Temp\\mybarcode.gif" (对于 VB,省略@ )来测试它。

Use Path.Combine() to construct a legal path;使用Path.Combine()构造合法路径; and be sure the filename does not contain illegal characters.并确保文件名不包含非法字符。


One other exception which sometimes comes up, and may be of interest, is Out Of Memory Exception .另一个有时会出现并且可能会引起兴趣的异常Out Of Memory Exception This usually means there is a problem with the image format.这通常意味着图像格式有问题。 I have a couple of apps that do a lot of work on images and found it was problematic tracking the format or assuming that an image can be saved to a particular format on any given machine .我有几个应用程序在图像上做了很多工作,但发现跟踪格式或假设图像可以在任何给定机器上保存为特定格式是有问题的。 A BarCode generator might have a similar issue.条码生成器可能有类似的问题。

For simple apps or ones which only deal with a single, standard format, the simple Bitmap.Save method will often be fine:对于简单的应用程序或仅处理单一标准格式的应用程序,简单的Bitmap.Save方法通常会很好:

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

But when your app is juggling different formats, it might be better to explicitly encode the image:但是当您的应用程序处理不同的格式时,最好对图像进行显式编码:

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

Put them in a DLL or make them extensions, and they become equally simple to work with:将它们放在 DLL 中或使它们扩展,它们变得同样易于使用:

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

Particularly when working with JPGs, it becomes especially easy to manage the compression/quality parameter.特别是在处理 JPG 时,管理压缩/质量参数变得特别容易。 I am not saying this is the preferred method, just that I have had far fewer problems in complex apps by explicitly encoding images.我并不是说这是首选方法,只是通过显式编码图像在复杂应用程序中遇到的问题要少得多。

Test code to create a BarCode GIF:创建条码 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);
}

The last one fails with the Generic GDI error even though it seems like it should be an IO or UnAuthorizedAccess related exception.最后一个失败并显示Generic GDI error即使它看起来应该是 IO 或 UnAuthorizedAccess 相关异常。

Output:输出:

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

The first and last images do not save for the reasons explained above and in code comments.由于上述原因和代码注释中的原因,第一张和最后一张图像不会保存。

I had this problem before, and I was able to solve it using an intermediate bitmap object, something like this:我以前遇到过这个问题,我能够使用中间位图对象来解决它,如下所示:

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");

I found this solution/workaround here我在这里找到了这个解决方案/解决方法

The reason is because "You are trying to write to a file which already has a bitmap image open on it" as @Plutonix mentioned before.原因是因为“您正在尝试写入一个已经打开了位图图像的文件”,正如前面提到的@Plutonix。

Gif is an indexed pallete format. Gif 是一种索引调色板格式。

Save it in a compatible format what was used to create the Bitmap instance.将其保存为用于创建Bitmap实例的兼容格式。

your problem is permissions.你的问题是权限。 allow network service full access to the path you are saving the file and see if that helps允许网络服务完全访问您保存文件的路径,看看是否有帮助

good luck!祝你好运!

I found a simple solution for it:我找到了一个简单的解决方案:

  1. Create a folder in solution, for example, I created Template folder in solution(Inside the project).在解决方案中创建一个文件夹,例如,我在解决方案(项目内部)中创建了模板文件夹。
  2. Then try to save your file into that folder with Server.MapPath, for example, Bitmap.Save(HttpContext.Current.Server.MapPath("/Template/3777.jpeg"), System.Drawing.Imaging.ImageFormat.Jpeg);然后尝试使用 Server.MapPath 将文件保存到该文件夹​​中,例如Bitmap.Save(HttpContext.Current.Server.MapPath("/Template/3777.jpeg"), System.Drawing.Imaging.ImageFormat.Jpeg);
  3. And Finally return HttpContext.Current.Server.MapPath("/Template/3777.jpeg");最后返回HttpContext.Current.Server.MapPath("/Template/3777.jpeg");
  4. For me it worked well and advantage of this method is the file that you want to save,not saving into the folder but when you return,it fetches the file对我来说它运行良好,这种方法的优点是您要保存的文件,而不是保存到文件夹中,但是当您返回时,它会获取文件

You may try Aspose.BarCode for .NET as well.你也可以试试Aspose.BarCode for .NET This component allows you to create bar codes from scratch and work with existing bar codes.该组件允许您从头开始创建条码并使用现有条码。 It provides great flexibility to create a variety of bar code images.它为创建各种条码图像提供了极大的灵活性。 You can use it with any type of .NET application.您可以将它用于任何类型的 .NET 应用程序。 Please try at your end and see if this might help in your scenario.请在你的最后尝试,看看这是否对你的场景有帮助。

Disclosure: I work as a developer evangelist at Aspose.披露:我在 Aspose 担任开发人员布道者。

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

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