¿Por qué recibo este error genérico, que no se nota en GDI + cuando intenta guardar un archivo PNG?
Pregunta
Tengo una función que añade dinámicamente texto a una imagen en un lugar previamente designado. Originalmente lo hice con archivos JPEG, y que estaba trabajando. Cambié a PNG para las imágenes serían de mejor calidad, ya que los archivos JPEG originales eran una especie de pixely. De todos modos, aquí está mi código. Ejecuta hasta el oBitmap.Save()
, luego muere con "un error general se ha producido en 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
Los únicos cambios que hice a este respecto a la versión JPEG son:
-
context.Response.ContentType = "image/jpeg"
cambió a"image/png"
- Imágenes cambiado de bases (
img/banner_green.jpg
,img/banner_blue.jpg
) a.png
- añade el segundo parámetro de codificación que especifica la profundidad de color
- cambiado
oInfo(1)
(JPEG) aoInfo(4)
(png)
¿Hay más cosas que tengo que pellizcar para obtener esta rutina para generar correctamente el PNG?
Solución
Según este post , Bitmap.Save requiere una corriente seekable guardar como PNG, que HttpResponse.OutputStream no lo es. Vas a tener que guardar la imagen en un MemoryStream primero, y luego copiar el contenido del mismo a Response.OutputStream, como:
Dim tempStream as New MemoryStream
oBitmap.Save(tempStream, ImageFormat.Png, oEncoderParams)
Response.OutputStream.Write(tempStream.ToArray(), 0, tempStream.Length)
Tenga en cuenta también que la línea
context.Response.Output.Write(oBitmap)
hace algo diferente de lo que es probable que esté esperando. HttpResponse.Output
es un TextWriter, y la sobrecarga se utiliza aquí, se acaba de llamar TextWriter.Write(object)
ToString en el objeto y escribir los resultados en la corriente, lo que en este caso los resultados en la escritura "System.Drawing.Bitmap" a la salida.
Otros consejos
Esta disponer del mapa de bits antes de que esté lavado de la Respuesta? Trate de mover de un tirón que alrededor. Además, parece que se está escribiendo el mapa de bits en la secuencia dos veces. No estoy seguro de por qué estás haciendo eso. Guardar el mapa de bits en el flujo de salida o utilizar el método Write del objeto Response, pero no ambos.