Guardar imagen en MemoryStream: error genérico de GDI+

Overview of my application: On the client side, a series of snapshots are taken with a webcam. On submit, I want the images to be converted to a byte array, and have that byte array sent to a service I have written.

My problem: I'm trying to save a single image to a MemoryStream, but it continues to break, spitting out the message, "Se produjo un error genérico en GDI+". Cuando profundizo, veo que se lanza la excepción cuando la posición del búfer de MemoryStream está en 54. Desafortunadamente, es un 1.2 mb photo. Here's the block of code:

// Create array of MemoryStreams
var imageStreams = new MemoryStream[SelectedImages.Count];
for (int i = 0; i < this.SelectedImages.Count; i++)
{   
    System.Drawing.Image image = BitmapFromSource(this.SelectedImages[i]);
    imageStreams[i] = new MemoryStream();
    image.Save(imageStreams[i], ImageFormat.Bmp); /* Error is thrown here! */
}

// Combine MemoryStreams into a single byte array (Threw this 
// in in case somebody has a better approach)
byte[] bytes = new byte[imageStreams.Sum(s => s.Length)];
for(int i = 0; i < imageStreams.Length; i++)
{
    bytes.Concat(imageStreams[i].ToArray());
}

And here is my BitmapFromSource method

// Converts a BitmapSource object to a Bitmap object
private System.Drawing.Image BitmapFromSource(BitmapSource source)
{
    System.Drawing.Image bitmap;

    using (MemoryStream ms = new MemoryStream())
    {
        BitmapEncoder encoder = new BmpBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(source));
        encoder.Save(ms);
        bitmap = new System.Drawing.Bitmap(ms);
    }
    return bitmap;
}

Mucho de lo que he leído sobre el error genérico GDI+ apunta a un problema de permisos, pero no veo cómo se aplicaría aquí, considerando que no estoy guardando en el sistema de archivos. Además, he visto que este error puede surgir debido al cierre de MemoryStream antes de que se guarde la imagen, pero tampoco veo cómo se aplicaría esto considerando que creo MemoryStream inmediatamente antes de guardar la imagen. Cualquier idea sería muy apreciada.

preguntado el 31 de julio de 12 a las 14:07

También por favor echa un vistazo a esto: stackoverflow.com/questions/1044085/… -

@MennanKara Tu enlace resolvió mi problema. Resulta que el mapa de bits debe copiarse en un nuevo mapa de bits antes de poder guardarlo. Parece redundante, pero funcionó. Publique su enlace como respuesta y lo aprobaré. -

2 Respuestas

I think your problem actually lies in your BitmapFromSource method.

Está creando una transmisión, luego crea un mapa de bits a partir de esa transmisión, luego desecha la transmisión y luego intenta guardar el mapa de bits en otra transmisión. Sin embargo, la documentación de la clase Bitmap dice:

Debe mantener la transmisión abierta durante la vida útil del mapa de bits.

En el momento en que viene a guardar ese mapa de bits, el mapa de bits ya está dañado porque ha desechado la transmisión original.

Ver: http://msdn.microsoft.com/en-us/library/z7ha67kw

Para solucionar esto (teniendo en cuenta que no he escrito el código y mucho menos lo he probado), cree el MemoryStream dentro del primer bucle for en su primer bloque de código y pase ese flujo de memoria a su método BitmapFromSource como un segundo parámetro.

Respondido 31 Jul 12, 15:07

+1 por señalar que MemoryStream se está cerrando en el método BitmapFromSource. Esto explica por qué es necesario copiar el mapa de bits antes de poder guardarlo. - Sr. Jones

Hay otra rareza en su código que me preocupa, ya que parece innecesaria. Parece que está abriendo un MemoryStream para crear su mapa de bits y luego guardar ese mapa de bits en otro MemoryStream. Puede que me esté perdiendo algo, pero ¿por qué no conservar el primer MemoryStream y almacenarlo en su matriz, en lugar de copiar el mapa de bits en un segundo flujo? - Chris

Otro punto de interés: la razón por la que su código original fallaba al escribir en la posición 54 del búfer es que ese es el tamaño del encabezado del mapa de bits. El código puede escribir el encabezado del archivo, pero luego falla al escribir el contenido real porque ya no podía leer la secuencia. - Chris

Esta es la respuesta más adecuada. No hubo necesidad de copiar el mapa de bits. - Sr. Jones

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.