Issue with WIC image resizing on ASP.NET MVC 2

Posted by Dave on Stack Overflow See other posts from Stack Overflow or by Dave
Published on 2011-01-15T00:51:56Z Indexed on 2011/01/15 0:53 UTC
Read the original article Hit count: 585

I am attempting to implement image resizing on user uploads in ASP.NET MVC 2 using a version of the method found: here on asp.net.

This works great on my dev machine, but as soon as I put it on my production machine, I start getting the error 'Exception from HRESULT: 0x88982F60' which is supposed to mean that there is an issue decoding the image. However, when I use WICExplorer to open the image, it looks ok. I've also tried this with dozens of images of various sources and still get the error (though possible, I doubt all of them are corrupted).

Here is the relevant code (with my debugging statements in there):

MVC Controller

    [Authorize, HttpPost]
    public ActionResult Upload(string file)
    {
        //Check file extension
        string fx = file.Substring(file.LastIndexOf('.')).ToLowerInvariant();
        string key;
        if (ConfigurationManager.AppSettings["ImageExtensions"].Contains(fx))
        {
            key = Guid.NewGuid().ToString() + fx;
        }
        else 
        {
            return Json("extension not found");
        }
        //Check file size
        if (Request.ContentLength <= Convert.ToInt32(ConfigurationManager.AppSettings["MinImageSize"]) ||
            Request.ContentLength >= Convert.ToInt32(ConfigurationManager.AppSettings["MaxImageSize"]))
        {
            return Json("content length out of bounds: " + Request.ContentLength);
        }
        ImageResizerResult irr, irr2;
        //Check if this image is coming from FF, Chrome or Safari (XHR)
        HttpPostedFileBase hpf = null;
        if (Request.Files.Count <= 0)
        {
            //Scale and encode image and thumbnail
            irr = ImageResizer.CreateMaxSizeImage(Request.InputStream);
            irr2 = ImageResizer.CreateThumbnail(Request.InputStream);
        }
        //Or IE
        else
        {                
            hpf = Request.Files[0] as HttpPostedFileBase;
            if (hpf.ContentLength == 0)
                return Json("hpf.length = 0");

            //Scale and encode image and thumbnail
            irr = ImageResizer.CreateMaxSizeImage(hpf.InputStream);
            irr2 = ImageResizer.CreateThumbnail(hpf.InputStream);                
        }
        //Check if image and thumbnail encoded and scaled correctly
        if (irr == null || irr.output == null
                || irr2 == null || irr2.output == null)

        {
            if (irr != null && irr.output != null)
                irr.output.Dispose();
            if (irr2 != null && irr2.output != null)
                irr2.output.Dispose();
            if(irr == null)
                return Json("irr null");
            if (irr2 == null)
                return Json("irr2 null");
            if (irr.output == null)
                return Json("irr.output null. irr.error = " + irr.error);
            if (irr2.output == null)
                return Json("irr2.output null. irr2.error = " + irr2.error);
        }
        if (irr.output.Length > Convert.ToInt32(ConfigurationManager.AppSettings["MaxImageSize"])
                || irr2.output.Length > Convert.ToInt32(ConfigurationManager.AppSettings["MaxImageSize"]))
        {
            if(irr.output.Length > Convert.ToInt32(ConfigurationManager.AppSettings["MaxImageSize"]))
                return Json("irr.output.Length > maximage size. irr.output.Length = " + irr.output.Length + ", irr.error = " + irr.error);
            return Json("irr2.output.Length > maximage size. irr2.output.Length = " + irr2.output.Length + ", irr2.error = " + irr2.error);
        }
        //Store scaled and encoded image and thumbnail

        ....

        return Json("success");
    }

The code is always failing when checking if the output stream is null (i.e. irr.output == null is true).

ImageResizerResult and ImageResizer

public class ImageResizerResult : IDisposable
{
    public MemoryIStream output;
    public int width;
    public int height;
    public string error;

    public void Dispose() { output.Dispose(); }
}

public static class ImageResizer
{
    private static Object thislock = new Object();
    public static ImageResizerResult CreateMaxSizeImage(Stream input)
    {
        uint maxSize = Convert.ToUInt32(ConfigurationManager.AppSettings["MaxImageDimension"]);
        try
        {
            lock (thislock)
            {
                // Read the source image
                var photo = ByteArrayFromStream(input);
                var factory = (IWICComponentFactory)new WICImagingFactory();
                var inputStream = factory.CreateStream();
                inputStream.InitializeFromMemory(photo, (uint)photo.Length);
                var decoder = factory.CreateDecoderFromStream(inputStream, null, WICDecodeOptions.WICDecodeMetadataCacheOnDemand);
                var frame = decoder.GetFrame(0);
                // Compute target size
                uint width, height, outWidth, outHeight;
                frame.GetSize(out width, out height);
                if (width > height)
                {
                    //Check if width is greater than maxSize
                    if (width > maxSize)
                    {
                        outWidth = maxSize;
                        outHeight = height * maxSize / width;
                    }
                    //Width is less than maxSize, so use existing dimensions
                    else
                    {
                        outWidth = width;
                        outHeight = height;
                    }
                }
                else
                {
                    //Check if height is greater than maxSize
                    if (height > maxSize)
                    {
                        outWidth = width * maxSize / height;
                        outHeight = maxSize;
                    }
                    //Height is less than maxSize, so use existing dimensions
                    else
                    {
                        outWidth = width;
                        outHeight = height;
                    }
                }
                // Prepare output stream to cache file
                var outputStream = new MemoryIStream();
                // Prepare JPG encoder
                var encoder = factory.CreateEncoder(Consts.GUID_ContainerFormatJpeg, null);
                encoder.Initialize(outputStream, WICBitmapEncoderCacheOption.WICBitmapEncoderNoCache);
                // Prepare output frame
                IWICBitmapFrameEncode outputFrame;
                var arg = new IPropertyBag2[1];
                encoder.CreateNewFrame(out outputFrame, arg);
                var propBag = arg[0];
                var propertyBagOption = new PROPBAG2[1];
                propertyBagOption[0].pstrName = "ImageQuality";
                propBag.Write(1, propertyBagOption, new object[] { 0.85F });
                outputFrame.Initialize(propBag);
                outputFrame.SetResolution(96, 96);
                outputFrame.SetSize(outWidth, outHeight);
                // Prepare scaler
                var scaler = factory.CreateBitmapScaler();
                scaler.Initialize(frame, outWidth, outHeight, WICBitmapInterpolationMode.WICBitmapInterpolationModeFant);
                // Write the scaled source to the output frame
                outputFrame.WriteSource(scaler, new WICRect { X = 0, Y = 0, Width = (int)outWidth, Height = (int)outHeight });
                outputFrame.Commit();
                encoder.Commit();
                return new ImageResizerResult { output = outputStream, height = (int)outHeight, width = (int)outWidth };
            }
        }
        catch (Exception e)
        {
            return new ImageResizerResult { error = "Create maxsizeimage = "  + e.Message };
        }

    }
}

Thoughts on where this is going wrong?

Thanks in advance for the effort.

© Stack Overflow or respective owner

Related posts about c#

Related posts about ASP.NET