为什么我在 GDI 中遇到这个通用的、非描述性的错误? 当尝试保存 PNG 时?
我有一个函数可以动态地将文本添加到图像中预先指定的位置。 最初我是用 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) tooInfo(4)
(png)
Are there more things I need to tweak to get this routine to properly generate the PNG?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
根据 这篇文章,Bitmap.Save 需要一个可查找的流来另存为PNG,而 HttpResponse.OutputStream 不是。 您必须首先将图像保存到 MemoryStream 中,然后将其内容复制到 Response.OutputStream,例如:
另请注意,该行
执行的操作与您可能期望的不同。
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:
Also note that the line
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.您要在刷新响应之前处理位图吗? 尝试翻转一下。 另外,看起来您将位图写入流两次。 我不确定你为什么要这样做。 将位图保存到输出流或使用 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.