Image.Save (..) arroja una excepción GDI + porque la secuencia de memoria está cerrada

Tengo algunos datos binarios que quiero guardar como imagen. Cuando bash guardar la imagen, arroja una excepción si la secuencia de memoria utilizada para crear la imagen se cerró antes del guardado. La razón por la que hago esto es porque estoy creando imágenes dinámicamente y, como tal, necesito usar un flujo de memoria.

este es el código:

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

¿Alguien tiene alguna sugerencia de cómo podría guardar una imagen con la secuencia cerrada? No puedo confiar en que los desarrolladores recuerden cerrar la secuencia después de guardar la imagen. De hecho, el desarrollador NO TENDRÍA NINGUNA IDEA de que la imagen se generó usando una secuencia de memoria (porque ocurre en algún otro código, en cualquier otro lugar).

Estoy realmente confundido 🙁

Como es un MemoryStream, realmente no necesita cerrar la transmisión; nada malo sucederá si no lo hace, aunque obviamente es una buena práctica desechar cualquier cosa desechable de todos modos. (Consulte esta pregunta para obtener más información sobre esto).

Sin embargo, debería deshacerse del bitmap, y eso cerrará la transmisión por usted. Básicamente, una vez que le das al constructor Bitmap una secuencia, “posee” la transmisión y no debes cerrarla. Como dicen los documentos para ese constructor :

Debes mantener la transmisión abierta durante toda la vida del bitmap.

No puedo encontrar ningún documento que prometa cerrar la secuencia cuando deseche el bitmap, pero debería poder verificarlo con bastante facilidad.

Se produjo un error genérico en GDI +. ¡También puede resultar de una ruta de guardado incorrecta ! Me tomó medio día darme cuenta de eso. Por lo tanto, asegúrese de haber verificado dos veces la ruta para guardar la imagen también.

Quizás vale la pena mencionar que si el directorio C: \ Temp no existe, también arrojará esta excepción incluso si la transmisión aún existe.

Copia el bitmap. Debes mantener la transmisión abierta durante toda la vida del bitmap.

Al dibujar una imagen: System.Runtime.InteropServices.ExternalException: se produjo un error genérico en 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"); } 

Tuve el mismo problema, pero en realidad la causa fue que la aplicación no tenía permiso para guardar los archivos en C. Cuando cambié a “D: \ ..” la imagen se ha guardado.

Se me ocurrió este error cuando estaba intentando de Citrix. La carpeta de la imagen se configuró en C: \ en el servidor, para lo cual no tengo privilegios. Una vez que la carpeta de imágenes se movió a una unidad compartida, el error desapareció.

Puede intentar crear otra copia de 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; } } 

Se produjo un error genérico en GDI +. Puede ocurrir debido a problemas de almacenamiento de rutas de imágenes, recibí este error porque mi ruta de almacenamiento es demasiado larga, lo arreglé guardando primero la imagen en una ruta más corta y moviéndola a la ubicación correcta con técnicas de manejo de rutas largas.

Recibí este error porque la prueba automática que estaba ejecutando intentaba almacenar instantáneas en una carpeta que no existía. Después de crear la carpeta, el error se resolvió

Una solución extraña que hizo que mi código funcionara. Abra la imagen en pintura y guárdela como un archivo nuevo con el mismo formato (.jpg). Ahora intenta con este nuevo archivo y funciona. Le explica claramente que el archivo puede estar dañado de alguna manera. Esto puede ayudar solo si su código tiene todos los otros errores corregidos

También apareció conmigo cuando estaba tratando de guardar una imagen en el camino

C:\Program Files (x86)\some_directory

y .exe no se ejecutó para ejecutarse como administrador, espero que esto pueda ayudar a alguien que también tenga el mismo problema.

Para mí, el código siguiente se bloqueó con A generic error occurred in GDI+ en la línea que guarda en un MemoryStream . El código se estaba ejecutando en un servidor web y lo resolví deteniendo e iniciando el grupo de aplicaciones que estaba ejecutando el sitio.

Debe haber habido algún error interno en GDI +

  private static string GetThumbnailImageAsBase64String(string path) { if (path == null || !File.Exists(path)) { var log = ContainerResolver.Container.GetInstance(); 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); } } } } 

Me encontré con este error cuando intentaba una simple edición de imágenes en una aplicación WPF.

Establecer el origen de un elemento de imagen en el bitmap impide el guardado de archivos. Incluso al configurar Source = null no parece liberar el archivo.

¡Ahora simplemente nunca uso la imagen como elemento de la Fuente de la Imagen, así que puedo sobrescribirlo después de la edición!

EDITAR

Después de enterarme de la propiedad CacheOption (Gracias a @Nyerguds) encontré la solución: entonces, en lugar de usar el constructor Bitmap, debo configurar el Uri después de establecer CacheOption BitmapCacheOption.OnLoad . ( Image1 continuación es el elemento Wpf Image )

En lugar de

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

Utilizar:

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

Ver esto: Almacenamiento en caché de imágenes WPF

Prueba este código:

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