web-dev-qa-db-ja.com

画像を保存するときに一般的なGDI +エラーの理由を見つける方法は?

イメージをロードおよび保存するときに年齢に応じて機能するコードを持っていると、このコードを壊すone single imageがあることがわかりました。

const string i1Path = @"c:\my\i1.jpg";
const string i2Path = @"c:\my\i2.jpg";

var i = Image.FromFile(i1Path);
i.Save(i2Path, ImageFormat.Jpeg);

例外は次のとおりです。

System.Runtime.InteropServices.ExternalExceptionが発生しました

GDI +で一般的なエラーが発生しました。

system.Drawing.Image.Save(String filename、ImageCodecInfo encoder、EncoderParameters encoderParams)で
at System.Drawing.Image.Save(String filename、ImageFormat format)
at ...

私が見る限り、この画像について特別なことは何もありません。サイズは約250ピクセルで、たとえばで開くことができます。 Windows Image ViewerまたはPaint.NET:

enter image description here

(上記の画像は、Stack Overflowにアップロードされた後、エラーを生成しなくなったため、ここに元の画像 を入れました

私が発見したのは、 Saveメソッドを呼び出すと 、宛先イメージファイルがゼロバイトで作成されていることです。

何がエラーの原因なのか本当に分かりません。

私の質問:

  • .NETが画像を保存するのを妨げる特別なことを考えることができますか?
  • この種のエラーを絞り込む方法はありますか?
29
Uwe Keim

画像を保存するときにエラーを正確に引き起こした理由はまだわかりませんが、適用する回避策が見つかりました。

const string i1Path = @"c:\my\i1.jpg";
const string i2Path = @"c:\my\i2.jpg";

var i = Image.FromFile(i1Path);

var i2 = new Bitmap(i);
i2.Save(i2Path, ImageFormat.Jpeg);

つまり画像を Bitmap インスタンスに内部的にコピーし、元の画像の代わりにこの画像を保存することにより、エラーは消えました。

私はそれをコピーすることで、元のSave呼び出しが失敗する原因となった誤った部分が削除または正規化され、保存操作が成功できると仮定しています。

saved image i2.jpg

興味深いことに、そのように保存されたイメージは、元のソース(26 kB)よりもディスク上のファイル(16 kB)が小さくなります。

39
Uwe Keim

まず、目的のフォルダーに読み取り/書き込み権限があることを確認してください。許可を変更すると、この問題は解決しました。

15

解決策はこちらです。サーバー上のメモリを解放するには、イメージオブジェクトを破棄する必要があります。 use usingステートメントを試してください。サーバー上の宛先ディレクトリも存在することを確認してください。

7
Azarsa

その理由は、イメージが遅延してロードされ、保存しようとしてもロードプロセスがまだ終了していない可能性があります。

このブログ投稿 (質問でリンクした写真であなたがドイツ人であると仮定)で言われたことに従うことは、可能な解決策を提供します。また、 this SO question's 受け入れられた答えは、保存しようとしている画像ファイルがロックされているという事実によるものであることを示しています。

[〜#〜] edit [〜#〜]
Ulysses Alvesの場合、リンクされたブログエントリから:Image.FromFile()を使用して画像をロードすると、破棄されるまでロックされたままになります。これにより、Save()の呼び出しが防止されます。

pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg");
pictureBox1.Image.Save("C:\\test\\test2.jpg");

上記のコードはエラーをスローします。

動作させるには、画像をコピーする必要があります。次のコードが機能します。

pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg");
Image copy = pictureBox1.Image;
copy.Save("C:\\test\\test2.jpg")
5

同様のエラーに直面し、ファイルが実際に長さゼロで作成された(ファイルが表示されない場合は、最初に他の回答が示唆するようにフォルダに書き込む権限を確認してください) 。私のコードは少し異なりましたが(ファイルからではなくメモリから画像を読み取るためにstreamを使用します)、私の答えは同様の問題に直面している人にとって役立つと思います。

直観に反するように見えるかもしれませんが、画像を終了するまでメモリストリームを実際に破棄することはできません。

動作していません

Image patternImage;

using (var ms = new MemoryStream(patternBytes)) {
    patternImage = new Bitmap(ms);
}

patternImage.Save(patternFile, ImageFormat.Jpeg);

画像を処理するまで、ストリームを破棄しないでください。

[〜#〜] works [〜#〜]

using (var ms = new MemoryStream(patternBytes)) {
    patternImage = new Bitmap(ms);
    patternImage.Save(patternFile, ImageFormat.Jpeg);
}

誤解を招くもの:

  • エラーメッセージは実際には何も伝えない
  • 幅や高さなどの画像プロパティは表示できますが、保存できません
3
Mike Keskinov

私の解決策は、ファイルを保存する直前に一時コンテンツ(File.WriteAllText)を作成し、書き込むことでした

コードは次のとおりです

var i = Image.FromFile(i1Path);
File.WriteAllText(i2Path, "empty");  // <---- magic goes here
i.Save(i2Path, ImageFormat.Jpeg);

試してみてください

3
mr.baby123

プログラムで開く

const string i1Path = @"c:\my\i1.jpg";

const string i2Path = @"c:\my\i2.jpg";

var i = Image.FromFile(i1Path);

i.Save(i2Path, ImageFormat.Jpeg);

i.Dispose();
0
Konstant