Почему я получаю эту общую, неописуемую ошибку в 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"
- измененные базовые изображения (
img/banner_green.jpg
,img/banner_blue.jpg
) к.png
- добавлен второй параметр кодировки, задающий глубину цвета
- измененный
oInfo(1)
(jpeg) дляoInfo(4)
(png)
Есть ли еще что-то, что мне нужно настроить, чтобы заставить эту процедуру правильно генерировать PNG?
Решение
Согласно этот пост, Растровое изображение.Для сохранения в формате 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" на выходе.
Другие советы
Вы удаляете растровое изображение перед удалением ответа?Попробуй перевернуть это.Кроме того, похоже, что вы дважды записываете растровое изображение в поток.Я не совсем понимаю, зачем ты это делаешь.Сохраните растровое изображение в выходном потоке или используйте метод Write объекта Response, но не оба варианта.