Почему я получаю эту общую, неописуемую ошибку в GDI + при попытке сохранить PNG?

StackOverflow https://stackoverflow.com/questions/511579

  •  21-08-2019
  •  | 
  •  

Вопрос

У меня есть функция, которая динамически добавляет текст к изображению в заранее обозначенном месте.Изначально я делал это в формате 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, но не оба варианта.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top