Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / CSS

Create ASP.NET Control for Image Resizer and Cropper Keeping Aspect Ratio

5.00/5 (1 vote)
8 Jan 2020CPOL3 min read 3.7K  
How to create an ASP.NET control for image resizer and cropper keeping aspect ratio

Overview

We had a long term problem about image resizing and cropping. Our problem was if we resize in server side, the image quality demolished and we can’t crop according to aspect ratio as uploading image can be in any size and any dimension. For a B2B type of project, we faced it a lot as user of the website needs to upload image, they are not resizing by themselves and uploading big images for their post which was making the site slow to load.

Finally, I make a control which forcefully resizes the uploaded image into my required size keeping the correct ratio of the original image and its quality. After that, user has the option to choose their cropping portion.

Here’s my canvas where user can do cropping:

pastedImage

After cropping, they can review the cropped image and have a chance to make a different crop again and upload the required size in a proportional way (keeping the aspect ratio that I have fixed for the image).

pastedImage (1)

After uploading the image, it will show a preview of the uploaded image without page refreshing.

pastedImage (2)

Image Resizing Algorithm

All the process is done with JavaScript, JQuery and AJAX. So, there’s no post back or page refresh needed and this resizing, cropping, uploading procedure is now more professional. I can set both portrait and landscape image ratio to crop without distorting the current ratio of the image. For that, I have developed my own resizing algorithm and implemented with JavaScript. Here’s the algorithm in JavaScript format.

JavaScript
      function ImageResizer(canvasWidth, canvasHeight, sourceWidth,
      sourceHeight, destinationX, destinationY, destinationWidth, destinationHeight) {
          var canvasRatio = canvasWidth / canvasHeight;
          var sourceRatio = sourceWidth / sourceHeight;

          if (sourceWidth > canvasWidth || sourceHeight > canvasHeight) {
              //if the image does not fit into the required canvas
              if (canvasRatio >= 1) {
                  //if the canvas is landscape
                  if (sourceRatio <= 1) {
                      //if the image is portrait
                      destinationHeight = canvasHeight;
                      destinationWidth = destinationHeight * sourceRatio;
                      destinationX = (canvasWidth - destinationWidth) / 2;
                      destinationY = 0;
                  }
                  else if (sourceRatio > 1) {
                      //if the image is landscape
                      if (canvasRatio < sourceRatio) {
                          //make the landscape image fit inside the required Canvas.
                          //In this case, ImageX is bigger than
                          //canvasWidth & ImageY is smaller than canvasHeight
                          destinationWidth = canvasWidth;
                          destinationHeight = destinationWidth / sourceRatio;
                          destinationX = 0;
                          destinationY = (canvasHeight - destinationHeight) / 2;
                      } else if (canvasRatio >= sourceRatio) {
                          //In this case, ImageY is bigger than canvasHeight &
                          //ImageX is smaller than canvasWidth
                          destinationHeight = canvasHeight;
                          destinationWidth = destinationHeight * sourceRatio;
                          destinationX = (canvasWidth - destinationWidth) / 2;
                          destinationY = 0;
                      }
                  }
              }
              else if (canvasRatio < 1) {
                  //if the canvas is portrait
                  if (sourceRatio >= 1) {
                      //if the image is landscape
                      destinationWidth = canvasWidth;
                      destinationHeight = destinationWidth / sourceRatio;
                      destinationX = 0;
                      destinationY = (canvasHeight - destinationHeight) / 2;
                  }
                  else if (sourceRatio < 1) {
                      //if the image is portrait
                      if (canvasRatio > sourceRatio) {
                          //make the portrait image fit inside the required Canvas.
                          //In this case, ImageY is bigger than
                          //canvasHeight & ImageX is small than canvasWidth
                          destinationHeight = canvasHeight;
                          destinationWidth = destinationHeight * sourceRatio;
                          destinationX = (canvasWidth - destinationWidth) / 2;
                          destinationY = 0;
                      } else if (canvasRatio <= sourceRatio) {
                          //In this case, ImageX is bigger than canvasWidth &
                          //ImageY is smaller than canvasHeight

                          destinationWidth = canvasWidth;
                          destinationHeight = destinationWidth / sourceRatio;
                          destinationX = 0;
                          destinationY = (canvasHeight - destinationHeight) / 2;
                      }
                  }
              }
          }
          else {
              //image will directly fit inside the canvas
              destinationWidth = sourceWidth;
              destinationHeight = sourceHeight;
              destinationX = (canvasWidth - sourceWidth) / 2;
              destinationY = (canvasHeight - sourceHeight) / 2;
          }

          console.log("img.width=" + sourceWidth + " img.height=" +
          sourceHeight + " destinationX=" + destinationX + " destinationY=" +
          destinationY + " destinationWidth=" + destinationWidth +
          " destinationHeight=" + destinationHeight);
}

To understand the algorithm, you have to consider the below image:

resulting image

After getting all appropriate parameters, you have to pass the values to a JavaScript method named CanvasRenderingContext2D.drawImage() of the Canvas 2D API to draw an image onto the canvas.

Along with my resizer algorithm, I have applied a JQuery cropping API called “jquery.Jcrop.js”.

I have uploaded all my source code for this control on Github for the help of other programmers. I am now showing the folder structure of the control:

3

Source code structure

The F-ImageUploader is the folder which contains all the required files for the control.

  1. ImageResizeNCrop.js contains all JavaScript code for resizing, cropping and saving.
  2. An ASP.NET Handler file (HandlerImageUploader.ashx) is used to save the file with Ajax.
  3. CMS_ImageResizeNCropp_CS.aspx and CMS_ImageResizeNCropp_VB.aspx are the containers for control which will open in fancybox iframe.
  4. ASP.NET custom controller Control_CMS_ImageResizeNCropp_CS.ascx and Control_CMS_ImageResizeNCropp_VB.ascx are used to quickly plug and play the control by dragging from VS Solution Explorer.
  5. Images will save on /Admin/Content folder.

In this article, I am not going to explain each and every code. If you are an ASP.NET and JavaScript developer, you can easily understand the source code from the hints and pin points that I am explaining here.

How to Use the Controls on Web Page?

1

4

Here, Width and Height is your required image dimension. The image will be cropped according to that ratio. ButtonName is your required text to show on button. Also, you can pass your CSS to that control by CssClass property.

2

How to Get the Uploaded Image From the Control?

First, have a look at controller markup:

HTML
<img data-attachment-id="1262"
data-permalink="https://debchy.wordpress.com/2017/07/29/
create-asp-net-control-for-image-resizer-and-cropper-keeping-aspect-ratio/capture-2/"
data-orig-file="https://debchy.files.wordpress.com/2017/07/capture1.png"
data-orig-size="656,274" data-comments-opened="1"
data-image-meta="{"aperture":"0","credit":"","camera":"","caption":"",
"created_timestamp":"0","copyright":"","focal_length":"0","iso":"0",
"shutter_speed":"0","title":"","orientation":"0"}" data-image-title="Capture"
data-image-description=""
data-medium-file="https://debchy.files.wordpress.com/2017/07/capture1.png?w=300"
data-large-file="https://debchy.files.wordpress.com/2017/07/capture1.png?w=656"
class="alignnone size-full wp-image-1262"
src="https://debchy.files.wordpress.com/2017/07/capture1.png?w=809" alt="Capture"
srcset="https://debchy.files.wordpress.com/2017/07/capture1.png 656w,
https://debchy.files.wordpress.com/2017/07/capture1.png?w=150 150w,
https://debchy.files.wordpress.com/2017/07/capture1.png?w=300 300w"
sizes="(max-width: 656px) 100vw, 656px"   />

Here’s a hidden field named hdnResultImage. You can access the field from the control object as the hidden field is a public property.

Source Code

References

  1. Javascript drawImage https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/drawImage
  2. Jquery Cropper API: http://jcrop.com

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)