2009-02-24 14 views
7

Básicamente estoy tratando de hacer una simple imagen en un controlador de ASP.NET:no puede procesar la imagen para HttpContext.Response.OutputStream

public void ProcessRequest (HttpContext context) 
{ 
    Bitmap image = new Bitmap(16, 16); 
    Graphics graph = Graphics.FromImage(image); 

    graph.FillEllipse(Brushes.Green, 0, 0, 16, 16); 

    context.Response.ContentType = "image/png"; 
    image.Save(context.Response.OutputStream, ImageFormat.Png); 
} 

Pero tengo la siguiente excepción:

System.Runtime.InteropServices.ExternalException: A generic error 
occurred in GDI+. 
    at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, 
    EncoderParameters encoderParams) 

El solución es usar esto en lugar de tener que escribir en la imagen OutputStream:

MemoryStream temp = new MemoryStream(); 
image.Save(temp, ImageFormat.Png); 
byte[] buffer = temp.GetBuffer(); 
context.Response.OutputStream.Write(buffer, 0, buffer.Length); 

Así que estoy curioso como ¿por qué la primera variante es problemática?

Editar: El HRESULT es 80004005 que es simplemente "genérico".

+0

En su solución utilizando GetBuffer(), debe usted dispone los objetos 'Image' y' MemoryStream' después de 'Response.OutputStream.Write'? – Pingpong

Respuesta

6

De hecho, el escritor debe intentar escribir correctamente en la secuencia.

Pero en su último código fuente, asegúrese de utilizar MemoryStream.ToArray() para obtener los datos correctos o, si no desea copiar los datos, utilice MemoryStream.GetBuffer() con MemoryStream.Length y no la longitud de la matriz devuelta.

GetBuffer devolverá el búfer interno utilizado por el MemoryStream, y su longitud generalmente es mayor que la longitud de los datos que se han escrito en la secuencia.

Esto evitará que envíe basura al final de la transmisión y no estropee un decodificador de imágenes estricto que no tolere la basura que se arrastra. (Y transfiera menos datos ...)

+0

¡Buena captura, gracias! MSDN dice más o menos lo mismo sobre GetBuffer(): http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer.aspx – Serguei

1

Creo que el problema es que Response.OutputStream no es compatible con la búsqueda. Para guardar un archivo PNG (o JPEG), el objeto de imagen debe poder escribir la salida de forma no secuencial. Si mal no recuerdo, hubiera funcionado si hubiera guardado la imagen como BMP, ya que ese formato de imagen se puede escribir sin buscar la transmisión.

+0

Lo intenté en realidad, pero el resultado fue el mismo. – Serguei

0

Ok Usé un contenedor para Stream (implementa Stream y pasa llamadas a un flujo subyacente) para determinar que Image.Save() llame a las propiedades de posición y longitud sin verificar CanSeek que devuelve falso. También intenta establecer Posición en 0.

Parece que se requiere un buffer intermedio.

3

Image.Save (secuencia de MemoryStream) requiere un objeto MemoryStream que se puede buscar. The context.Response.OutputStream es solo para reenvío y no admite búsquedas, por lo que necesita una transmisión intermedia. Sin embargo, no necesita el búfer de matriz de bytes. Usted puede escribir directamente a partir de la secuencia de memoria temporal en el context.Response.OutputStream:

/// <summary> 
/// Sends a given image to the client browser as a PNG encoded image. 
/// </summary> 
/// <param name="image">The image object to send.</param> 
private void SendImage(Image image) 
{ 
    // Get the PNG image codec 
    ImageCodecInfo codec = GetCodec("image/png"); 

    // Configure to encode at high quality 
    using (EncoderParameters ep = new EncoderParameters()) 
    { 
     ep.Param[0] = new EncoderParameter(Encoder.Quality, 100L); 

     // Encode the image 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      image.Save(ms, codec, ep); 

      // Send the encoded image to the browser 
      HttpContext.Current.Response.Clear(); 
      HttpContext.Current.Response.ContentType = "image/png"; 
      ms.WriteTo(HttpContext.Current.Response.OutputStream); 
     } 
    } 
} 

Un ejemplo de código totalmente funcional está disponible aquí:

Auto-Generate Anti-Aliased Text Images with ASP.NET

Cuestiones relacionadas