当我尝试保存 PNG 时,为什么会在 GDI+ 中遇到这种通用的、非描述性的错误?
题
我有一个函数可以动态地将文本添加到图像中预先指定的位置。最初我是用 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"
- 更改了基础图像(
img/banner_green.jpg
,img/banner_blue.jpg
) 到.png
- 添加了指定颜色深度的第二个编码参数
- 改变了
oInfo(1)
(jpeg) 至oInfo(4)
(PNG)
为了让这个例程正确生成 PNG,我还需要调整更多的东西吗?
解决方案
根据 这个帖子, 、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”写入输出。
其他提示
您要在刷新响应之前处理位图吗?尝试翻转一下。另外,看起来您将位图写入流两次。我不确定你为什么要这样做。将位图保存到输出流或使用 Response 对象的 Write 方法,但不能同时使用两者。
不隶属于 StackOverflow