Create ASP.net control for Image resizer and cropper keeping aspect ratio

Published in CodeProject as well.

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 cropped 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 need 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 resize the uploaded image into my required size keeping the correct ratio of the original image and it’s quality. After that, user has 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 chance to make different crop again and upload the required size in 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
        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 parameter 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 Git Hub for the help of other programmer. 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. A 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 a 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:

Capture

Here’s a hidden filed 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

Referance: 

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

Leave a comment