/*!
 * Image Compressor v1.1.4
 * https://xkeshi.github.io/image-compressor
 *
 * Copyright 2017-present Chen Fengyuan
 * Released under the MIT license
 *
 * Date: 2018-06-20T07:28:41.051Z
 */

(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
	typeof define === 'function' && define.amd ? define(factory) :
	(global.ImageCompressor = factory());
}(this, (function () { 'use strict';

	function createCommonjsModule(fn, module) {
		return module = { exports: {} }, fn(module, module.exports), module.exports;
	}

	var canvasToBlob = createCommonjsModule(function (module) {
	(function (window) {

	  var CanvasPrototype =
	    window.HTMLCanvasElement && window.HTMLCanvasElement.prototype;
	  var hasBlobConstructor =
	    window.Blob &&
	    (function () {
	      try {
	        return Boolean(new Blob())
	      } catch (e) {
	        return false
	      }
	    })();
	  var hasArrayBufferViewSupport =
	    hasBlobConstructor &&
	    window.Uint8Array &&
	    (function () {
	      try {
	        return new Blob([new Uint8Array(100)]).size === 100
	      } catch (e) {
	        return false
	      }
	    })();
	  var BlobBuilder =
	    window.BlobBuilder ||
	    window.WebKitBlobBuilder ||
	    window.MozBlobBuilder ||
	    window.MSBlobBuilder;
	  var dataURIPattern = /^data:((.*?)(;charset=.*?)?)(;base64)?,/;
	  var dataURLtoBlob =
	    (hasBlobConstructor || BlobBuilder) &&
	    window.atob &&
	    window.ArrayBuffer &&
	    window.Uint8Array &&
	    function (dataURI) {
	      var matches,
	        mediaType,
	        isBase64,
	        dataString,
	        byteString,
	        arrayBuffer,
	        intArray,
	        i,
	        bb;
	      // Parse the dataURI components as per RFC 2397
	      matches = dataURI.match(dataURIPattern);
	      if (!matches) {
	        throw new Error('invalid data URI')
	      }
	      // Default to text/plain;charset=US-ASCII
	      mediaType = matches[2]
	        ? matches[1]
	        : 'text/plain' + (matches[3] || ';charset=US-ASCII');
	      isBase64 = !!matches[4];
	      dataString = dataURI.slice(matches[0].length);
	      if (isBase64) {
	        // Convert base64 to raw binary data held in a string:
	        byteString = atob(dataString);
	      } else {
	        // Convert base64/URLEncoded data component to raw binary:
	        byteString = decodeURIComponent(dataString);
	      }
	      // Write the bytes of the string to an ArrayBuffer:
	      arrayBuffer = new ArrayBuffer(byteString.length);
	      intArray = new Uint8Array(arrayBuffer);
	      for (i = 0; i < byteString.length; i += 1) {
	        intArray[i] = byteString.charCodeAt(i);
	      }
	      // Write the ArrayBuffer (or ArrayBufferView) to a blob:
	      if (hasBlobConstructor) {
	        return new Blob([hasArrayBufferViewSupport ? intArray : arrayBuffer], {
	          type: mediaType
	        })
	      }
	      bb = new BlobBuilder();
	      bb.append(arrayBuffer);
	      return bb.getBlob(mediaType)
	    };
	  if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {
	    if (CanvasPrototype.mozGetAsFile) {
	      CanvasPrototype.toBlob = function (callback, type, quality) {
	        var self = this;
	        setTimeout(function () {
	          if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {
	            callback(dataURLtoBlob(self.toDataURL(type, quality)));
	          } else {
	            callback(self.mozGetAsFile('blob', type));
	          }
	        });
	      };
	    } else if (CanvasPrototype.toDataURL && dataURLtoBlob) {
	      CanvasPrototype.toBlob = function (callback, type, quality) {
	        var self = this;
	        setTimeout(function () {
	          callback(dataURLtoBlob(self.toDataURL(type, quality)));
	        });
	      };
	    }
	  }
	  if (typeof undefined === 'function' && undefined.amd) {
	    undefined(function () {
	      return dataURLtoBlob
	    });
	  } else if (module.exports) {
	    module.exports = dataURLtoBlob;
	  } else {
	    window.dataURLtoBlob = dataURLtoBlob;
	  }
	})(window);
	});

	/* globals Blob */
	var toString = Object.prototype.toString;

	var isBlob = function (x) {
		return x instanceof Blob || toString.call(x) === '[object Blob]';
	};

	var DEFAULTS = {
	  /**
	   * Indicates if read the image's Exif Orientation information,
	   * and then rotate or flip the image automatically.
	   * @type {boolean}
	   */
	  checkOrientation: true,

	  /**
	   * The max width of the output image.
	   * @type {number}
	   */
	  maxWidth: Infinity,

	  /**
	   * The max height of the output image.
	   * @type {number}
	   */
	  maxHeight: Infinity,

	  /**
	   * The min width of the output image.
	   * @type {number}
	   */
	  minWidth: 0,

	  /**
	   * The min height of the output image.
	   * @type {number}
	   */
	  minHeight: 0,

	  /**
	   * The width of the output image.
	   * If not specified, the natural width of the source image will be used.
	   * @type {number}
	   */
	  width: undefined,

	  /**
	   * The height of the output image.
	   * If not specified, the natural height of the source image will be used.
	   * @type {number}
	   */
	  height: undefined,

	  /**
	   * The quality of the output image.
	   * It must be a number between `0` and `1`,
	   * and only available for `image/jpeg` and `image/webp` images.
	   * Check out {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob canvas.toBlob}.
	   * @type {number}
	   */
	  quality: 0.8,

	  /**
	   * The mime type of the output image.
	   * By default, the original mime type of the source image file will be used.
	   * @type {string}
	   */
	  mimeType: 'auto',

	  /**
	   * PNG files over this value (5M by default) will be converted to JPEGs.
	   * To disable this, just set the value to `Infinity`.
	   * Check out {@link https://github.com/xkeshi/image-compressor/issues/2 #2}.
	   * @type {number}
	   */
	  convertSize: 5000000,

	  /**
	   * The hook function to execute before draw the image into the canvas for compression.
	   * @type {Function}
	   * @param {CanvasRenderingContext2D} context - The 2d rendering context of the canvas.
	   * @param {HTMLCanvasElement} canvas - The canvas for compression.
	   * @example
	   * function (context, canvas) { context.fillStyle = '#fff' }
	   */
	  beforeDraw: null,

	  /**
	   * The hook function to execute after drew the image into the canvas for compression.
	   * @type {Function}
	   * @param {CanvasRenderingContext2D} context - The 2d rendering context of the canvas.
	   * @param {HTMLCanvasElement} canvas - The canvas for compression.
	   * @example
	   * function (context, canvas) { context.filter = grayscale(100%) }
	   */
	  drew: null,

	  /**
	   * The hook function to execute when success to compress the image.
	   * @type {Function}
	   * @param {File} file - The compressed image File object.
	   * @example
	   * function (file) { console.log(file) }
	   */
	  success: null,

	  /**
	   * The hook function to execute when fail to compress the image.
	   * @type {Function}
	   * @param {Error} err - An Error object.
	   * @example
	   * function (err) { console.log(err.message) }
	   */
	  error: null
	};

	var REGEXP_IMAGE_TYPE = /^image\/.+$/;

	/**
	 * Check if the given value is a mime type of image.
	 * @param {*} value - The value to check.
	 * @returns {boolean} Returns `true` if the given is a mime type of image, else `false`.
	 */
	function isImageType(value) {
	  return REGEXP_IMAGE_TYPE.test(value);
	}

	/**
	 * Convert image type to extension.
	 * @param {string} value - The image type to convert.
	 * @param {boolean} [includeDot=true] - Include a leading dot or not.
	 * @returns {boolean} Returns the image extension.
	 */
	function imageTypeToExtension(value) {
	  var includeDot = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;

	  var extension = isImageType(value) ? value.substr(6) : '';

	  if (extension === 'jpeg') {
	    extension = 'jpg';
	  }

	  if (extension && includeDot) {
	    extension = '.' + extension;
	  }

	  return extension;
	}

	var fromCharCode = String.fromCharCode;

	/**
	 * Get string from char code in data view.
	 * @param {DataView} dataView - The data view for read.
	 * @param {number} start - The start index.
	 * @param {number} length - The read length.
	 * @returns {string} The read result.
	 */

	function getStringFromCharCode(dataView, start, length) {
	  var str = '';
	  var i = void 0;

	  length += start;

	  for (i = start; i < length; i += 1) {
	    str += fromCharCode(dataView.getUint8(i));
	  }

	  return str;
	}

	var _window = window,
	    btoa = _window.btoa;

	/**
	 * Transform array buffer to Data URL.
	 * @param {ArrayBuffer} arrayBuffer - The array buffer to transform.
	 * @param {string} mimeType - The mime type of the Data URL.
	 * @returns {string} The result Data URL.
	 */

	function arrayBufferToDataURL(arrayBuffer, mimeType) {
	  var uint8 = new Uint8Array(arrayBuffer);
	  var data = '';

	  // TypedArray.prototype.forEach is not supported in some browsers as IE.
	  if (typeof uint8.forEach === 'function') {
	    uint8.forEach(function (value) {
	      data += fromCharCode(value);
	    });
	  } else {
	    var length = uint8.length;


	    for (var i = 0; i < length; i += 1) {
	      data += fromCharCode(uint8[i]);
	    }
	  }

	  return 'data:' + mimeType + ';base64,' + btoa(data);
	}

	/**
	 * Get orientation value from given array buffer.
	 * @param {ArrayBuffer} arrayBuffer - The array buffer to read.
	 * @returns {number} The read orientation value.
	 */
	function getOrientation(arrayBuffer) {
	  var dataView = new DataView(arrayBuffer);
	  var orientation = void 0;
	  var littleEndian = void 0;
	  var app1Start = void 0;
	  var ifdStart = void 0;

	  // Only handle JPEG image (start by 0xFFD8)
	  if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
	    var length = dataView.byteLength;
	    var offset = 2;

	    while (offset < length) {
	      if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
	        app1Start = offset;
	        break;
	      }

	      offset += 1;
	    }
	  }

	  if (app1Start) {
	    var exifIDCode = app1Start + 4;
	    var tiffOffset = app1Start + 10;

	    if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
	      var endianness = dataView.getUint16(tiffOffset);

	      littleEndian = endianness === 0x4949;

	      if (littleEndian || endianness === 0x4D4D /* bigEndian */) {
	          if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
	            var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);

	            if (firstIFDOffset >= 0x00000008) {
	              ifdStart = tiffOffset + firstIFDOffset;
	            }
	          }
	        }
	    }
	  }

	  if (ifdStart) {
	    var _length = dataView.getUint16(ifdStart, littleEndian);
	    var _offset = void 0;
	    var i = void 0;

	    for (i = 0; i < _length; i += 1) {
	      _offset = ifdStart + i * 12 + 2;

	      if (dataView.getUint16(_offset, littleEndian) === 0x0112 /* Orientation */) {
	          // 8 is the offset of the current tag's value
	          _offset += 8;

	          // Get the original orientation value
	          orientation = dataView.getUint16(_offset, littleEndian);

	          // Override the orientation with its default value
	          dataView.setUint16(_offset, 1, littleEndian);
	          break;
	        }
	    }
	  }

	  return orientation;
	}

	/**
	 * Parse Exif Orientation value.
	 * @param {number} orientation - The orientation to parse.
	 * @returns {Object} The parsed result.
	 */
	function parseOrientation(orientation) {
	  var rotate = 0;
	  var scaleX = 1;
	  var scaleY = 1;

	  switch (orientation) {
	    // Flip horizontal
	    case 2:
	      scaleX = -1;
	      break;

	    // Rotate left 180°
	    case 3:
	      rotate = -180;
	      break;

	    // Flip vertical
	    case 4:
	      scaleY = -1;
	      break;

	    // Flip vertical and rotate right 90°
	    case 5:
	      rotate = 90;
	      scaleY = -1;
	      break;

	    // Rotate right 90°
	    case 6:
	      rotate = 90;
	      break;

	    // Flip horizontal and rotate right 90°
	    case 7:
	      rotate = 90;
	      scaleX = -1;
	      break;

	    // Rotate left 90°
	    case 8:
	      rotate = -90;
	      break;

	    default:
	  }

	  return {
	    rotate: rotate,
	    scaleX: scaleX,
	    scaleY: scaleY
	  };
	}

	var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/i;

	/**
	 * Normalize decimal number.
	 * Check out {@link http://0.30000000000000004.com/}
	 * @param {number} value - The value to normalize.
	 * @param {number} [times=100000000000] - The times for normalizing.
	 * @returns {number} Returns the normalized number.
	 */
	function normalizeDecimalNumber(value) {
	  var times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000;

	  return REGEXP_DECIMALS.test(value) ? Math.round(value * times) / times : value;
	}

	var classCallCheck = function (instance, Constructor) {
	  if (!(instance instanceof Constructor)) {
	    throw new TypeError("Cannot call a class as a function");
	  }
	};

	var createClass = function () {
	  function defineProperties(target, props) {
	    for (var i = 0; i < props.length; i++) {
	      var descriptor = props[i];
	      descriptor.enumerable = descriptor.enumerable || false;
	      descriptor.configurable = true;
	      if ("value" in descriptor) descriptor.writable = true;
	      Object.defineProperty(target, descriptor.key, descriptor);
	    }
	  }

	  return function (Constructor, protoProps, staticProps) {
	    if (protoProps) defineProperties(Constructor.prototype, protoProps);
	    if (staticProps) defineProperties(Constructor, staticProps);
	    return Constructor;
	  };
	}();

	var _extends = Object.assign || function (target) {
	  for (var i = 1; i < arguments.length; i++) {
	    var source = arguments[i];

	    for (var key in source) {
	      if (Object.prototype.hasOwnProperty.call(source, key)) {
	        target[key] = source[key];
	      }
	    }
	  }

	  return target;
	};

	var _window$1 = window,
	    ArrayBuffer$1 = _window$1.ArrayBuffer,
	    FileReader = _window$1.FileReader;

	var URL = window.URL || window.webkitURL;
	var REGEXP_EXTENSION = /\.\w+$/;

	/**
	 * Creates a new image compressor.
	 * @class
	 */

	var ImageCompressor = function () {
	  /**
	   * The constructor of ImageCompressor.
	   * @param {File|Blob} file - The target image file for compressing.
	   * @param {Object} [options] - The options for compressing.
	   */
	  function ImageCompressor(file, options) {
	    classCallCheck(this, ImageCompressor);

	    this.result = null;

	    if (file) {
	      this.compress(file, options);
	    }
	  }

	  /**
	   * The main compress method.
	   * @param {File|Blob} file - The target image file for compressing.
	   * @param {Object} [options] - The options for compressing.
	   * @returns {Promise} - A Promise instance.
	   */


	  createClass(ImageCompressor, [{
	    key: 'compress',
	    value: function compress(file, options) {
	      var _this = this;

	      var image = new Image();

	      options = _extends({}, DEFAULTS, options);

	      if (!ArrayBuffer$1) {
	        options.checkOrientation = false;
	      }

	      return new Promise(function (resolve, reject) {
	        if (!isBlob(file)) {
	          reject(new Error('The first argument must be a File or Blob object.'));
	          return;
	        }

	        var mimeType = file.type;

	        if (!isImageType(mimeType)) {
	          reject(new Error('The first argument must be an image File or Blob object.'));
	          return;
	        }

	        if (!URL && !FileReader) {
	          reject(new Error('The current browser does not support image compression.'));
	          return;
	        }

	        if (URL && !options.checkOrientation) {
	          resolve({
	            url: URL.createObjectURL(file)
	          });
	        } else if (FileReader) {
	          var reader = new FileReader();
	          var checkOrientation = options.checkOrientation && mimeType === 'image/jpeg';

	          reader.onload = function (_ref) {
	            var target = _ref.target;
	            var result = target.result;


	            resolve(checkOrientation ? _extends({
	              url: arrayBufferToDataURL(result, mimeType)
	            }, parseOrientation(getOrientation(result))) : {
	              url: result
	            });
	          };
	          reader.onabort = function () {
	            reject(new Error('Aborted to load the image with FileReader.'));
	          };
	          reader.onerror = function () {
	            reject(new Error('Failed to load the image with FileReader.'));
	          };

	          if (checkOrientation) {
	            reader.readAsArrayBuffer(file);
	          } else {
	            reader.readAsDataURL(file);
	          }
	        }
	      }).then(function (data) {
	        return new Promise(function (resolve, reject) {
	          image.onload = function () {
	            return resolve(_extends({}, data, {
	              naturalWidth: image.naturalWidth,
	              naturalHeight: image.naturalHeight
	            }));
	          };
	          image.onabort = function () {
	            reject(new Error('Aborted to load the image.'));
	          };
	          image.onerror = function () {
	            reject(new Error('Failed to load the image.'));
	          };
	          image.alt = file.name;
	          image.src = data.url;
	        });
	      }).then(function (_ref2) {
	        var naturalWidth = _ref2.naturalWidth,
	            naturalHeight = _ref2.naturalHeight,
	            _ref2$rotate = _ref2.rotate,
	            rotate = _ref2$rotate === undefined ? 0 : _ref2$rotate,
	            _ref2$scaleX = _ref2.scaleX,
	            scaleX = _ref2$scaleX === undefined ? 1 : _ref2$scaleX,
	            _ref2$scaleY = _ref2.scaleY,
	            scaleY = _ref2$scaleY === undefined ? 1 : _ref2$scaleY;
	        return new Promise(function (resolve) {
	          var canvas = document.createElement('canvas');
	          var context = canvas.getContext('2d');
	          var aspectRatio = naturalWidth / naturalHeight;
	          var maxWidth = Math.max(options.maxWidth, 0) || Infinity;
	          var maxHeight = Math.max(options.maxHeight, 0) || Infinity;
	          var minWidth = Math.max(options.minWidth, 0) || 0;
	          var minHeight = Math.max(options.minHeight, 0) || 0;
	          var width = naturalWidth;
	          var height = naturalHeight;

	          if (maxWidth < Infinity && maxHeight < Infinity) {
	            if (maxHeight * aspectRatio > maxWidth) {
	              maxHeight = maxWidth / aspectRatio;
	            } else {
	              maxWidth = maxHeight * aspectRatio;
	            }
	          } else if (maxWidth < Infinity) {
	            maxHeight = maxWidth / aspectRatio;
	          } else if (maxHeight < Infinity) {
	            maxWidth = maxHeight * aspectRatio;
	          }

	          if (minWidth > 0 && minHeight > 0) {
	            if (minHeight * aspectRatio > minWidth) {
	              minHeight = minWidth / aspectRatio;
	            } else {
	              minWidth = minHeight * aspectRatio;
	            }
	          } else if (minWidth > 0) {
	            minHeight = minWidth / aspectRatio;
	          } else if (minHeight > 0) {
	            minWidth = minHeight * aspectRatio;
	          }

	          if (options.width > 0) {
	            var _options = options;
	            width = _options.width;

	            height = width / aspectRatio;
	          } else if (options.height > 0) {
	            var _options2 = options;
	            height = _options2.height;

	            width = height * aspectRatio;
	          }

	          width = Math.min(Math.max(width, minWidth), maxWidth);
	          height = Math.min(Math.max(height, minHeight), maxHeight);

	          var destX = -width / 2;
	          var destY = -height / 2;
	          var destWidth = width;
	          var destHeight = height;

	          if (Math.abs(rotate) % 180 === 90) {
	            var _width$height = {
	              width: height,
	              height: width
	            };
	            width = _width$height.width;
	            height = _width$height.height;
	          }

	          canvas.width = normalizeDecimalNumber(width);
	          canvas.height = normalizeDecimalNumber(height);

	          if (!isImageType(options.mimeType)) {
	            options.mimeType = file.type;
	          }

	          var defaultFillStyle = 'transparent';

	          // Converts PNG files over the `convertSize` to JPEGs.
	          if (file.size > options.convertSize && options.mimeType === 'image/png') {
	            defaultFillStyle = '#fff';
	            options.mimeType = 'image/jpeg';
	          }

	          // Override the default fill color (#000, black)
	          context.fillStyle = defaultFillStyle;
	          context.fillRect(0, 0, width, height);
	          context.save();
	          context.translate(width / 2, height / 2);
	          context.rotate(rotate * Math.PI / 180);
	          context.scale(scaleX, scaleY);

	          if (options.beforeDraw) {
	            options.beforeDraw.call(_this, context, canvas);
	          }

	          context.drawImage(image, Math.floor(normalizeDecimalNumber(destX)), Math.floor(normalizeDecimalNumber(destY)), Math.floor(normalizeDecimalNumber(destWidth)), Math.floor(normalizeDecimalNumber(destHeight)));

	          if (options.drew) {
	            options.drew.call(_this, context, canvas);
	          }

	          context.restore();

	          var done = function done(result) {
	            resolve({
	              naturalWidth: naturalWidth,
	              naturalHeight: naturalHeight,
	              result: result
	            });
	          };

	          if (canvas.toBlob) {
	            canvas.toBlob(done, options.mimeType, options.quality);
	          } else {
	            done(canvasToBlob(canvas.toDataURL(options.mimeType, options.quality)));
	          }
	        });
	      }).then(function (_ref3) {
	        var naturalWidth = _ref3.naturalWidth,
	            naturalHeight = _ref3.naturalHeight,
	            result = _ref3.result;

	        if (URL && !options.checkOrientation) {
	          URL.revokeObjectURL(image.src);
	        }

	        if (result) {
	          // Returns original file if the result is greater than it and without size related options
	          if (result.size > file.size && options.mimeType === file.type && !(options.width > naturalWidth || options.height > naturalHeight || options.minWidth > naturalWidth || options.minHeight > naturalHeight)) {
	            result = file;
	          } else {
	            var date = new Date();

	            result.lastModified = date.getTime();
	            result.lastModifiedDate = date;
	            result.name = file.name;

	            // Convert the extension to match its type
	            if (result.name && result.type !== file.type) {
	              result.name = result.name.replace(REGEXP_EXTENSION, imageTypeToExtension(result.type));
	            }
	          }
	        } else {
	          // Returns original file if the result is null in some cases.
	          result = file;
	        }

	        _this.result = result;

	        if (options.success) {
	          options.success.call(_this, result);
	        }

	        return Promise.resolve(result);
	      }).catch(function (err) {
	        if (!options.error) {
	          throw err;
	        }

	        options.error.call(_this, err);
	      });
	    }
	  }]);
	  return ImageCompressor;
	}();

	return ImageCompressor;

})));
