Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# mvc image upload resizing server side

I've got an webapplication where users can upload images. The current problem i'm running into is that the images being uploaded are being saved to the database in the original format. This causes a lot of performance issues when the images are used on a webpage. I used dotTrace to profile the application and I see significant problems when images are processed from the database.

The idea I have is to resize the image when it's uploaded to the server. Take the following example which I want the application to do when the user uploads a new image;

  1. User uploads an image
  2. The image is being resized to an size of 7.500 x 7.500 in pixels in 72 dpi
  3. The image is being saved into the database
  4. Original file gets disposed

The only stored image is the one mentioned above and the webapplication contains technology to resize this on the fly.

I've already read several topics here on SO. And most of them point me into the direction of ImageMagick. This tool is already familiar at my company, and being used in PHP projects. But are there any good and stable released C# wrappers for this tool? I already found the tools below but they're either in Béta release, Alpha Release or currently not updated.

ImageMagick.NET

ImageMagick APP

I also found this topic on SO. In this topic the following code example is supplied;

private static Image CreateReducedImage(Image imgOrig, Size newSize)
{
    var newBm = new Bitmap(newSize.Width, newSize.Height);
    using (var newGrapics = Graphics.FromImage(newBm))
    {
        newGrapics.CompositingQuality = CompositingQuality.HighSpeed;
        newGrapics.SmoothingMode = SmoothingMode.HighSpeed;
        newGrapics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        newGrapics.DrawImage(imgOrig, new Rectangle(0, 0, newSize.Width, newSize.Height));
    }

    return newBm;
}

In short the questions i have;

  • Are there any advantages in relation to performance using the example above?
  • Is there a good and reliable C# wrapper for ImageMagick i can use to do this?

Any other good tips relating to the performance are welcome!

like image 710
Rob Avatar asked Jan 19 '11 15:01

Rob


1 Answers

We use the latter approach - I can't comment on performance but it certainly makes handling dependencies simpler.

However, one thing to note is that the above code is probably too simple if your users are able to upload images in all sorts of formats. The underlying library (GDI+) has issues with a lot of color formats, but it also is dependent on the OS version. Here's the core of the code we use:

    // GDI+ has problems with lots of image formats, and it also chokes on unknown ones (like CMYK).
// Therefore, we're going to take a whitelist approach.
// see http://bmpinroad.blogspot.com/2006/04/file-formats-pixel-formats.html
// also see http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/c626a478-e5ef-4a5e-9a73-599b3b7a6ecc
PixelFormat format = originalImage.PixelFormat;

if (format == PixelFormat.Format16bppArgb1555 ||
    format == PixelFormat.Format64bppArgb)
{
    // try to preserve transparency
    format = PixelFormat.Format32bppArgb;
}
else if (format == PixelFormat.Format64bppPArgb)
{
    // try to preserve pre-multiplied transparency
    format = PixelFormat.Format32bppPArgb;
}
else if (format != PixelFormat.Format24bppRgb && format != PixelFormat.Format32bppRgb)
{
    format = PixelFormat.Format24bppRgb;
}


// GIF saving is probably still an issue.  If we ever need to tackle it, see the following:
// http://support.microsoft.com/kb/319061
// http://www.bobpowell.net/giftransparency.htm
// http://support.microsoft.com/kb/318343


using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, format))
{
    using (Graphics Canvas = Graphics.FromImage(newImage))
    {
        using (ImageAttributes attr = new ImageAttributes())
        {
            attr.SetWrapMode(WrapMode.TileFlipXY);

            Canvas.SmoothingMode = SmoothingMode.AntiAlias;
            Canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
            Canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
            Canvas.DrawImage(originalImage, new Rectangle(new Point(0, 0), newSize), srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, GraphicsUnit.Pixel, attr);
            newImage.Save(outputImageStream, originalImage.RawFormat);
        }
    }
}
like image 130
super_seabass Avatar answered Sep 20 '22 22:09

super_seabass