8

基本的に、ASP.NET ハンドラーで単純な画像をレンダリングしようとしています。

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 で、これは単に「一般的」です。

4

4 に答える 4

6

ライターは、実際にストリームに適切に書き込む必要があります。

ただし、最後のソース コードでは、MemoryStream.ToArray() を使用して適切なデータを取得するか、データをコピーしたくない場合は、MemoryStream.GetBuffer() を長さではなく MemoryStream.Length と共に使用してください。返された配列の。

GetBuffer は、MemoryStream によって使用される内部バッファーを返します。その長さは、通常、ストリームに書き込まれたデータの長さよりも大きくなります。

これにより、ストリームの最後にガベージを送信することを回避でき、末尾のガベージを許容しない厳密な画像デコーダを台無しにすることもありません。(そして、転送するデータが少なくなります...)

于 2009-02-25T03:24:01.337 に答える
4

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

完全に機能するコード サンプルは、次の場所で入手できます。

ASP.NET でアンチエイリアス テキスト画像を自動生成する

于 2010-05-16T15:50:22.923 に答える
1

問題は、Response.OutputStream がシークをサポートしていないことだと思います。PNG (または JPEG) を保存するには、画像オブジェクトが出力をノンシーケンシャルに書き込める必要があります。私の記憶が正しければ、画像を BMP として保存すればうまくいったはずです。なぜなら、その画像形式はストリームをシークせずに書き込むことができるからです。

于 2009-02-24T18:01:58.580 に答える
0

OK、Stream のラッパーを使用して (Stream を実装し、呼び出しを基になるストリームに渡します)、Image.Save() が CanSeek をチェックせずに Position プロパティと Length プロパティを呼び出すことを確認しました。これは false を返します。また、Position を 0 に設定しようとします。

したがって、中間バッファーが必要なようです。

于 2009-02-24T21:45:04.053 に答える