I have a curious problem with IE, IIS 6.0 dynamic PNG files and I am baffled as to how to fix..
Snippet from Helper (this returns the URL to the view for requesting the images from my Controller.
string url = LinkBuilder.BuildUrlFromExpression(helper.ViewContext.RequestContext, helper.RouteCollection, c = c.FixHeight(ir.Filename, ir.AltText, "FFFFFF"));
url = url.Replace("&", "&");
sb.Append(string.Format("<removed id=\"TheImage\" src=\"{0}\" alt=\"\" /", url)+Environment.NewLine);
This produces a piece of html as follows:-
img id="TheImage" src="/ImgText/FixHeight?sFile=Images%2FUser%2FJulianGuppy%2FMediums%2Fconservatory.jpg&backgroundColour=FFFFFF" alt="" /
brackets missing because i cant post an image... even though I dont want to post an image I jsut want to post the markup... sigh
Snippet from Controller ImgTextController
/// <summary>
/// This function fixes the height of the image
/// </summary>
/// <param name="sFile"></param>
/// <param name="alternateText"></param>
/// <param name="backgroundColour"></param>
/// <returns></returns>
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult FixHeight(string sFile, string alternateText, string backgroundColour)
{
#region File
if (string.IsNullOrEmpty(sFile))
{
return new ImgTextResult();
}
// MVC specific change to prepend the new directory
if (sFile.IndexOf("Content") == -1)
{
sFile = "~/Content/" + sFile;
}
// open the file
System.Drawing.Image img;
try
{
img = System.Drawing.Image.FromFile(Server.MapPath(sFile));
}
catch
{
img = null;
}
// did we fail?
if (img == null)
{
return new ImgTextResult();
}
#endregion File
#region Width
// Sort out the width from the image passed to me
Int32 nWidth = img.Width;
#endregion Width
#region Height
Int32 nHeight = img.Height;
#endregion Height
// What is the ideal height given a width of 2100 this should be 1400.
var nIdealHeight = (int)(nWidth / 1.40920096852);
// So is the actual height of the image already greater than the ideal height?
Int32 nSplit;
if (nIdealHeight < nHeight)
{
// Yes, do nothing, well i need to return the iamge...
nSplit = 0;
}
else
{
// rob wants to not show the white at the top or bottom, so if we were to crop the image how would be do it
// 1. Calculate what the width should be If we dont adjust the heigt
var newIdealWidth = (int)(nHeight * 1.40920096852);
// 2. This newIdealWidth should be smaller than the existing width... so work out the split on that
Int32 newSplit = (nWidth - newIdealWidth) / 2;
// 3. Now recrop the image using 0-nHeight as the height (i.e. full height)
// but crop the sides so that its the correct aspect ration
var newRect = new Rectangle(newSplit, 0, newIdealWidth, nHeight);
img = CropImage(img, newRect);
nHeight = img.Height;
nWidth = img.Width;
nSplit = 0;
}
// No, so I want to place this image on a larger canvas and we do this by Creating a new image to be the size that we want
System.Drawing.Image canvas = new Bitmap(nWidth, nIdealHeight, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(canvas);
#region Color
// Whilst we can set the background colour we shall default to white
if (string.IsNullOrEmpty(backgroundColour))
{
backgroundColour = "FFFFFF";
}
Color bc = ColorTranslator.FromHtml("#" + backgroundColour);
#endregion Color
// Filling the background (which gives us our broder)
Brush backgroundBrush = new SolidBrush(bc);
g.FillRectangle(backgroundBrush, -1, -1, nWidth + 1, nIdealHeight + 1);
// draw the image at the position
var rect = new Rectangle(0, nSplit, nWidth, nHeight);
g.DrawImage(img, rect);
return new ImgTextResult { Image = canvas, ImageFormat = ImageFormat.Png };
}
My ImgTextResult is a class that returns an Action result for me but embedding the image from a memory stream into the response.outputstream.
snippet from my ImageResults
/// <summary>
/// Execute the result
/// </summary>
/// <param name="context"></param>
public override void ExecuteResult(ControllerContext context)
{
// output
context.HttpContext.Response.Clear();
context.HttpContext.Response.ContentType = "image/png";
try
{
var memStream = new MemoryStream();
Image.Save(memStream, ImageFormat.Png);
context.HttpContext.Response.BinaryWrite(memStream.ToArray());
context.HttpContext.Response.Flush();
context.HttpContext.Response.Close();
memStream.Dispose();
Image.Dispose();
}
catch (Exception ex)
{
string a = ex.Message;
}
}
Now all of this works locally and lovely, and indeed all of this works on my production server
BUT Only for Firefox, Safari, Chrome (and other browsers) IE has a fit and decides that it either wont display the image or it does display the image after approx 154seconds of waiting.....
I have made sure my HTML is XHTML compliant, I have made sure I am getting no Routing errors or crashes in my event log on the server....
Now obviously I have been a muppet and have done something wrong... but what I cant fathom is why in development all works fine, and in production all non IE browsers also work fine, but IE 8 using IIS 6.0 production server is having some kind of problem in returning this PNG and I dont have an error to trace... so what I am looking for is guidance as to how I can debug this problem.