117

画像として保存したいバイナリデータがあります。画像を保存しようとすると、画像の作成に使用されたメモリ ストリームが保存前に閉じられていた場合、例外がスローされます。これを行う理由は、画像を動的に作成しているためです..メモリストリームを使用する必要があります。

これはコードです:

[TestMethod]
public void TestMethod1()
{
    // Grab the binary data.
    byte[] data = File.ReadAllBytes("Chick.jpg");

    // Read in the data but do not close, before using the stream.
    Stream originalBinaryDataStream = new MemoryStream(data);
    Bitmap image = new Bitmap(originalBinaryDataStream);
    image.Save(@"c:\test.jpg");
    originalBinaryDataStream.Dispose();

    // Now lets use a nice dispose, etc...
    Bitmap2 image2;
    using (Stream originalBinaryDataStream2 = new MemoryStream(data))
    {
        image2 = new Bitmap(originalBinaryDataStream2);
    }

    image2.Save(@"C:\temp\pewpew.jpg"); // This throws the GDI+ exception.
}

ストリームを閉じた状態で画像を保存する方法について何か提案はありますか? 画像が保存された後、開発者がストリームを閉じることを覚えているとは言えません。実際、開発者は、イメージがメモリ ストリームを使用して生成されたことを認識していません (別のコードで発生するため)。

私は本当に混乱しています:(

4

17 に答える 17

184

これは MemoryStream であるため、実際にストリームを閉じる必要はありません。閉じなくても問題はありませんが、いずれにせよ使い捨て可能なものはすべて破棄することをお勧めします。(詳細については、この質問を参照してください。)

ただし、ビットマップを破棄する必要があります。これにより、ストリームが閉じられます。基本的に、Bitmap コンストラクターにストリームを与えると、そのストリームを "所有" するので、閉じないでください。そのコンストラクターのドキュメントが言うように:

Bitmap の存続期間中、ストリームを開いたままにしておく必要があります。

ビットマップを破棄するときにストリームを閉じることを約束するドキュメントは見つかりませんが、かなり簡単に確認できるはずです。

于 2008-12-03T07:12:05.967 に答える
103

GDI+ で一般的なエラーが発生しました。間違った保存パス が原因である可能性もあります! それに気付くのに半日かかった。そのため、画像を保存するパスも再確認してください。

于 2012-04-03T21:14:35.657 に答える
14

C:\Temp ディレクトリが存在しない場合、ストリームがまだ存在していても、この例外がスローされることに注意してください。

于 2011-10-25T22:06:39.600 に答える
4

ビットマップをコピーします。ビットマップの存続期間中、ストリームを開いたままにしておく必要があります。

画像の描画時: System.Runtime.InteropServices.ExternalException: GDI で一般的なエラーが発生しました

    public static Image ToImage(this byte[] bytes)
    {
        using (var stream = new MemoryStream(bytes))
        using (var image = Image.FromStream(stream, false, true))
        {
            return new Bitmap(image);
        }
    }

    [Test]
    public void ShouldCreateImageThatCanBeSavedWithoutOpenStream()
    {
        var imageBytes = File.ReadAllBytes("bitmap.bmp");

        var image = imageBytes.ToImage();

        image.Save("output.bmp");
    }
于 2010-03-31T18:55:04.353 に答える
2

このエラーは、Citrix から試していたときに発生しました。画像フォルダはサーバーの C:\ に設定されており、権限がありません。画像フォルダーが共有ドライブに移動されると、エラーはなくなりました。

于 2015-01-15T19:40:09.600 に答える
1

GDI+ で一般的なエラーが発生しました。画像保存パスの問題が原因で発生する可能性があります。保存パスが長すぎるためにこのエラーが発生しました。最初に画像を最短パスに保存し、長いパス処理技術を使用して正しい場所に移動することでこれを修正しました。

于 2014-02-07T08:07:01.273 に答える
0

画像をパスに保存しようとしたときにも表示されました

C:\Program Files (x86)\some_directory

.exe管理者として実行するために実行されませんでした。これが同じ問題を抱えている人にも役立つことを願っています。

于 2017-03-27T15:31:29.223 に答える
0

このコードを試してください:

static void Main(string[] args)
{
    byte[] data = null;
    string fullPath = @"c:\testimage.jpg";

    using (MemoryStream ms = new MemoryStream())
    using (Bitmap tmp = (Bitmap)Bitmap.FromFile(fullPath))
    using (Bitmap bm = new Bitmap(tmp))
    {
        bm.SetResolution(96, 96);
        using (EncoderParameters eps = new EncoderParameters(1))
        {   
            eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
            bm.Save(ms, GetEncoderInfo("image/jpeg"), eps);
        }

        data = ms.ToArray();
    }

    File.WriteAllBytes(fullPath, data);
}

private static ImageCodecInfo GetEncoderInfo(string mimeType)
{
        ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();

        for (int j = 0; j < encoders.Length; ++j)
        {
            if (String.Equals(encoders[j].MimeType, mimeType, StringComparison.InvariantCultureIgnoreCase))
                return encoders[j];
        }
    return null;
}
于 2018-07-30T16:24:59.830 に答える
0

WPF アプリで簡単な画像編集をしようとしたときに、このエラーに遭遇しました。

Image 要素の Source をビットマップに設定すると、ファイルが保存されなくなります。Source=null を設定しても、ファイルが解放されないようです。

画像を画像要素のソースとして使用することは決してないので、編集後に上書きすることができます!

編集

CacheOption プロパティについて聞いた後 (@Nyerguds のおかげで) 解決策を見つけました。したがって、Bitmap コンストラクターを使用する代わりに、設定後に Uri を設定する必要がありCacheOption BitmapCacheOption.OnLoadます (Image1以下は WpfImage要素です) 。

それ以外の

Image1.Source = new BitmapImage(new Uri(filepath));

使用する:

var image = new BitmapImage();
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(filepath);
image.EndInit();
Image1.Source = image;

これを参照してください:WPF画像キャッシュ

于 2018-03-16T08:25:17.883 に答える