Почему я получаю эту общую неописанную ошибку в GDI + при попытке сохранить PNG? - PullRequest
2 голосов
/ 04 февраля 2009

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

Ответы [ 2 ]

5 голосов
/ 04 февраля 2009

Согласно этой записи , 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» в вывод.

0 голосов
/ 04 февраля 2009

Вы избавляетесь от растрового изображения до того, как очистите Response? Попробуйте перевернуть это. Кроме того, похоже, что вы записываете растровое изображение в поток дважды. Я не уверен, почему ты это делаешь. Сохраните растровое изображение в выходном потоке или используйте метод Write объекта Response, но не оба.

...