3

アプリケーションを実行すると、「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」オブジェクトです。

4

4 に答える 4

5

私の経験では、99% の確率で、このエラーは次のいずれかの問題が原因で発生します。

  1. ファイルを書き込む権限がありません。
  2. 書き込もうとしているファイルは、別のプロセスによってロックされています。

時折、次のようなときに遭遇しました。

  • ポイントがゼロの GraphicPaths を描画しています。
  • 私は自分の GDI+ オブジェクトをプロパティで処分しているわけではありません。(上記のオプション 2 に関連している可能性があります)

最初に最初の 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番の明確化)...

  • C:\TEST書き込もうとしているディレクトリ内の画像を参照する PictureBox またはその他のコントロールがアプリ内にある場合、このエラーが表示されることがあります。
  • 書き込もうとしている画像を読み取る他のコードがある場合、このエラーが表示されます。
  • IDE、画像ビューア/エディタなどの外部プロセスでファイルが開かれている場合、このエラーが表示されます。

デバッグのアイデア:

  • Save 呼び出しにブレークポイントを設定してみてください。到達したら、ここにあるヒントを使用して、ファイルにアクセスしている可能性のあるプロセスを特定します。.NET を使用してファイルをロックしているプロセスを確認するにはどうすればよいですか
  • 最初にファイルを削除してみて、自分のものでない場合に保存できるかどうかを確認してください。
  • 書き込み先のディレクトリで「Everyone」に完全なアクセス許可を設定してみてください (ただし、このままにしないでください)。
  • 保存しようとしている画像の幅がゼロより大きい数値であることを確認してください。プログラムで設定していることに気付きました。
  • 保存しようとしている画像の幅がとてつもなく大きくないことを確認してください (メモリの問題が発生している可能性があります)。
于 2012-11-27T03:28:24.587 に答える
2

答えが見つかりました。ディレクトリ「\TEST\」は存在しませんでした。作成したところ、問題なく動作しました。

于 2012-11-27T14:23:40.363 に答える
1

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()); 
}
于 2012-11-27T03:27:30.650 に答える