質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.53%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

Q&A

解決済

1回答

10675閲覧

c#でBitmap保存時の"GDI+ で汎用エラーが発生しました。"の対処法について

shimakon

総合スコア3

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

0グッド

0クリップ

投稿2022/02/01 06:04

編集2022/02/02 10:47

c#で、

・カメラから画像を取得しpictureBox1にライブ表示
・ボタンをクリックすると(checkBox1がTrueになると)その時の画像を保存する

というアプリを作ろうとしています。
ライブ表示はできるのですが、画像保存しようとすると_bmp.Saveの所で
"GDI+ で汎用エラーが発生しました。"というエラーが発生します。
エラー文で調べてみると、保存するbitmapを別のbitmap(_bmp)にコピーするとエラー回避できるとの情報があり試してみたのですがダメでした。
対処法をご存じの方がいましたら教えていただけませんでしょうか。

C#

1private void CameraImageEvent1(IGrabResult grabResult) 2{ 3 Bitmap bmp = GrabResultToBmp(grabResult); 4 // 画面更新 5 if (pictureBox1.IsDisposed) return; 6 if (pictureBox1.InvokeRequired) 7 { 8 pictureBox1.Invoke((MethodInvoker)(delegate 9 { 10 Bitmap old = pictureBox1.Image as Bitmap; 11 pictureBox1.Image = bmp; 12 if (old != null) 13 old.Dispose(); 14 })); 15 } 16 else 17 { 18 Bitmap old = pictureBox1.Image as Bitmap; 19 pictureBox1.Image = bmp; 20 if (old != null) 21 old.Dispose(); 22 } 23 24 // 画像保存 25 if (checkBox1.Checked) 26 { 27 if (checkBox1.InvokeRequired) 28 { 29 checkBox1.Invoke((MethodInvoker)(delegate 30 { 31 checkBox1.Checked = false; 32 })); 33 } 34 else 35 { 36 checkBox1.Checked = false; 37 } 38 39 pictureBox1.Invoke((MethodInvoker)(delegate 40 { 41 Bitmap _bmp = pictureBox1.Image as Bitmap; 42 pictureBox1.Image = bmp; 43 _bmp.Save(SavePath, ImageFormat.Bmp); 44 if (_bmp != null) 45 _bmp.Dispose(); 46 })); 47 } 48}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/02/01 06:11

「bitmap save gdi+ で汎用エラーが発生しました」でググるといろいろヒットするのですが見ましたか?
shimakon

2022/02/01 06:37

はい、調べた中では画像ファイルからbitmap読込⇒元の画像ファイルに上書き保存する時に同様のエラーが出るそうです。この原因は、読み込んだbitmapが存在する間は元の画像ファイルがロックされ続けるためで、新しいBitmapオブジェクトにコピーすれば解決出来ていました。 今回は画像ファイルから読み込んでいるわけではないのですが、一応pictureBox1.Imageを別のBitmapオブジェクトに入れて保存しようとしたところ同じエラーが出ました。
hihijiji

2022/02/01 08:36

代入するんじゃなくて新しいインスタンスを作らないとだめなんじゃないの?
KOZ6.0

2022/02/01 10:37

checkBox1.Checked のとき、_bmp と bmp は同じインスタンスになっていませんか?
guest

回答1

0

ベストアンサー

提示されたコードからプログラムのコルーチンを除いて整理すると

C#

1Bitmap old = pictureBox1.Image as Bitmap; 2pictureBox1.Image = bmp; 3if (old != null) 4 old.Dispose(); 5if (checkBox1.Checked) { 6 Bitmap _bmp = pictureBox1.Image as Bitmap; 7 pictureBox1.Image = bmp; 8 _bmp.Save(SavePath, ImageFormat.Bmp); 9 if (_bmp != null) 10 _bmp.Dispose(); 11}

になります。
つまり、_bmp と bmp は同じインスタンスなので、Dispose された Bitmap を
PictureBox が画面に描画しようとしてエラーが起きています。

やりたいことを整理し、bmp を引数にしてメソッドを作ると

C#

1private void SaveImage(Bitmap bmp) { 2 Bitmap old = pictureBox1.Image as Bitmap; 3 pictureBox1.Image = bmp; 4 if (old != null) 5 old.Dispose(); 6 if (checkBox1.Checked) { 7 bmp.Save(SavePath, ImageFormat.Bmp); 8 } 9}

のようになるはずです。

これを使って、別スレッドから Invoke します。
pictureBox1 も checkBox1 も同じスレッドで作られているので
分けて考える必要はありません。

C#

1private void CameraImageEvent1(IGrabResult grabResult) { 2 Bitmap bmp = GrabResultToBmp(grabResult); 3 Action<Bitmap> saveImageAction = SaveImage; 4 pictureBox1.Invoke(saveImageAction, bmp); 5}

初心者のうちはコルーチンを使わず、きちんとメソッドにしましょう。

投稿2022/02/01 14:28

編集2022/02/01 14:31
KOZ6.0

総合スコア2597

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shimakon

2022/02/02 01:47

無事保存することが出来ました。分かりやすいコードで教えていただきありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.53%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問