【问题标题】:Why am I getting this generic, non-descript error in GDI+ when trying to save a PNG?为什么我在尝试保存 PNG 时会在 GDI+ 中得到这个通用的、非描述性的错误?
【发布时间】:2010-10-05 10:11:01
【问题描述】:

我有一个功能,可以在预先指定的位置向图像动态添加文本。最初我是用 jpegs 做的,它正在工作。我切换到PNG,因此图像质量会更好,因为原始的jpeg有点像素化。无论如何,这是我的代码。它执行到oBitmap.Save(),然后因“GDI+ 中发生一般错误”而死。

Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
    context.Response.ContentType = "image/png"
    context.Response.Clear()
    context.Response.BufferOutput = True

    Try
        Dim oText As String = context.Server.HtmlDecode(context.Request.QueryString("t"))
        If String.IsNullOrEmpty(oText) Then oText = "Placeholder"
        Dim oPType As String = context.Server.HtmlDecode(context.Request.QueryString("p"))
        If String.IsNullOrEmpty(oPType) Then oPType = "none"

        Dim imgPath As String = ""
        Select Case oPType
            Case "c"
                imgPath = "img/banner_green.png"
            Case "m"
                imgPath = "img/banner_blue.png"
            Case Else
                Throw New Exception("no ptype")
        End Select

        Dim oBitmap As Bitmap = New Bitmap(context.Server.MapPath(imgPath))
        Dim oGraphic As Graphics = Graphics.FromImage(oBitmap)
        Dim frontColorBrush As New SolidBrush(Color.White)
        Dim oFont As New Font(FONT_NAME, 30)


        Dim oInfo() As ImageCodecInfo = ImageCodecInfo.GetImageEncoders
        Dim oEncoderParams As New EncoderParameters(2)
        Dim xOffset As Single = Math.Round((oBitmap.Height - oFont.Height) / 2, MidpointRounding.ToEven)
        Dim oPoint As New PointF(275.0F, xOffset + 10)

        oEncoderParams.Param(0) = New EncoderParameter(Encoder.Quality, 100L)
        oEncoderParams.Param(1) = New EncoderParameter(Encoder.ColorDepth,8L)

        oGraphic.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
        oGraphic.DrawString(oText, oFont, frontColorBrush, oPoint)
        oBitmap.Save(context.Response.OutputStream, oInfo(4), oEncoderParams)
        context.Response.Output.Write(oBitmap)

        oFont.Dispose()
        oGraphic.Dispose()
        oBitmap.Dispose()  
        context.Response.Flush()
    Catch ex As Exception

    End Try
End Sub

我对 jpeg 版本所做的唯一更改是:

  • context.Response.ContentType = "image/jpeg" 更改为 "image/png"
  • 将基础镜像(img/banner_green.jpgimg/banner_blue.jpg)更改为.png
  • 添加了指定颜色深度的第二个编码参数
  • oInfo(1) (jpeg) 更改为 oInfo(4) (png)

为了让这个例程正确生成 PNG,我还需要调整更多的东西吗?

【问题讨论】:

    标签: asp.net vb.net gdi+ png


    【解决方案1】:

    您要在刷新响应之前处理位图?尝试翻转它。此外,看起来您正在将位图写入流两次。我不确定你为什么要这样做。将位图保存到输出流或使用 Response 对象的 Write 方法,但不能同时使用。

    【讨论】:

    • 我不认为我正在使用文件系统(即将图像保存到目录?)。无论如何,在到达 dispose/flush 行之前脚本会出错,但无论如何我都会试一试。
    • 是的,它仍然会在保存线爆炸。我要去调查这个内存流的东西
    • 对不起,重新阅读代码并更改了我的答案。我看到的两个问题是先处理后刷新和先保存后写入。可能是其中之一;什么 jpeg 可以处理 png 可能不会。
    • 从我在线阅读的内容来看,保存部分将文件信息写入位图对象,并写入显示它。我可能弄错了,但我会尝试再混一些
    • 使用内存流解决了这个问题,我将位图写入内存流,然后将内存流写入响应的输出流。谢谢!
    【解决方案2】:

    根据this post,Bitmap.Save 需要一个可搜索的流来保存为 PNG,而 HttpResponse.OutputStream 不是。您必须先将图像保存到 MemoryStream 中,然后将其内容复制到 Response.OutputStream,例如:

    Dim tempStream as New MemoryStream
    oBitmap.Save(tempStream, ImageFormat.Png, oEncoderParams)
    Response.OutputStream.Write(tempStream.ToArray(), 0, tempStream.Length)
    

    还要注意这一行

    context.Response.Output.Write(oBitmap)
    

    做一些不同于你可能期望的事情。 HttpResponse.Output 是一个 TextWriter,您在此处使用的重载 TextWriter.Write(object) 只会在对象上调用 ToString 并将结果写入流,在这种情况下会导致将“System.Drawing.Bitmap”写入输出。

    【讨论】:

    • 尽管 Will 的回答让我找出了问题所在,但您的帖子准确地概述了问题所在。谢谢!
    猜你喜欢
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 2016-08-26
    • 1970-01-01
    相关资源
    最近更新 更多