Saturday, May 25, 2019

jQuery Resize and Compress Image

This is a jQuery technique to resize image using canvas and Image object. You can resize image as you wanted.
Below is a jQuery class that will actually convert file to blob after resize done:
class ImageResizer {
  "use strict"

  static _initDone = false;

  static resize(file, options, callback) {
    this._init();

    var thisOptions = {
      maxWidth: 1200
    };
    $.extend( thisOptions, options );

    var width = thisOptions.maxWidth;
    var fileName = file.name;
    var fileType = file.type;

    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = function(event) {
      const img = new Image();
      img.src = event.target.result;
      img.onload = function() {
        if (width > img.width) {
          width = img.width;
        }
        const elem = document.createElement('canvas');
        elem.width = width;
        const scaleFactor = width / img.width;
        elem.height = img.height * scaleFactor;
        const ctx = elem.getContext('2d');
        // img.width and img.height will contain the original dimensions
        ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);

        // function(callback_function, file_type, quality_0_to_1)
        ctx.canvas.toBlob(function(blob) {
          blob.lastModifiedDate = Date.now();
          blob.name = fileName;
          blob.width = width;
          blob.height = img.height * scaleFactor;

          callback(undefined, blob);
        }, fileType, 1);
      },
        reader.onerror = function(error) {
          callback(error);
        };
    };
  }

  static _init() {
    if (!this._initDone) {
      this._initDone = true;

      if (!HTMLCanvasElement.prototype.toBlob) {
        Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
          value: function (callback, type, quality) {
            var dataURL = this.toDataURL(type, quality).split(',')[1];
            setTimeout(function() {
              var binStr = atob( dataURL ), len = binStr.length, arr = new Uint8Array(len);
              for (var i = 0; i < len; i++ ) {
                arr[i] = binStr.charCodeAt(i);
              }
              callback( new Blob( [arr], {type: type || 'image/png'} ) );
            });
          }
        });
      }
    }
  }
}
And you can use this from html page as below:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Image Resize Component</title>
  <script src="//code.jquery.com/jquery-1.7.2.min.js"></script>
  <script src="image-resizer.js"></script>
  <script type="text/javascript">
    $(document).on('ready', function() {
      var image = $("#PhotoPicker");
      image.on('change', function(e) {
        $("canvas").remove();

        ImageResizer.resize(e.target.files[0], {maxWidth: 300}, function(error, blob) {
          const canvas = document.createElement('canvas');
          canvas.width = blob.width
          canvas.height = blob.height;
          const context = canvas.getContext('2d');

          var img = new Image();
          img.onload = function(){
            context.drawImage(img, 0, 0, blob.width, blob.height);
          };
          img.onerror = function(e){
            console.log('Error during loading image:', e);
          };
          img.src = URL.createObjectURL(blob);

          document.body.appendChild(canvas);
        });
      });
    });
  </script>
</head>
<body>
<input type="file" id="PhotoPicker" accept="image/*" capture="camera"><br/><br/>
</body>
</html>

1 comment: