为什么我在 GDI 中遇到这个通用的、非描述性的错误? 当尝试保存 PNG 时?

发布于 2024-07-13 08:14:46 字数 2523 浏览 6 评论 0原文

我有一个函数可以动态地将文本添加到图像中预先指定的位置。 最初我是用 jpeg 来做的,而且效果很好。 我改用 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"
  • 更改了基本图像 (< code>img/banner_green.jpg、img/banner_blue.jpg) 到 .png
  • 添加了指定颜色深度的第二个编码参数
  • 已更改 oInfo(1 ) (jpeg) 到 oInfo(4) (png)

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

I have a function that dynamically adds text to an image in a predesignated spot. Originally I did it with jpegs, and it was working. I switched to PNG so the images would be better quality, as the original jpegs were kind of pixely. Anyway, here is my code. It executes down to the oBitmap.Save(), then dies with "A General Error Has Occurred in 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

The only changes I made to this from the jpeg version are:

  • context.Response.ContentType = "image/jpeg" changed to "image/png"
  • changed base images (img/banner_green.jpg, img/banner_blue.jpg) to .png
  • added the second encoding parameter specifying color depth
  • changed oInfo(1) (jpeg) to oInfo(4) (png)

Are there more things I need to tweak to get this routine to properly generate the PNG?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

未央 2024-07-20 08:14:46

根据 这篇文章,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”写入输出。

According to this post, Bitmap.Save requires a seekable stream to save as PNG, which HttpResponse.OutputStream isn't. You'll have to save the image into a MemoryStream first, and then copy the contents of it to Response.OutputStream, like:

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

Also note that the line

context.Response.Output.Write(oBitmap)

does something different then what you are probably expecting. HttpResponse.Output is a TextWriter, and the overload you use here, TextWriter.Write(object) will just call ToString on the object and write the results into the stream, what in this case results in writing "System.Drawing.Bitmap" to the output.

梦中楼上月下 2024-07-20 08:14:46

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

You're disposing of the bitmap before you're flushing the Response? Try flipping that around. Also, it looks like you're writing the bitmap to the stream twice. I'm not sure why you're doing that. Save the bitmap to the output stream or use the Write method of the Response object, but not both.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文