web-dev-qa-db-ja.com

Image.Save(..)は、メモリストリームが閉じられているため、GDI +例外をスローします

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

これはコードです:

[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.
}

ストリームを閉じた状態で画像を保存するにはどうすればよいですか?画像を保存した後、ストリームを閉じることを忘れずに開発者に頼ることはできません。実際、開発者には、イメージがメモリストリームを使用して生成されたというNO IDEA)があります(他のコードで発生するため)。

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

103
Pure.Krome

MemoryStreamであるため、ストリームを閉じる必要はありませんneed-しなくても悪いことは起こりませんが、明らかにとにかく使い捨てのものは処分してください。 (これについて詳しくは this question をご覧ください。)

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

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

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

160
Jon Skeet

GDI +で一般的なエラーが発生しました。誤った保存パス!それに気づくために半日かかった。そのため、画像も保存するためにパスを再確認してください。

87
Houman

おそらく、C:\ Tempディレクトリが存在しない場合、ストリームがまだ存在していても、この例外がスローされることに言及する価値があります。

14
Rojzik

私は同じ問題を抱えていましたが、実際には、アプリケーションがCにファイルを保存する権限を持っていなかったためです。「D:\ ..」に変更すると、画像が保存されました。

4
Morad Aktam

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

画像の描画時: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");
    }
2
Brian Low

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

2
Jay K

ビットマップの別のコピーを作成しようとすることができます:

using (var memoryStream = new MemoryStream())
{
    // write to memory stream here

    memoryStream.Position = 0;
    using (var bitmap = new Bitmap(memoryStream))
    {
        var bitmap2 = new Bitmap(bitmap);
        return bitmap2;
    }
}
1
Yuri Perekupko

実行していた自動化されたテストが、存在しないフォルダーにスナップショットを保存しようとしていたため、このエラーが発生していました。フォルダーを作成した後、エラーが解決しました

1
P.Lisa

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

1
S.Roshanth

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

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;
}
0
BogdanRB

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

C:\Program Files (x86)\some_directory

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

0
Ali Ezzat Odeh

私のコードを動作させる奇妙な解決策。ペイントで画像を開き、同じ形式(.jpg)の新しいファイルとして保存します。次に、この新しいファイルで試してみてください。ファイルが何らかの形で破損する可能性があることを明確に説明しています。これは、コードに他のすべてのバグが修正されている場合にのみ役立ちます

0
Vinothkumar

私にとって、以下のコードは、MemoryStreamに保存する行でA generic error occurred in GDI+でクラッシュしました。コードはWebサーバーで実行されていたため、サイトを実行していたアプリケーションプールを停止および開始することで解決しました。

GDI +の内部エラーである必要があります

    private static string GetThumbnailImageAsBase64String(string path)
    {
        if (path == null || !File.Exists(path))
        {
            var log = ContainerResolver.Container.GetInstance<ILog>();
            log.Info($"No file was found at path: {path}");
            return null;
        }

        var width = LibraryItemFileSettings.Instance.ThumbnailImageWidth;

        using (var image = Image.FromFile(path))
        {
            using (var thumbnail = image.GetThumbnailImage(width, width * image.Height / image.Width, null, IntPtr.Zero))
            {
                using (var memoryStream = new MemoryStream())
                {
                    thumbnail.Save(memoryStream, ImageFormat.Png); // <= crash here 
                    var bytes = new byte[memoryStream.Length];
                    memoryStream.Position = 0;
                    memoryStream.Read(bytes, 0, bytes.Length);
                    return Convert.ToBase64String(bytes, 0, bytes.Length);
                }
            }
        }
    }
0
mortb

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

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

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

[〜#〜] edit [〜#〜]

CacheOptionプロパティについて聞いた後(@Nyergudsに感謝)私は解決策を見つけました:したがって、ビットマップコンストラクターを使用する代わりに、CacheOptionBitmapCacheOption.OnLoad。(Image1を設定した後にUriを設定する必要がありますWpf Image要素です)

の代わりに

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 Image Caching

0
mkb