Image.Save()でのエラー

一見正しく書いたつもりでもImage.Save()で画像を保存するときに例外が発生することがあります。
特に、ExternalExceptionで"GDI+ で汎用エラーが発生しました。"というメッセージの場合は原因が掴みにくく、ハマることがあります。
複雑な原因の場合もありますが、単純な勘違いなどが原因のことが多いのでエラーが起こりやすいor私がハマったことのあるエラーをまとめてみました。


全て

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

が宣言済みとします。

読み込んだファイルを上書きするとき、ファイルがロックされているために起こるエラー

using (Image img = Image.FromFile(@"C:\test.bmp")) {
    img.Save(@"C:\test.bmp", ImageFormat.Bmp); //ExternalException: GDI+ で汎用エラーが発生しました。
}
using (FileStream fs = new FileStream(@"C:\test.bmp", FileMode.Open))
using (Image img = Image.FromStream(fs)) {
    img.Save(@"C:\test.bmp"); //ExternalException: GDI+ で汎用エラーが発生しました。
}
Image img;
using (Image imgSrc = Image.FromFile(@"C:\test.bmp")) {
    img = (Image)imgSrc.Clone(); //Clone()してみる
}
using (img) {
    img.Save(@"C:\test.bmp", ImageFormat.Bmp); //ExternalException: GDI+ で汎用エラーが発生しました。
}

これらの回避策として一端別のBitmapコピーしておき、元の画像が解放された後に上書きします。

Image img;
using (Image imgSrc = Image.FromFile(@"C:\test.bmp")) {
    img = new Bitmap(imgSrc);
}
using (img) {
    img.Save(@"C:\test.bmp", ImageFormat.Bmp); //OK
}

Image.FromStream()で指定したストリームが閉じているために起きるエラー

Image img;
using (FileStream fs = new FileStream(@"C:\test.bmp", FileMode.Open)) {
    img = Image.FromStream(fs);
}
img.Save(@"C:\test2.bmp"); //ExternalException: GDI+ で汎用エラーが発生しました。
Image img;
using (FileStream fs = new FileStream(@"C:\test.bmp", FileMode.Open))
using (Image imgTemp = Image.FromStream(fs)) {
    img = (Image)imgTemp.Clone(); //Clone()してみる
}
img.Save(@"C:\test.bmp", ImageFormat.Bmp); //ExternalException: GDI+ で汎用エラーが発生しました。

この場合も別のBitmapにコピーして回避できます。

Image img;
using (FileStream fs = new FileStream(@"C:\test.bmp", FileMode.Open))
using (Image imgSrc = Image.FromStream(fs)) {
    img = new Bitmap(imgSrc);
}
img.Save(@"C:\test.bmp", ImageFormat.Bmp); //OK