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

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

5.00/5 (5 votes)
29 Jul 2017CPOL3 min read 12.3K   627  
How to create an ASP.NET control for image resizer and cropper keeping aspect ratio

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 made a control which forcefully resized 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)

Resizing Algorithm

All the process is done with JavaScript, JQuery and AJAX. So, there’s no postback 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 do 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 small 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 small 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 small 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 my Git Hub account  as well for the help of other programmers. I am now showing how to use the control:

Source Code Structure

3

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 container 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 are your required image dimensions. 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:

JavaScript
<%@ Control Language="C#" AutoEventWireup="true" 
CodeFile="Control_CMS_ImageResizeNCropp_CS.ascx.cs" Inherits="Control_CMS_ImageResizeNCropp_CS" %>
<div class="row">
    <div class="col-xs-12">
        <asp:Image ID="imgResultImage" runat="server" 
         style="display:none;border: rgba(128, 128, 128, 0.33) dashed 1px;" />
        <asp:HiddenField ID="hdnResultImage" runat="server" />
        
    </div>
    <div class="col-xs-12" style="margin-top:5px;">
        <a href='/F-ImageUploader/CMS_ImageResizeNCropp_CS.aspx?controlID=
                <%= this.ID %>&width=<%= Width %>&height=<%= Height %>'  
            class="imageUpload btn btn-primary fancybox.iframe 
            <%= CssClass %>" ><%= ButtonName %></a>  
    </div>
</div>

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

Source Code

https://github.com/debchy/ResizeNCrop

Reference

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

 

Image 9 Image 10

License

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