15

Is there an easy and dynamic way to create thumbnails and resize images in MVC3/Razor? A helper, libary, anything?

It would be nice, if I somehow could manage the size of the images from the controller. Or even in razorview. Example: In the index view I want the images to be a certain size, but in the details view i want them to be full size.

I know this question is vague, but I really couldnt find anything on google/stackoverflow other than old mvc1 thingos.

How do you guys normally deal with this?

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Kasper Skov
  • 1,954
  • 10
  • 32
  • 53

4 Answers4

26

Is there an easy and dynamic way to create thumbnails and resize images in MVC3/Razor? A helper, libary, anything?

You could use the built-in System.Drawing assembly and the Image class to achieve this. You may write a controller action which would be passed as arguments the image name and the desired new size and this controller action would perform the resize and return the new image.

For example:

public ActionResult Thumbnail(int width, int height)
{
    // TODO: the filename could be passed as argument of course
    var imageFile = Path.Combine(Server.MapPath("~/app_data"), "test.png");
    using (var srcImage = Image.FromFile(imageFile))
    using (var newImage = new Bitmap(width, height))
    using (var graphics = Graphics.FromImage(newImage))
    using (var stream = new MemoryStream())
    {
        graphics.SmoothingMode = SmoothingMode.AntiAlias;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
        graphics.DrawImage(srcImage, new Rectangle(0, 0, width, height));
        newImage.Save(stream, ImageFormat.Png);
        return File(stream.ToArray(), "image/png");
    }
}

Now go ahead and include this action in your view:

<img src="@Url.Action("Thumbnail", "SomeController", new { width = 100, height = 50 })" alt="thumb" />
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Youve used Url.Action. Shouldnt it me Html.Action? – Kasper Skov Sep 07 '11 at 10:55
  • 2
    @Kasper Skov, no, I don't want to render the execution of a given action, I want to get the url of this action, so the correct is to use Url.Action. To read more about Html.Action you may take a look at the following blog post: http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx – Darin Dimitrov Sep 07 '11 at 10:58
  • Never mind. Its Url. Thats why: OutputStream is not available when a custom TextWriter is used. – Kasper Skov Sep 07 '11 at 11:00
  • 3
    Any idea of how to preserve proportionality of the original image? For example, an original image of size `500x200` should be converted into a thumbnail of size `100x40`, not `100x100`. Otherwise, it would be stretched. – Saeed Neamati Jan 22 '12 at 09:26
  • @Saeed: take a look at my answer... the WebImage Resize method has a parameter to keep proportionality. Works great! – Leniel Maccaferri Apr 26 '12 at 18:42
  • 1
    This is a lot of processing every time you need to get an image...might be better to run this and save a thumbnail separately when you upload an image if that suits your scenario – Stuart Dobson Feb 06 '14 at 11:43
19

Using WebImage class that comes in System.Web.Helpers.WebImage you can achieve this.

You can use this great kid to output resized images on the fly.

Sample code:

public void GetPhotoThumbnail(int realtyId, int width, int height)
{
    // Loading photos’ info from database for specific Realty...
    var photos = DocumentSession.Query<File>().Where(f => f.RealtyId == realtyId);

    if (photos.Any())
    {
        var photo = photos.First();

        new WebImage(photo.Path)
            .Resize(width, height, false, true) // Resizing the image to 100x100 px on the fly...
            .Crop(1, 1) // Cropping it to remove 1px border at top and left sides (bug in WebImage)
            .Write();
    }

    // Loading a default photo for realties that don't have a Photo
        new WebImage(HostingEnvironment.MapPath(@"~/Content/images/no-photo100x100.png")).Write();
}

In a view you'd have something like this:

<img src="@Url.Action("GetPhotoThumbnail",
     new { realtyId = item.Id, width = 100, height = 100 })" />

More about it here: Resize image on the fly with ASP.NET MVC


I just found this nice tutorial about WebImage at the ASP.NET site:

Working with Images in an ASP.NET Web Pages (Razor) Site.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
  • 2
    This worked rather well for me. One caveat is that I ended up writing a small cache on the server side (by using Save() instead of Write()), because resizing large photos turned out to be CPU intensive and my AWS EC2 micro instance was not keeping up. – DenNukem Dec 27 '12 at 19:56
  • This is a really nice vulnerabilitie to make some DoS attacks. – gog Mar 10 '16 at 18:42
10

Also take a look at my Simple.ImageResizer.MvcExtensions nuget package.

Demo site here: http://imageresizer.apphb.com/

Adds a ImageResult class that you can use in your controller action that takes a height and width input making it pretty easy to add image resizing to your mvc site. Would love to hear what you think

terjetyl
  • 9,497
  • 4
  • 54
  • 72
4

There's a library for it - it's MVC3 compatible, and it's implemented as an HttpModule, so it gets great performance.

It's also free (although some plugins require a 1-time developer or business license).

You can download it at http://imageresizing.net

Although it's tempting to just write an action for it, there are a lot of GDI bugs that you'll have to deal with, one, by one, over the years. Using a library frees you from tracking and avoiding them. Google "Image resizing pitfalls", the first result is an article that will help if you write your own decoding/resizing/encoding system.

Lilith River
  • 16,204
  • 2
  • 44
  • 76
  • i want to try this, but i don't find any clear steps or tutorial on how to call the method in asp mvc view using `@Url.Action`, i tried [this](http://imageresizing.net/docs/v4) and [this](http://www.hanselman.com/blog/NuGetPackageOfWeek11ImageResizerEnablesCleanClearImageResizingInASPNET.aspx) links ? – Shaiju T Mar 10 '16 at 11:40