Reputation: 5135
I've got an ASPX page that renders whatever is in its querystring as vertical text and returns a PNG. It works great.
I have exactly one customer who has run into an issue. Every few days the page stops working and throws the dreaded GDI+ "generic" error.
Error: System.Runtime.InteropServices.ExternalException (0x80004005): A generic error occurred in GDI+.
at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(Stream stream, ImageFormat format)
...
I don't know why the error comes up, or why it eventually goes away. I was able to throw a testing ASPX file into their installation that ran similar code with a few variations to see if I could pinpoint the problem. I discovered that if I changed the ImageFormat from Png to Jpeg the error went away.
I could conceivably change the product to render JPEGs instead of PNGs. However I have no way of knowing if this would eventually start causing errors intermittently just like it is now.
Anybody know what might cause a problem like this? Thanks! Code is below.
Update: The customer server is a Windows Server 2008 R2 box running IIS 7.5 and my application runs on .NET 4.0.
protected void Page_Load(object sender, EventArgs e)
{
byte[] image = GetImageBytes(this.Text);
if (image != null)
{
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "image/png";
Response.OutputStream.Write(image, 0, image.Length);
}
}
private byte[] GetImageBytes(string text)
{
var font = new Font("Tahoma", 11, FontStyle.Bold, GraphicsUnit.Pixel);
// Create an image the size of the text we are writing
Bitmap img = new Bitmap(1,1);
var graphics = Graphics.FromImage(img);
int width = (int)graphics.MeasureString(text, font).Width;
int height = (int)graphics.MeasureString(text, font).Height;
img = new Bitmap(img, new Size(width, height));
// Draw the text onto the image
graphics = Graphics.FromImage(img);
graphics.Clear(Color.Transparent);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.DrawString(text, font, new SolidBrush(Color.Black), 0, 0);
graphics.Flush();
// Rotate the image to be vertical
img.RotateFlip(RotateFlipType.Rotate270FlipNone);
var stream = new System.IO.MemoryStream();
img.Save(stream, ImageFormat.Png);
stream.Position = 0;
return stream.ToArray();
}
Upvotes: 4
Views: 2078
Reputation: 20120
I would say that the flush could be the issue
Forces execution of all pending graphics operations and returns immediately without waiting for the operations to finish.
This member is overloaded. For complete information about this member, including syntax, usage, and examples, click a name in the overload list.
can you try this to see if you still have the issue?
private byte[] GetImageBytes(string text)
{
using (var font = new Font("Tahoma", 20, FontStyle.Bold, GraphicsUnit.Pixel))
using (var img = new Bitmap(1, 1))
{
int width;
int height;
using (var graphics = Graphics.FromImage(img))
{
width = (int)graphics.MeasureString(text, font).Width;
height = (int)graphics.MeasureString(text, font).Height;
}
using (var realImg = new Bitmap(img, new Size(width, height)))
{
using (var graphics = Graphics.FromImage(realImg))
{
graphics.Clear(Color.Transparent);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.DrawString(text, font, new SolidBrush(Color.Black), 0, 0);
}
realImg.RotateFlip(RotateFlipType.Rotate270FlipNone);
using (var stream = new System.IO.MemoryStream())
{
realImg.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Position = 0;
return stream.ToArray();
}
}
}
}
Upvotes: 3