【问题标题】:Bitmap.Save "Generic Error"Bitmap.Save “一般错误”
【发布时间】:2012-11-14 15:15:18
【问题描述】:

当我运行我的应用程序时,我的脸上出现了以下错误“GDI+ 中发生了一般错误。” 我环顾四周,看到人们有类似的错误,但没有找到真正的解决方案,或者实施起来真的很痛苦。而那些没有得到解决方案的人也没有发布他们的代码。

所以我想我不妨试一试,并提出另一个关于如何修复此错误的线程。这是我的代码和错误

            Random r = new Random();
            DirectoryInfo di = new DirectoryInfo(folderbrowser.SelectedPath);
            FileInfo[] fi = di.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
            for (int i = 0; i < imageCount; i++)
            {
                int img1 = r.Next(imageCount);
                int img2 = r.Next(imageCount);
                while (img2 == img1)
                    img2 = r.Next(imageCount);
                pic1.Image = Image.FromFile(fi[img1].FullName);
                pic2.Image = Image.FromFile(fi[img2].FullName);
                Image i1 = pic1.Image;
                Image i2 = pic2.Image;
                Bitmap bitmap = new Bitmap(i1.Width + i2.Width, 1080);
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.DrawImage(i1, 0, 0);
                    g.DrawImage(i2, i2.Width, 0);
                }
                bitmap.Save(@"C:\TEST\Image_"+i.ToString());                   
            }

这是错误代码

System.Runtime.InteropServices.ExternalException was unhandled
  Message=A generic error occurred in GDI+.
  Source=System.Drawing
  ErrorCode=-2147467259
  StackTrace:
       at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
       at System.Drawing.Image.Save(String filename, ImageFormat format)
       at System.Drawing.Image.Save(String filename)
       at WallpaperMerger.Form1.btn_merge_Click(Object sender, EventArgs e) in C:\Users\PeppeJ\documents\visual studio 2010\Projects\WallpaperMerger\WallpaperMerger\Form1.cs:line 113
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at WallpaperMerger.Program.Main() in C:\Users\PeppeJ\documents\visual studio 2010\Projects\WallpaperMerger\WallpaperMerger\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

那么你们在 StackOverflow 有什么想法。我是和其他人一样,必须输入一个复杂得离谱的代码来解决这个问题,还是我犯了一个简单的错误,很容易纠正?

如果您想自己测试它是否有帮助,这里是Debug Build的链接

只需勾选“使用多个文件”,例如选择一个包含图像文件的文件夹(C:\Users\Public\Pictures\Sample Pictures)。点击合并。

我想补充一点,我在这个函数中使用了 Bitmap.Save,它可以完美运行。

        Bitmap bitmap = new Bitmap(pic1.Image.Width + pic2.Image.Width, 1080);
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.DrawImage(pic1.Image, 0, 0);
            g.DrawImage(pic2.Image, pic1.Image.Width, 0);
        }
        if (savepicfile.ShowDialog() == DialogResult.OK)
            bitmap.Save(savepicfile.FileName);

在上面的函数文件中是这样加载的:

    DialogResult result = pic1file.ShowDialog();
    if (result == DialogResult.OK)
        pic1.Image = Image.FromFile(pic1file.FileName);

还有一点值得一提的是“picX”是一个“System.Windows.Forms.PictureBox”对象。

【问题讨论】:

  • 您是否有权写入 C:\TEST?
  • 我有一个完全禁用 UAC 的管理员帐户 (W7),我可以创建文件。而且我也在别的地方使用了Bitmap.Save(我打算把这个函数加到mainpost中)
  • 什么 .NET 框架版本?

标签: c# windows forms bitmap gdi+


【解决方案1】:

我遇到了这个确切的问题,解决方法是将位图包装在 using 子句中;位图也需要处理

using (Bitmap bmp = new Bitmap()) 
{
    // Bitmap operation
}

【讨论】:

    【解决方案2】:

    我找到了答案,目录“\TEST\”不存在。当我创建它时,它完美无缺。

    【讨论】:

    • 遇到了同样的问题。花了 1 小时才找到你的答案:-)
    【解决方案3】:

    根据我的经验,99% 的情况下,此错误是由以下任一问题引起的:

    1. 您没有写入文件的权限。
    2. 您尝试写入的文件已被另一个进程锁定。

    我偶尔会遇到这种情况:

    • 我正在绘制带有零点的 GraphicPath。
    • 我不是处置我的 GDI+ 对象的财产。 (可能与上述选项 2 有关)

    我会先检查前两件事。如果可以排除这种情况,我可以看到您在提供的代码中没有正确处理一些对象的位置。我会把它清理干净。如果您不应该调用 Dispose(),则 GDI+ 与 .NET 的 GC 并不是特别合作。

            var r = new Random();
            var di = new DirectoryInfo(folderbrowser.SelectedPath);
            var fi = di.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
            for (var i = 0; i < imageCount; i++)
            {
                var img1 = r.Next(imageCount);
                var img2 = r.Next(imageCount);
                while (img2 == img1) 
                {
                    img2 = r.Next(imageCount);
                }
                pic1.Image = Image.FromFile(fi[img1].FullName);
                pic2.Image = Image.FromFile(fi[img2].FullName);
                var i1 = pic1.Image;
                var i2 = pic2.Image;
                using (var bitmap = new Bitmap(i1.Width + i2.Width, 1080))
                using (var g = Graphics.FromImage(bitmap))
                {
                    g.DrawImage(i1, 0, 0);
                    g.DrawImage(i2, i2.Width, 0);
                    bitmap.Save(@"C:\TEST\Image_"+i.ToString());
                }                   
            }
    

    编辑:更多想法(嗯,确实澄清了上面的第 2 点)...

    • 如果您的应用中有 PictureBox 或其他控件引用您尝试写入的 C:\TEST 目录中的图像,您会看到此错误。
    • 如果您有其他代码读取您尝试写入的图像,您会看到此错误。
    • 如果外部进程(例如您的 IDE、图像查看器/编辑器等)打开了文件,您会看到此错误。

    调试思路:

    • 尝试在 Save 调用上设置断点。当您找到它时,请使用此处的提示找出可能正在访问该文件的进程:How do I find out which process is locking a file using .NET?
    • 先尝试删除文件,看看是否允许您保存不是他们的文件。
    • 尝试在您正在写入的目录上为“所有人”设置完全权限(但不要这样)
    • 确保您尝试保存的图像的宽度是大于零的数字。我注意到您正在以编程方式进行设置。
    • 确保您要保存的图像的宽度不会太大(也许您遇到了内存问题?)

    【讨论】:

    • 这看起来和“akatakritos”建议的没什么不同,我还是试过了,但没什么区别。
    • 看起来没什么不同?也许你跳过了第一部分。此错误在 GDI+ 开发和真正的 PITA 故障排除中很常见。就像我上面说的,很有可能是权限问题或文件被“某些东西”锁定的问题(另一个进程?当前应用程序中的竞争条件?)。当一切都失败时,是时候重写一段代码了。
    • 我复制粘贴它是为了很好的衡量标准,我非常怀疑它与权限相关,而是你第二次提到的。再次查看 OP,我用一些可能有帮助的信息对其进行了编辑。
    • 还有其他东西可以访问C:\TEST\whatever 中的文件吗?有什么吗?你的应用程序? IDE?任何事物?如果在该行设置断点,然后在 Visual Studio 的“立即”窗口中进行保存,是否仍然出现错误?
    • 另外,删除所有现有文件,看看是否仍然出现错误。
    【解决方案4】:

    在处理 Graphics 对象之前尝试执行 bitmap.Save:

    Bitmap bitmap = new Bitmap(i1.Width + i2.Width, 1080);
    using (Graphics g = Graphics.FromImage(bitmap))
    {
        g.DrawImage(i1, 0, 0);
        g.DrawImage(i2, i2.Width, 0);
        bitmap.Save(@"C:\TEST\Image_"+i.ToString()); 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-26
      • 1970-01-01
      • 2017-05-04
      • 2011-08-14
      • 2010-12-20
      • 2016-07-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多