Using MVC3, Razor Helpers, and jCrop to upload and crop images.
UPDATE – Original Source Link
I somehow miraculously stumbled upon the source code for this project, so I’m including a link to it here:
Note: If you get a “Project Type Not Supported” in Visual Studio 2010, you need to download the MVC 3 Tools Update (or install SP1, I believe).
The link is here: http://www.microsoft.com/en-us/download/details.aspx?id=1491
A common requirement for websites that allow user registration is the uploading of user profile images. In many cases, this can be a bother for both user and developer. The implementation of image cropping functionality has traditionally been somewhat cumbersome for developers, and users are generally pained by having to crop an image offline before uploading it, especially more inexperienced computer users.
We’ll explore how to quickly and easily create a solution using ASP.NET MVC3 and 2 of the new Razor helpers, the FileUpload and WebImage helpers and jCrop, an excellent jQuery plugin for image cropping.
Jcrop is available for download from the following link: Jcrop Webpage
Just drop your CSS and the Jcrop.gif file in your Content foler, and include the jQuery.jCrop.min.js in your Scripts folder.
FileUpload and WebImage for uploading images
Adding the Microsoft.Web.Helpers Library
To add the Microsoft.Web.Helpers library, install NuGet, and install the Microsoft.Web.Helpers package. Also, include the System.Web.Helpers package included with ASP.NET MVC 3.
We’re creating a very simple solution for displaying and cropping images here.
First, we’ll need a view model for our profile editing view.
You can see we’re using a UIHint to simplify the naming of our Display and Editor templates.
Next, we’ll create an editor template for our image:
Now, lets create our index page.
We’ve got a basic HTML form here that will post to the Upload action method with the encoding type set to multipart/form-data for file upload. We’ll need to add in the code for the upload box. For this, we’ll use the FileUpload helper.
The FileUpload helper
For our purposes, we’ll use the following FileUpload command for a single file upload:
Receiving Uploaded Files
To receive and save the uploaded file, we’ll implement the Upload action method using the WebImage helper to save the file:
Using the GetImageFromRequest static method on the WebImage class, we retrieve a WebImage object representing the uploaded file. Since we’re constraining all images to a maximum of 500 pixels in width, we’ll use the Width property to check the size, and use the Resize functionality of the WebImage helper to resize the image in memory. We the get the filename and use the Save function of the WebImage helper to svae the file to a TempImages folder. We then retrieve the image url and set it back to the ImageUrl property of our ProfileViewModel instance and return the model to our view. This results in the following:
In our app, we’re displaing a profile picture constrained to a 1 to 1 aspect ratio. this causes most images we’d upload to appear tiny and squished. This results in an ugly profile picture. Lets fix this problem by giving our users the ability to crop their image using jCrop.
Cropping using jCrop and WebImage
jCrop requires a few image properties initially to set the initial crop window. We’ll create an Editor input model that will give us the ability to both supply those values, and to retrieve the final cropping dimensions to perform the cropping action.
Out EditorInputModel contains our original ProfileViewModel which supplies our ImageUrl property, but may contain other profile information for the solution you’re implementing. It also contains both size and position properties for the crop selection. We’re going to set these properties to set the initial cropping indicator.
Updating our Upload action method:
Paste the following code at Line 17 in our Upload action method above:
This code populates our EditorInputModel with the initial information we need to supply jCrop with to do the cropping operation. We’re passing this information then to the “Editor” view.
The editor view
First, we’re going to use jCrop to allow us to crop our image with a live thumbnail preview. To do that, we need to display our image twice. We’ll use the following editor template:
This simple editor template creates 2 img tags displaying the image, one named “preview”and one named “profileImageEditor”. The size of preview is constrained to a 1 to 1 aspect ratio using CSS.
Next, we’ll need our Editor view.
We display our editor for the image, and create hidden HTML fields for the Left, Right, Top, and Bottom properties of the cropping indicator. These we pass back to perform the cropping operation.
here we’re calling .Jcrop on our profileImageEditor image tag, setting the jCrop onChange and onSelect callsback to the showPreview function. We’re also setting the Model.Top, model.left, Model.Right, and Model.Bottom properties to the html form values being automatically set by jCrop. We’re also constraining the selector to an aspect ratio of 1.
In the showPreview function, we’re grabbing the crop selectors values and updating our thumbnail window to show a preview of the cropping operation.
Now, after launching our app and submitting an image for upload, we’re given the following view:
On the left, we have our main image display with our jCrop cropping tool, and our live thumbail perview to the left, along with the “Crop” button to submit our post request.
The last thing we need to do is to implement our Edit action method, which will do the actual cropping using the WebImage helper.
The edit action method
First, we load the original image form disk using the ImageUrl we had stored in our ProfileViewModel instance. We retrieve the width and eight from the loaded image, as these are our initial width and height values we’ll need to perform our cropping.
We then call the Crop method of the WebImage instance, supplying the top and left values on the original image where the crop begins, and calculating the width and height of the resulting image by subtracting the bottom of the crop tool from the height of the image, and the rigth of the crop tool from the width of the original image.
We then grab the original source image URL before setting the ImageURL property to the new location we’ll be saving our cropped image. Now that we’ve cropped our image to a 1 to 1 aspect ratio, we’ll resize to the final profile image size, 100 x 100. We then save the image to our new ImageURL, delete the original source image, and pass the cropped image back to the index page.
After our cropping operation, we’re returned to our index view with our new cropped image.