2008-12-03 12 views
90

tengo algunos datos binarios que quiero guardar como imagen. Cuando intento 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.Image.Save (..) arroja una excepción GDI + porque la secuencia de memoria está cerrada

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 a cómo podría guardar una imagen con la corriente 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 muy confundido :(

+13

Por favor, no utilizar imágenes por código como este, hace que sea más difícil para las personas para copiar el código con el fin de tratar de cambiar a un estado de trabajo. Lo editaré para usar la sintaxis de reducción. –

+0

Recibí este comentario de @HansPassant en otra [pregunta] (https://stackoverflow.com/questions/33331370/a-generic-error-occurred-in-gdi-exception-while-uploading-an-image-file) . Obtendrá esta excepción siempre que el códec tenga problemas para escribir el archivo. Una buena declaración de depuración para agregar es System.IO.File.WriteAllText (ruta, "prueba") antes de la llamada a Guardar(), verifica la capacidad básica para crear el archivo. Ahora obtendrá una buena excepción que le dice lo que hizo mal. –

Respuesta

143

Como es un MemoryStream, que realmente no necesidad de cerrar la corriente - nada malo va a pasar si no lo hace, aunque, obviamente, es una buena práctica para disponer . todo lo que sea desechable de todos modos (Ver this question para más información sobre esto.)

Sin embargo, debe ser disponer el mapa de bits -. y que cerrará la corriente de que, básicamente, una vez que dar el constructor de mapa de bits a un arroyo, que " posee "la secuencia y no debe cerrarla. Como the docs for that constructor diga:

Debe mantener la secuencia abierta para el de por vida del mapa de bits.

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

+2

¡increíble! esa es una gran respuesta Jon. Hace perfecto sentido (y me perdí un poco sobre la secuencia en los documentos). ¡Dos pulgares arriba! Informaré cuando lo haya dado una oportunidad :) –

+0

@Brian: Eso es muy extraño. Sin embargo, parece recordar que Image tiene una carcasa especial alrededor de las transmisiones de memoria. Podría estar equivocado, pero eso podría explicarlo. –

+0

¿Algún comentario sobre cómo hacer esto si queremos obedecer la regla CA2000? (msdn.microsoft.com/en-us/library/ms182289.aspx) –

1

Copie el mapa de bits. Debes mantener la transmisión abierta durante toda la vida del mapa de bits.

When drawing an image: System.Runtime.InteropServices.ExternalException: A generic error occurred in 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"); 
    } 
+1

Esto no funciona exactamente; en su código en ToImage(), la "imagen" local tendrá correctamente un .RawFormat de lo que sea que fue el archivo original (jpeg o png, etc.), mientras que el valor de retorno de ToImage() tendrá inesperadamente .RawFormat MemoryBmp. –

12

Tal vez vale la pena mencionar que si el directorio C: \ Temp no existe, sino que también lanzar esta excepción, incluso si su flujo es todavía existe.

+0

+1 Esta excepción parece ocurrir en una variedad de escenarios. La ruta inválida es una que he encontrado hoy. –

+0

¡Hurra! Esto lo hizo por mí. –

75

Ocurrió un error genérico en GDI +. También puede resultar de ruta de guardado incorrecta! Me tomó medio día darme cuenta de eso. Así que asegúrese de haber verificado dos veces la ruta para guardar también la imagen.

+2

Me alegra haber visto esto, mi ruta era 'C \ Users \ mason \ Desktop \ pic.png'. ¡Faltan dos puntos! Hubiera pasado una eternidad antes de que me diera cuenta de eso. – mason

+1

¡Me salvaste el día! ¡He intentado varias cosas y tu comentario ha aclarado mi problema! ¡¡¡Un millón de gracias!!! – Saxophonist

+2

Incorrecto también significa que no existe una carpeta en la que desea guardar la imagen. – Roemer

1

Usted puede tratar de crear otra copia del mapa de bits: Se ha producido

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

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.

0

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 corregidos todos los errores

2

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

2

Se me ocurrió este error cuando estaba intentando con 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ó.

1

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 resuelto

0

También ha aparecido conmigo cuando yo estaba tratando de guardar una imagen en la trayectoria

C:\Program Files (x86)\some_directory

y la .exe no se ha ejecutado a ejecutar como administrador, Espero que esto pueda ayudar a alguien que también tiene el mismo problema.

0

Para mí, el código siguiente se bloqueó con A generic error occurred in GDI+ en la línea que guarda en 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<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); 
       } 
      } 
     } 
    } 
Cuestiones relacionadas