2009-02-24 2 views
7

내가 ASP.NET 처리기에서 간단한 이미지를 렌더링하는 것을 시도하고있다 :는에 이미지를 렌더링 할 수 없습니다 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); 
} 

하지만 다음과 같은 예외가 얻을 :

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

을 해결책은 OutputStream에 이미지를 쓰는 대신에 이것을 사용하는 것입니다 :

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

그래서 저는 왜 첫 번째 변종이 문제가 되는가?

편집 : HRESULT는 단지 "일반"인 80004005입니다.

+0

GetBuffer()를 사용하여,해야합니다 당신은'Image.'와'MemoryStream' 객체를'Response.OutputStream.Write' 다음에 처분합니까? – Pingpong

답변

6

작가는 실제로 스트림에 올바르게 쓰려고해야합니다.

마지막 소스 코드에서 적절한 데이터를 가져 오려면 MemoryStream.ToArray()를 사용하고, 데이터를 복사하지 않으려면 MemoryStream.GetBuffer()를 MemoryStream.Length와 함께 사용하십시오 반환 된 배열의 길이가 아닙니다.

GetBuffer는 MemoryStream에서 사용하는 내부 버퍼를 반환하며 일반적으로 스트림에 기록 된 데이터의 길이보다 길다.

이렇게하면 스트림 끝에서 가비지를 보내지 않고 잔상 쓰레기를 허용하지 않는 일부 엄격한 이미지 디코더를 엉망으로 만들지 않습니다. (적은 데이터 전송 ...)

+0

좋은 캐치, 고마워! MSDN은 GetBuffer()에 대해 거의 동일한 내용을 말합니다 : http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer.aspx – Serguei

1

저는 Response.OutputStream이 검색을 지원하지 않는다고 생각합니다. PNG (또는 JPEG)를 저장하려면 이미지 객체가 비 연속적으로 출력을 쓸 수 있어야합니다. 올바르게 기억한다면 스트림을 찾지 않고 이미지 형식을 쓸 수 있기 때문에 이미지를 BMP로 저장하면 작동했을 것입니다.

+0

나는 그걸 실제로 시도했지만 그 결과는 똑같은 것으로 판명되었다. – Serguei

0

Ok ImageSave()가 false를 반환하는 CanSeek을 확인하지 않고 Position 및 Length 속성을 호출하는지 확인하기 위해 Stream 용 래퍼 (Stream 구현 및 호출을 기본 스트림으로 전달)를 사용했습니다. 또한 Position을 0으로 설정하려고 시도합니다.

중간 버퍼가 필요합니다.

3

Image.Save (MemoryStream stream)에는 검색 할 수있는 MemoryStream 객체가 필요합니다. context.Response.OutputStream은 전진 전용이며 탐색을 지원하지 않으므로 중간 스트림이 필요합니다. 그러나 바이트 배열 버퍼가 필요하지 않습니다. 당신은 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); 
     } 
    } 
} 

완전히 기능 코드 샘플은 여기에 있습니다 : 솔루션에

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