Upload and Crop Images with jQuery, JCrop and ASP.NET

I got given jQuery In Action for Christmas. By nature, I'm kind of a late adopter, and I'm already regretting this fact. jQuery has been around for some time, and I wished I had looked at it sooner. It's a fantastic library that really simplifies Javascript development, and is already attracting a goodly number of plug-ins. JCrop is one such, and while it hasn't yet reached version 1.0, it is remarkably easy to use as a web based image cropper. Here's how to put jQuery, JCrop and a FileUpload control together to allow users to upload images and crop them.

If you haven't already done so, you will need to download the jQuery library. The current version, and therefore the one that is used in this sample is 1.2.6. Then you need to get hold of the files for JCrop. The download also includes a number of samples which show the features offered by JCrop, such as specifying a fixed aspect or minimum and maximum sizes etc, but this sample uses the default out-of-the-box settings. Be sure to get version 0.9.8 or later, as previous versions had trouble working with IE8 when compatability mode is switched off. Finally you could probably do with making sure that your VS 2008 or VWD 2008 has SP1 applied together with this hotfix which enables Intellisense on javascript files, including jQuery and JCrop.

This example consists of a single page. It caters for three actions: first, the user is presented with an Upload control to locate and upload their image; second, they will be presented with their uploaded image ready for cropping; and finally, they are presented with the cropped result. To accommodate this, three Panel controls are added to the page. The first, pnlUpload contains the FileUpload control and a button linked to an event handler for its click event. The second, pnlCrop contains an Image control and a button - again, linked to an event handler for its Click event. It also contains 4 HiddenField controls. They will be explained shortly. The Panel's Visibility is set to false. The final Panel, pnlCropped contains an Image control, and its Visibility is also set to false.

Some Javascript is required. If you were starting this kind of application from scratch, it would need an awful lot of javascript. However, jQuery's real power is illustrated by just how little javascript this page actually needs. To make use of both jQuery and JCrop, they need to be linked to in the head section of the page, along with the css file that comes as part of the JCrop download. The link to jQuery makes use of the copy available from the Google Ajax API Library for better caching and faster downloading:

All that's now needed to activate JCrop is a handful of lines of Javascript, which go within <script> that's in the head of the document below the previous lines:

<scripttype="text/javascript">

jQuery(document).ready(function() {

jQuery('#imgCrop').Jcrop({

onSelect: storeCoords

});

});

function storeCoords(c) {

jQuery('#X').val(c.x);

jQuery('#Y').val(c.y);

jQuery('#W').val(c.w);

jQuery('#H').val(c.h);

};

</script>

It really is that simple. Jcrop has been applied to the image that has the id of imgCrop (the one in pnlCrop), and an event handler has been added to the select event of the cropper. This will happen when the user has completed selecting the area of the image they want to keep. The handler makes use of the storeCoords function, which sets the values of the HiddenFields, passing them the x and y coordinates of the top left of the selection relative to the image, and the width and height of the selection. That's all ASP.NET needs to know in order to process the image on the server. Now on to the server-side code.

There are 4 namespaces that need to be referenced in additional to the default ones that a new Web Form brings in:

using System.IO;

using SD = System.Drawing;

using System.Drawing.Imaging;

using System.Drawing.Drawing2D;

Since we will be working with instances of System.Drawing.Image as well as System.Web.UI.WebControls, which also has an Image class, I have aliased System.Drawing.Image, which will permit me to use a shorthand to reference the System.Drawing.Image classes. The first four lines of the code-behind simply set a variable to point to the file system path of the directory in which uploaded images will be stored, and show an empty Page_Load method:

lblError.Text = "File could not be uploaded." + ex.Message.ToString();

lblError.Visible = true;

FileSaved = false;

}

}

else

{

lblError.Text = "Cannot accept files of this type.";

lblError.Visible = true;

}

if (FileSaved)

{

pnlUpload.Visible = false;

pnlCrop.Visible = true;

imgCrop.ImageUrl = "images/" + Session["WorkingImage"].ToString();

}

}

This code should be pretty familiar to anyone who has worked with the FileUpload control before. It simply checks to see if a file has been submitted, and ensures that it is of the right type. Then it saves the file to disk and the name of the file to a Session variable. Once the image has been saved, it is set as the ImageUrl of the Image control which has been targeted by JCrop and makes the containing Panel visible.

This section references the image name from the Session variable, and then declares a number of integers that get their values from the HiddenFields that JCrop wrote to when the user selected the area they wanted to keep.

It then calls a method called Crop() to perform the actual cropping of the image (more of which soon). Crop() returns a byte array, which is written to a MemoryStream so that it can be used and converted back to an Image. This is then prefixed with the word "crop" in its name before being saved to disk and displayed to the user.

This might at first glance look a little daunting to beginners, but most of the code just sets properties that affect the quality and appearance of the resulting image. What it does is to simply use the original image as a base from which a new image is drawn, and then save it to a MemoryStream object, which is returned as a byte array to be consumed by the calling code above. You should take note of the using blocks that are employed in this method. They ensure that Image, Bitmap and Graphics objects are all disposed of when the method is done. There's nothing worse than finding that your busy web app has slowed to a crawl through unreleased resources.

22 February 2009 16:45 - hoanghieu

23 February 2009 10:17 - Tung

24 February 2009 09:28 - Anas

24 February 2009 10:58 - ntnikolov

Thanks man. Very useful article -:)

25 February 2009 00:53 - Kaypee

Great article, a must read ^_^

25 February 2009 08:17 - Jigar

Thanks, very useful article

26 February 2009 05:56 - Pushkar

Hey hey man...thanks its very useful for the asp.net developer who really seeking Image Scrop functionality whille uploading image...Thanks man..i have checked its working properly in FireFox but not in IE..I hope you will lookafter for the IE issue..Thanks again.

26 February 2009 18:54 - Mike

@Pushkar

It works fine in IE for me.

26 February 2009 20:34 - Siraj

I want to do resize of image and then to do crop or to do crop and then resize cropped image

26 February 2009 21:00 - Mike

@Siraj,

That's fine. Just change the order of the code to what you need.

28 February 2009 17:27 - Sandy

nice article men..

04 March 2009 05:25 - Ashish

Hi, Good Article but if if upload a big image the image cover the whole page

04 March 2009 07:37 - Mike

@Ashish

Yes - if you try to display a big image, it will appear ermmm.... Big. If you want to reduce the image dimensions, you can do this before uploading, or you can do so as you initially save the image to the file system, but before you display it for cropping.

16 March 2009 07:49 - Minhaj Mansuri

Thanks A Lot , Nice Article
If You Want To Crop Default Selected Portion Without Touching The Crop Portion Then It Give Error

17 March 2009 07:36 - Mike

@Minhaj

The reason that you get an error is that there are no default values in the hidden fields when the page first loads. Either set some, or handle the exception in your server-side code.

18 March 2009 13:16 - venkatesh

hi!
it is very code but it is not work in my site i am using master page

18 March 2009 13:53 - Mike

@venkatesh,

I suspect you have done something wrong. My guess would be that you are trying to reference controls that have had their names changed by INamingContainer (Google it - or put it in the search box at the top of the page), but I could be wrong. If you can't work it out, post a question to the forums at www.asp.net.

20 March 2009 05:25 - jithu

Very nice article.. image quality is superb after cropping.. !!!!

20 March 2009 11:08 - mark

Is there a sample download for this post at all? Cheers...

20 March 2009 19:44 - Mike

@Mark

I don't do downloads as a rule. However, all the code you need is in the article.

23 March 2009 17:31 - mark

OK Mike. No problem. Thanks for the repsonse anyway. :-)

24 March 2009 13:27 - Dan Sylvester

Thanks for the link to the google api library. I might use it.

26 March 2009 05:48 - anjan

plz anyone help me .when i applied this code , i hav an error of uploading an image ..the error is-------

**File could not be uploaded.Could not find a part of the path 'C:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\WebSites\UploadAndCrop\images\cropped.jpg'.

can anyone fix the problem???

29 March 2009 04:20 - Hamid

Please write article with code which take the images from the folder or database and then display those images using jquery

30 March 2009 16:34 - mansoor

Nice article.ver useful.
If possible palace a small article like a project.
It will help more(i think)

03 April 2009 18:02 - Marleny Nunez

Excellent article and great usage of the JCrop plug-in. I must add for the newbies that the code is not all complete for just copy/pasting. It requires at least basic understanding of dot net applications.
This is what is missing on the explanation for the uninitiated:
1. Save the first block of code as UploadAndCrop.aspx
2. Add the second and third blocks of code to the head section of the aspx file. this is explained in the article.
3. Save the rest of the code as UploadAndCrop.aspx.cs
4. On the .cs file, replace the lines
using System.IO;
using SD = System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

with this:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using System.IO;
using SD = System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

public partial class UploadAndCrop : System.Web.UI.Page
{

5. Add a closing bracket "}" at the end of the .cs file to wrap the class we just added.
}

Good luck and happy programming!

05 April 2009 09:40 - Warren Tan TL

i realized that the value is empty... aikz

08 April 2009 16:39 - Mark Brown

Hi,

I was just wondering if there is a way to set the crop area to a set width and height, so that the user just moves a square of 250 x 250 px but doesn't have the option the resize it?

10 April 2009 18:00 - Mike

11 April 2009 13:23 - Vinicius

Nice article but can you give us a 'download this project' link ? :)
Thanks!

12 April 2009 10:42 - sourav

.every thing is al rite but plz clear me the CSS AND JAVAscript part(second block of code) it does not work..

12 April 2009 12:16 - Mike

@Sourav

Yes it works. I tested it before posting it in this article. What I think you mean is that *your* implementation of the code doesn't work. If you want quick help, I suggest you go to the forums at www.asp.net and post a question there.

13 April 2009 10:25 - Umesh

Hello Mike

Its really nice article ..

But how to reset the cropper. (i.e., If i provide one more reset button and i want it reset the cropper by clicking on this button ).

14 April 2009 07:12 - Mike

@Umesh

I refer you to the link I gave Mark Brown in my reply to his question which details the options you can set. The one you want is setSelect.

20 April 2009 15:47 - George Grubar

Very cool Mike.....jquery is super-rich in functionality. Client-side scripting kicks butt these days.

I developed a similar crop image solution using Classic ASP and Javascript (might be of use to others)

20 April 2009 19:09 - Mike

That's exactly the same javascript cropper I used in an old classic ASP application before I came across jQuery. I even recognise the sample image of the castle!

01 May 2009 18:15 - Nikolaj

@Mikesdotnetting
The problem mentioned by Pushkar on 26 February 2009 05:56, does happend on some version of IE - so it probably haven't occurred to you :)

Anyhow, the problem is that (some versions of) IE sends the entire filepath (ie.: "C:\Pictures\mypicture.jpg") - not only the filename (ie.: "mypicture.jpg"), as one expects. Therefore you will get an invalid path in the end (ie.: "{PhysicalApplicationPath}images\C:\Pictures\mypicture.jpg"), then trying to save the image.

I have tried putting Labels on the aspx page and changing the text. It changes as I move the box or change the selection. However, when I click the button crop, those values don't get passed to the event handler?

What am I not doing?

25 May 2009 20:13 - Mike

@Ramona

I can only repeat what I suggested to Python. Some simple debugging will help you, becaise you need to find out what value W is passing at the moment that causes the error. ?Use the VS/VWD debugger or use FireFox and install Firebug and look at the values that are being passed.

26 May 2009 19:15 - Ramona

Hi! Thanks for the feedback. Actually the issue was that I am using a MasterPage format, so the Hidden TextBox ID's were getting munged. I had to use the <%= X.ClientID %> workaround to get the values.

Next issue is that I am using shared hosting, and can't yet save the file to the FileSystem. Works great on localhost and production equipment.

Is there code to save the first image to a database, and then read it back from there, instead. I am using Visual Studio 2008 Professional and C#.

Thank you for all of your great work!

27 May 2009 08:55 - Mike

@Ramona

Thanks for clarifying your issue and providing the solution. I'll amend the article to point this out. As far as saving the image to the database instead of the filesystem is concerned, there are thousands of samples all over the web. Here's one:

04 June 2009 12:03 - Mahesh Chavda

Great article man!!...

It's really really helpful.

Thanks

06 June 2009 16:41 - Jon Stranger

A very helpful article. In my case, however, I am using a dynamic image (using the Microsoft.Web.GeneratedImage.dll) inside an ASP.NET AJAX UpdatePanel. This works fine the first time, but after a partial update Jcrop no longer works - seemingly gets 'unwired'! I know this is not an issue for your code but would be interested to hear if you or any one else has tried using Jcrop in combination with an UpdatePanel. Or if there is a recommended way of 'rewiring' Jcrop (or any other Jquery plugin for that matter).

Jon

26 June 2009 12:44 - santhosh kumar

Its a nice article. In my point of view if you upload a image with the file name having spaces means its not working and also some works to do.
But its very very useful thing for upload and crop image in ,net

12 August 2009 05:50 - Felipe Lima

Hello,I found your code of great value and actually used it to accomplish something similar using jCrop and ASP.NET and ModalPopupExtender. I blogged about it at http://blog.felipel.com/post/Upload-and-Crop-Images-with-ASPNET-and-jCrop-Revisited!.aspx

Also, I'd like to make a comment about the method that actually crops the image. I believe you can return the image stream directly, instead of transfering the whole byte array into memory and then returning it, which might be an expensive operation, depending on the image size. I'm using the streamed version of your method. The only difference is that it returns "ms" itself, instead of "ms.GetBuffer()".

Thanks for sharing!Felipe

28 August 2009 02:19 - Nestcn

Thanks!Nestcn

29 August 2009 10:54 - Damodharan

All of your coding was working properly. If i include my master page to my application it doesn't working how configure that javascript files.

Please Help Me!

Thanks in Advance

29 August 2009 20:32 - Mike

@Damodharan

Read Ramona's comment.

02 September 2009 06:52 - stanly

Input string was not in a correct format.. I'm getting this error.. help me

03 October 2009 11:33 - Nageswaran

Hi Mikes, I am using this coding, after uploading the image. I was unable to crop that image. So please tell me where i am going wrong.

03 October 2009 23:20 - Mike

@Nageswaran

There could be a million reasons why you are experiencing problems. Post a question to the www.asp.net forums and please provide a full description of your problem. For example, what exactly do you mean by "unable to crop the image"? Does it fail to appear? Do you get an error message? If so, what is it and what line causes it?

05 October 2009 13:41 - raaz

ya it's look nice

06 October 2009 08:59 - gtaure

Hi,

Do you have any way of resizing/cropping it in proportional size?

Thanks for the code BTW.

06 October 2009 10:15 - Mike

@gtaure

The actual size of the cropped image is taken from the selected area and passed in here:

using (SD.Bitmap bmp = new SD.Bitmap(Width, Height))

If you want to change the Width and Height values, you can do so by intercepting them before they are passed into the Bitmap() constructor. If, for example, you decide that Width must be 200, then you would calculate what 200 is as a proportion of the actual width of the selected area, and use that proportion to alter the height. Something like this:

18 November 2009 12:22 - sam

i have checked its working properly in FireFox but not in IE..I hope you will lookafter for the IE issue..its urgentThanks

18 November 2009 19:33 - Mike

@sam

Thanks for pointing that out to me. During testing, I had IE8 compatability mode switched on. You are correct in that it doesn't work with JCrop 0.9.7 or earlier when Compatability Mode is switched off. A patch was released by the authors of JCrop and version 0.9.8 fixes the problem.

13 June 2010 15:24 - ayan

14 June 2010 16:52 - Mike

14 June 2010 20:11 - ayan

Hi, Actually I have implemented your code while saving an image file in the sql server 2008 database, retrieved it and then used cropping and saved it in the database using asp .net. It worked well. But when using with master page that has total sitemap based menu and security(not asp .net default security) save the image, retrieve it from database but the cropping panel not showing.

14 June 2010 20:28 - Mike

@ayan

I can't begin to guess where your problem lies. I suggest you post a question to the forums at www.asp.net with details of what you have done and what the problem is.

03 July 2010 19:42 - Guarav

its working 100% and such a great thought for me.............

Thanks

08 July 2010 15:03 - Hennie

Working for me... but....

Does anyone have an example on how I can resize the image to a max of 600 x 480 before uploading a photo to the server?

08 July 2010 18:40 - Mike

@Hennie

Resizing images on the user's PC is the jobn of a client side application. There's nothing that ASP.NET, the browser or javascript can do for you.

15 July 2010 13:21 - Peddiraju

Hi Great article it is really help alot me to finish My Task .but sme Logic required to apply this Article Code.

thanks

04 August 2010 11:25 - Dharmesh

Hi

can i use this under masterpage .......how to use crop image under masterpage

please help me

17 August 2010 15:14 - kavitha

Image crop is working in fire fox but its not working in IE browsers as per above comments i downloaded jquery.Jcrop-0.9.8 but i dont how to use this or integrate with the above code. please help us

17 August 2010 17:55 - Mike

@kavitha

Just replace the old Jcrop file with the new one. Nothing else is needed. You might have to refresh the page so that your temp cache is cleared out and the file updated.

27 September 2010 07:31 - manjay kumar

thanks

it is to good for beginner

30 September 2010 10:38 - Ibrahim Sidat

Great article! I got a PHP version of JCop but no ASP. This article was very helpful to me.

15 November 2010 13:40 - Dhanunjai

How to implement this is master page.............

01 December 2010 16:26 - Ravi

Thanks, you did a great job.

03 December 2010 13:43 - Eduardo Elarrat

Great article. But what if the image has a fixed size? I mean, in this example, the image can take over the whole page if its big enough, so I thought of having the image sizes a limit (ie. Width 640px, Height 480px). When i do this, the jcrop starts missing the cropping bounds, so that the cropped image is different from my crop selection. Is there a way to do this as I expect?

03 December 2010 13:56 - Mike

@Eduardo

I suppose it depends on how you are applying you limit.

11 January 2011 13:36 - Rahul Khakse

it amazing thank you for adding sir

11 February 2011 04:12 - Kanagaraj

It's Working Fine....Thanks.....You given great Article...

04 April 2011 12:52 - Antonio

Hi this don't work under masterpage. The same code on a simple page works ok. Any help?Thanks for that good work

06 April 2011 10:34 - elie

Hey Guys, I implemented your code and it looks great. But I am getting an error, in case I clicked "Crop" button without selecting part of the image Please advise

06 April 2011 15:39 - Mike

@elie

Look at previous comments. Your issue is covered there - you need to check that the HiddenFields have values in them.

06 April 2011 15:45 - Mike

@Antonio

Your issue is also covered in previous comments. You need to use Control.ClientID to work with MasterPages

06 August 2011 16:47 - Santosh

It's very nice Working Fine....Thanks.....

07 May 2012 12:11 - sandy

HI,Nice article to explain about crop image. But here your are storing image in a bitmap format. When you store a bitmap image it will take more size. But is it possible to store a JPEG image so that we can reduce the size.

08 May 2012 20:52 - Gregory F.

Thank you very much sir. The most useful article about image cropping on the web using all the latest and greatest technologies out there now.

29 June 2012 09:57 - Thuy

Thanks! Good article

16 August 2012 07:47 - TheDonSansone

sandy,I think you are mistaken in the storing of the cropped image. The code uses 'InterpolationMode.HighQualityBicubic' after it is cropped and saves out the resulting image in the same format the client uploaded as long as it matches one of the format params earlier in the code.

The cropper itself uses bitmap format only whilst cropping.

I have tested this and originally optimized images uploaded - then cropped to full size of original image, are only marginally larger than the original image (due to the QualityBicubic setting above of HIGH).

Works a treat Mike, if a little clunky, but great proof of concept.

The above should be improved by creating two storage locations. A 'tmp' for the working image being cropped and a different folder for the cropped image, as currently the folder saves both original and cropped in the same folder.

Then use 'imgpath' to store the finished image. This allows easy identification and removal if necessary of original uploads.

;) Martin.

17 October 2012 10:46 - keyvan

thank is very good and usefull

18 October 2012 16:10 - Sakthi

Hi this is working good in mozila and google chrome perfectly but it should not work in IE.I am using jquery 0.9.10 version onlycan u please give whats the reason?

20 October 2012 07:58 - Mike

@Sakthi,

You need version 0.9.8 or later

17 February 2013 11:19 - Lijin John

sir I a beginner with asp.net.My problem is that, When I use the following code I get an Error Message. Let me paste the code for You byte[] cropimage = Crop(path+image,a,b,c,d); When i type this code I get a RED line mark stating the error under the word--- Crop-----.can you please explain the reason why i get this type of error.I use VS2010 and i have used all the namespaces that u have asked to mention

07 March 2013 13:17 - madhu

hello can you give download link

31 March 2013 21:58 - Garry

This is an excellent article! Nice one @Mikesdotnetting.

29 May 2013 14:06 - Kürşat Vuruşan

Thanks! Nice and simple code.

29 July 2013 06:10 - Windyyyy

Very nice article. It works great on Chrome, Firefox but not in IE. I am using Jcrop v0.9.12 (build: 20130202) and IE version is 10.0.9200.16635. Jcrop selection in image doesn't work in IE. Can you pls shed some light on this problem if you know any workarounds for IE. Your help is appreciated.

19 August 2013 20:00 - djv

Thanks, works perfectly!!!! Also on IE version 10.0.9200.16660. Question to the people having trouble here: are you using the most recent jquery version?

20 August 2013 08:15 - djv

Yesterday I wrote the code was working properly on IE. Today, I am using another PC and the code did not work on IE. However, this could be solved by giving the image imgCrop a background color! See also for more information:http://deepliquid.com/content/Jcrop_Internet_Explorer_Notes.html

20 August 2013 08:20 - djv

correction to my post few minutes ago. Doesn't seem to work yet properly. Am working on it.

23 August 2013 14:02 - khristian

Excellent article. COngratulation buddy.

23 September 2013 08:01 - AlexP

Great article, gave me a great starting point, cheers for that mate!A few things which I had to fix in order to fit into my project:- avoid postbacks when actually cropping- loading and reloading image without postbacks (i used uploadify plugin) and that led to some issues with JCrop.I will post a quick article how to resolve those issues and will link back to your as the original source if you are okay with that.Thanks again!

11 November 2014 12:19 - Minhaj

Thanks for article. But how can we re-size crop area?

11 November 2014 20:10 - Mike

@Minhaj,

I have no idea. I haven't use JCrop for about 5 years.

10 December 2014 08:29 - lovepreet

There is an error while i'm using this code i.e.

'string' does not contain a definition for 'GetExtension' and no extension method 'GetExtension' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)

How can i remove this error..??

10 December 2014 17:12 - Mike

@lovepreet

GetExtension is a static method on the Path class:

Path.GetExtension(...)

Check the code in the article against what you have typed.

24 October 2015 09:04 - JamesCui

Thanks

Unfortunately, something went wrong and your message or comments have not been submitted
successfully. I'll try to fix whatever the problem is as soon as I can.

Thanks for your comments. They have been successfully sent to me. I will try to respond
if necessary as soon as I can.