programing

Image.Save (..)에서 메모리 스트림이 닫히기 때문에 GDI + 예외가 발생합니다.

nasanasas 2020. 8. 14. 07:52
반응형

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

누구든지 스트림을 닫은 상태에서 이미지를 저장할 수있는 방법에 대한 제안이 있습니까? 이미지가 저장된 후 스트림을 닫는 것을 기억하는 개발자에게 의존 할 수 없습니다. 사실, 개발자는 이미지가 메모리 스트림을 사용하여 생성되었다는 생각이 없습니다 (다른 코드에서 발생하기 때문에).

정말 혼란 스러워요 :(


MemoryStream이므로 스트림을 닫을 필요 가 없습니다. 그렇지 않으면 나쁜 일이 일어나지 않을 것입니다. 어쨌든 처분 할 수있는 것은 폐기하는 것이 좋습니다. (자세한 내용은 이 질문참조하십시오 .)

그러나 Bitmap을 폐기 해야 합니다. 그러면 스트림이 닫힙니다. 기본적으로 Bitmap 생성자에 스트림을 제공하면 스트림을 "소유"하고 닫으면 안됩니다. 해당 생성자에 대한 문서는 다음과 같이 말합니다.

Bitmap의 수명 동안 스트림을 열어 두어야합니다.

비트 맵을 처리 할 때 스트림을 닫을 것을 약속하는 문서를 찾을 수 없지만 상당히 쉽게 확인할 수 있습니다.


GDI +에서 일반 오류가 발생했습니다. 잘못된 저장 경로로 인해 발생할 수도 있습니다 ! 그것을 알아 차리는 데 반나절이 걸렸습니다. 따라서 이미지를 저장하기 위해 경로를 두 번 확인했는지 확인하십시오.


C : \ Temp 디렉토리가 존재하지 않으면 스트림이 여전히 존재하더라도이 예외가 발생한다는 점을 언급 할 가치가 있습니다.


나는 같은 문제가 있었지만 실제로 원인은 응용 프로그램이 C에 파일을 저장할 수있는 권한이 없었기 때문입니다. "D : \ .."로 변경하면 사진이 저장되었습니다.


비트 맵을 복사합니다. 비트 맵의 ​​수명 동안 스트림을 열어 두어야합니다.

이미지를 그릴 때 : 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");
    }

This error occurred to me when I was trying from Citrix. The image folder was set to C:\ in the server, for which I do not have privilege. Once the image folder was moved to a shared drive, the error was gone.


You can try to create another copy of bitmap:

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

A generic error occurred in GDI+. It can occur because of image storing paths issues,I got this error because my storing path is too long, I fixed this by first storing the image in a shortest path and move it to the correct location with long path handling techniques.


I was getting this error, because the automated test I was executing, was trying to store snapshots into a folder that didn't exist. After I created the folder, the error resolved


One strange solution which made my code to work. Open the image in paint and save it as a new file with same format(.jpg). Now try with this new file and it works. It clearly explains you that the file might be corrupted in someway. This can help only if your code has every other bugs fixed


It has also appeared with me when I was trying to save an image into path

C:\Program Files (x86)\some_directory

and the .exe wasn't executed to run as administrator, I hope this may help someone who has same issue too.


For me the code below crashed with A generic error occurred in GDI+on the line which Saves to a MemoryStream. The code was running on a web server and I resolved it by stopping and starting the Application Pool that was running the site.

Must have been some internal error in 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);
                }
            }
        }
    }

I came across this error when I was trying a simple image editing in a WPF app.

Setting an Image element's Source to the bitmap prevents file saving. Even setting Source=null doesn't seem to release the file.

Now I just never use the image as the Source of Image element, so I can overwrite after editing!

EDIT

After hearing about the CacheOption property(Thanks to @Nyerguds) I found the solution: So instead of using the Bitmap constructor I must set the Uri after setting CacheOption BitmapCacheOption.OnLoad.(Image1 below is the Wpf Image element)

Instead of

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

Use:

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

See this: WPF Image Caching


Try this code:

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

참고URL : https://stackoverflow.com/questions/336387/image-save-throws-a-gdi-exception-because-the-memory-stream-is-closed

반응형