From 616ccc861eeaaf159c1ba54ad78d79299d6d313f Mon Sep 17 00:00:00 2001 From: Chen Fengyuan Date: Sat, 25 Feb 2023 19:37:33 +0800 Subject: [PATCH] build: release 1.2.0 --- CHANGELOG.md | 2 +- dist/compressor.common.js | 1145 +++++++++++++++---------------------- dist/compressor.esm.js | 1145 +++++++++++++++---------------------- dist/compressor.js | 1145 +++++++++++++++---------------------- dist/compressor.min.js | 6 +- docs/index.html | 2 +- docs/js/compressor.js | 1145 +++++++++++++++---------------------- package-lock.json | 290 +++++----- package.json | 14 +- 9 files changed, 2075 insertions(+), 2819 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d65caf3..bb5665f 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## next +## 1.2.0 (Feb 25, 2023) - Add a new option: `retainExif` (#159). diff --git a/dist/compressor.common.js b/dist/compressor.common.js index 26d83f8..377f5b4 100644 --- a/dist/compressor.common.js +++ b/dist/compressor.common.js @@ -1,105 +1,27 @@ /*! - * Compressor.js v1.1.1 + * Compressor.js v1.2.0 * https://fengyuanchen.github.io/compressorjs * * Copyright 2018-present Chen Fengyuan * Released under the MIT license * - * Date: 2023-02-12T06:45:05.457Z + * Date: 2023-02-25T11:35:56.625Z */ 'use strict'; -function ownKeys(object, enumerableOnly) { - var keys = Object.keys(object); - - if (Object.getOwnPropertySymbols) { - var symbols = Object.getOwnPropertySymbols(object); - - if (enumerableOnly) { - symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - }); - } - - keys.push.apply(keys, symbols); - } - - return keys; -} - -function _objectSpread2(target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i] != null ? arguments[i] : {}; - - if (i % 2) { - ownKeys(Object(source), true).forEach(function (key) { - _defineProperty(target, key, source[key]); - }); - } else if (Object.getOwnPropertyDescriptors) { - Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); - } else { - ownKeys(Object(source)).forEach(function (key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); - }); - } - } - - return target; -} - -function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a 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); - } -} - -function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; -} - -function _defineProperty(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - - return obj; -} - function _extends() { - _extends = Object.assign || function (target) { + _extends = Object.assign ? Object.assign.bind() : 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; }; - return _extends.apply(this, arguments); } @@ -118,16 +40,13 @@ var canvasToBlob = {exports: {}}; * Based on stackoverflow user Stoive's code snippet: * http://stackoverflow.com/q/4998908 */ - (function (module) { if (typeof window === 'undefined') { return; } - (function (window) { var CanvasPrototype = window.HTMLCanvasElement && window.HTMLCanvasElement.prototype; - var hasBlobConstructor = window.Blob && function () { try { return Boolean(new Blob()); @@ -135,7 +54,6 @@ var canvasToBlob = {exports: {}}; return false; } }(); - var hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && function () { try { return new Blob([new Uint8Array(100)]).size === 100; @@ -143,52 +61,42 @@ var canvasToBlob = {exports: {}}; 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 - + 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 - - + } + // 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: - - + } + // 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: - - + } + // 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) { @@ -223,7 +131,6 @@ var canvasToBlob = {exports: {}}; } } } - if (module.exports) { module.exports = dataURLtoBlob; } else { @@ -231,14 +138,12 @@ var canvasToBlob = {exports: {}}; } })(window); })(canvasToBlob); - var toBlob = canvasToBlob.exports; -var isBlob = function isBlob(value) { +var isBlob = value => { if (typeof Blob === 'undefined') { return false; } - return value instanceof Blob || Object.prototype.toString.call(value) === '[object Blob]'; }; @@ -249,65 +154,55 @@ var DEFAULTS = { * @type {boolean} */ strict: true, - /** * Indicates if read the image's Exif Orientation information, * and then rotate or flip the image automatically. * @type {boolean} */ checkOrientation: true, - /** * Indicates if retain the image's Exif information after compressed. * @type {boolean} */ retainExif: false, - /** * 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, - /** * Sets how the size of the image should be resized to the container * specified by the `width` and `height` options. * @type {string} */ resize: 'none', - /** * The quality of the output image. * It must be a number between `0` and `1`, @@ -316,28 +211,24 @@ var DEFAULTS = { * @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', - /** * Files whose file type is included in this list, * and whose file size exceeds the `convertSize` value will be converted to JPEGs. * @type {string|Array} */ convertTypes: ['image/png'], - /** * PNG files over this size (5 MB by default) will be converted to JPEGs. * To disable this, just set the value to `Infinity`. * @type {number} */ convertSize: 5000000, - /** * The hook function to execute before draw the image into the canvas for compression. * @type {Function} @@ -349,7 +240,6 @@ var DEFAULTS = { * } */ beforeDraw: null, - /** * The hook function to execute after drew the image into the canvas for compression. * @type {Function} @@ -361,7 +251,6 @@ var DEFAULTS = { * } */ drew: null, - /** * The hook function to execute when success to compress the image. * @type {Function} @@ -372,7 +261,6 @@ var DEFAULTS = { * } */ success: null, - /** * The hook function to execute when fail to compress the image. * @type {Function} @@ -385,54 +273,54 @@ var DEFAULTS = { error: null }; -var IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined'; -var WINDOW = IS_BROWSER ? window : {}; +const IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined'; +const WINDOW = IS_BROWSER ? window : {}; /** * Check if the given value is a positive number. * @param {*} value - The value to check. * @returns {boolean} Returns `true` if the given value is a positive number, else `false`. */ +const isPositiveNumber = value => value > 0 && value < Infinity; +const { + slice +} = Array.prototype; -var isPositiveNumber = function isPositiveNumber(value) { - return value > 0 && value < Infinity; -}; -var slice = Array.prototype.slice; /** * Convert array-like or iterable object to an array. * @param {*} value - The value to convert. * @returns {Array} Returns a new array. */ - function toArray(value) { return Array.from ? Array.from(value) : slice.call(value); } -var REGEXP_IMAGE_TYPE = /^image\/.+$/; +const 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. * @returns {boolean} Returns the image extension. */ - function imageTypeToExtension(value) { - var extension = isImageType(value) ? value.substr(6) : ''; - + let extension = isImageType(value) ? value.substr(6) : ''; if (extension === 'jpeg') { extension = 'jpg'; } - - return ".".concat(extension); + return `.${extension}`; } -var fromCharCode = String.fromCharCode; +const { + fromCharCode +} = String; + /** * Get string from char code in data view. * @param {DataView} dataView - The data view for read. @@ -440,83 +328,74 @@ var fromCharCode = String.fromCharCode; * @param {number} length - The read length. * @returns {string} The read result. */ - function getStringFromCharCode(dataView, start, length) { - var str = ''; - var i; + let str = ''; + let i; length += start; - for (i = start; i < length; i += 1) { str += fromCharCode(dataView.getUint8(i)); } - return str; } -var btoa = WINDOW.btoa; +const { + btoa +} = WINDOW; + /** * 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 chunks = []; - var chunkSize = 8192; - var uint8 = new Uint8Array(arrayBuffer); - + const chunks = []; + const chunkSize = 8192; + let uint8 = new Uint8Array(arrayBuffer); while (uint8.length > 0) { // XXX: Babel's `toConsumableArray` helper will throw error in IE or Safari 9 // eslint-disable-next-line prefer-spread chunks.push(fromCharCode.apply(null, toArray(uint8.subarray(0, chunkSize)))); uint8 = uint8.subarray(chunkSize); } - - return "data:".concat(mimeType, ";base64,").concat(btoa(chunks.join(''))); + return `data:${mimeType};base64,${btoa(chunks.join(''))}`; } + /** * Get orientation value from given array buffer. * @param {ArrayBuffer} arrayBuffer - The array buffer to read. * @returns {number} The read orientation value. */ - function resetAndGetOrientation(arrayBuffer) { - var dataView = new DataView(arrayBuffer); - var orientation; // Ignores range error when the image does not have correct Exif information + const dataView = new DataView(arrayBuffer); + let orientation; + // Ignores range error when the image does not have correct Exif information try { - var littleEndian; - var app1Start; - var ifdStart; // Only handle JPEG image (start by 0xFFD8) + let littleEndian; + let app1Start; + let ifdStart; + // Only handle JPEG image (start by 0xFFD8) if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { - var length = dataView.byteLength; - var offset = 2; - + const length = dataView.byteLength; + let offset = 2; while (offset + 1 < 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; - + const exifIDCode = app1Start + 4; + const tiffOffset = app1Start + 10; if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { - var endianness = dataView.getUint16(tiffOffset); + const endianness = dataView.getUint16(tiffOffset); littleEndian = endianness === 0x4949; - - if (littleEndian || endianness === 0x4D4D - /* bigEndian */ - ) { + if (littleEndian || endianness === 0x4D4D /* bigEndian */) { if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { - var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); - + const firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); if (firstIFDOffset >= 0x00000008) { ifdStart = tiffOffset + firstIFDOffset; } @@ -524,26 +403,21 @@ function resetAndGetOrientation(arrayBuffer) { } } } - if (ifdStart) { - var _length = dataView.getUint16(ifdStart, littleEndian); - - var _offset; - - var i; - - for (i = 0; i < _length; i += 1) { - _offset = ifdStart + i * 12 + 2; - - if (dataView.getUint16(_offset, littleEndian) === 0x0112 - /* Orientation */ - ) { + const length = dataView.getUint16(ifdStart, littleEndian); + let offset; + let i; + 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 + offset += 8; - orientation = dataView.getUint16(_offset, littleEndian); // Override the orientation with its default value + // Get the original orientation value + orientation = dataView.getUint16(offset, littleEndian); - dataView.setUint16(_offset, 1, littleEndian); + // Override the orientation with its default value + dataView.setUint16(offset, 1, littleEndian); break; } } @@ -551,66 +425,64 @@ function resetAndGetOrientation(arrayBuffer) { } catch (e) { orientation = 1; } - 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; - + let rotate = 0; + let scaleX = 1; + let scaleY = 1; switch (orientation) { // Flip horizontal case 2: scaleX = -1; break; - // Rotate left 180° + // Rotate left 180° case 3: rotate = -180; break; - // Flip vertical + // Flip vertical case 4: scaleY = -1; break; - // Flip vertical and rotate right 90° + // Flip vertical and rotate right 90° case 5: rotate = 90; scaleY = -1; break; - // Rotate right 90° + // Rotate right 90° case 6: rotate = 90; break; - // Flip horizontal and rotate right 90° + // Flip horizontal and rotate right 90° case 7: rotate = 90; scaleX = -1; break; - // Rotate left 90° + // Rotate left 90° case 8: rotate = -90; break; } - return { - rotate: rotate, - scaleX: scaleX, - scaleY: scaleY + rotate, + scaleX, + scaleY }; } -var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; +const REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; + /** * Normalize decimal number. * Check out {@link https://0.30000000000000004.com/} @@ -618,29 +490,28 @@ var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; * @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; + let times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000; return REGEXP_DECIMALS.test(value) ? Math.round(value * times) / times : value; } + /** * Get the max sizes in a rectangle under the given aspect ratio. * @param {Object} data - The original sizes. * @param {string} [type='contain'] - The adjust type. * @returns {Object} The result sizes. */ - function getAdjustedSizes(_ref) { - var aspectRatio = _ref.aspectRatio, - height = _ref.height, - width = _ref.width; - var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none'; - var isValidWidth = isPositiveNumber(width); - var isValidHeight = isPositiveNumber(height); - + let { + aspectRatio, + height, + width + } = _ref; + let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none'; + const isValidWidth = isPositiveNumber(width); + const isValidHeight = isPositiveNumber(height); if (isValidWidth && isValidHeight) { - var adjustedWidth = height * aspectRatio; - + const adjustedWidth = height * aspectRatio; if ((type === 'contain' || type === 'none') && adjustedWidth > width || type === 'cover' && adjustedWidth < width) { height = width / aspectRatio; } else { @@ -651,531 +522,467 @@ function getAdjustedSizes(_ref) { } else if (isValidHeight) { width = height * aspectRatio; } - return { - width: width, - height: height + width, + height }; } + /** * Get Exif information from the given array buffer. * @param {ArrayBuffer} arrayBuffer - The array buffer to read. * @returns {Array} The read Exif information. */ - function getExif(arrayBuffer) { - var array = toArray(new Uint8Array(arrayBuffer)); - var length = array.length; - var segments = []; - var head = 0; - var endPoint; + const array = toArray(new Uint8Array(arrayBuffer)); + const { + length + } = array; + const segments = []; + let start = 0; + while (start + 3 < length) { + const value = array[start]; + const next = array[start + 1]; - while (head + 1 < length) { // SOS (Start of Scan) - if (array[head] === 0xff && array[head + 1] === 0xda) { + if (value === 0xFF && next === 0xDA) { break; - } // SOI (Start of Image) - + } - if (array[head] === 0xff && array[head + 1] === 0xd8) { - head += 2; + // SOI (Start of Image) + if (value === 0xFF && next === 0xD8) { + start += 2; } else { - var len = array[head + 2] * 256 + array[head + 3]; - endPoint = head + len + 2; - var segment = array.slice(head, endPoint); + const offset = array[start + 2] * 256 + array[start + 3]; + const end = start + offset + 2; + const segment = array.slice(start, end); segments.push(segment); - head = endPoint; + start = end; } } - - return segments.reduce(function (exifArray, current) { - if (current[0] === 0xff && current[1] === 0xe1) { + return segments.reduce((exifArray, current) => { + if (current[0] === 0xFF && current[1] === 0xE1) { return exifArray.concat(current); } - return exifArray; }, []); } + /** * Insert Exif information into the given array buffer. - * @param {ArrayBuffer} arrayBuffer - The array buffer to insert. - * @param {Array} exifArray - The Exif information array. + * @param {ArrayBuffer} arrayBuffer - The array buffer to transform. + * @param {Array} exifArray - The Exif information to insert. * @returns {ArrayBuffer} The transformed array buffer. */ - function insertExif(arrayBuffer, exifArray) { - var array = toArray(new Uint8Array(arrayBuffer)); - - if (array[2] !== 0xff || array[3] !== 0xe0) { + const array = toArray(new Uint8Array(arrayBuffer)); + if (array[2] !== 0xFF || array[3] !== 0xE0) { return arrayBuffer; } - - var app0Length = array[4] * 256 + array[5]; - var newArrayBuffer = [0xff, 0xd8].concat(exifArray, array.slice(4 + app0Length)); + const app0Length = array[4] * 256 + array[5]; + const newArrayBuffer = [0xFF, 0xD8].concat(exifArray, array.slice(4 + app0Length)); return new Uint8Array(newArrayBuffer); } -var ArrayBuffer$1 = WINDOW.ArrayBuffer, - FileReader = WINDOW.FileReader; -var URL = WINDOW.URL || WINDOW.webkitURL; -var REGEXP_EXTENSION = /\.\w+$/; -var AnotherCompressor = WINDOW.Compressor; +const { + ArrayBuffer: ArrayBuffer$1, + FileReader +} = WINDOW; +const URL = WINDOW.URL || WINDOW.webkitURL; +const REGEXP_EXTENSION = /\.\w+$/; +const AnotherCompressor = WINDOW.Compressor; + /** * Creates a new image compressor. * @class */ - -var Compressor = /*#__PURE__*/function () { +class Compressor { /** * The constructor of Compressor. * @param {File|Blob} file - The target image file for compressing. * @param {Object} [options] - The options for compressing. */ - function Compressor(file, options) { - _classCallCheck(this, Compressor); - + constructor(file, options) { this.file = file; this.exif = []; this.image = new Image(); - this.options = _objectSpread2(_objectSpread2({}, DEFAULTS), options); + this.options = { + ...DEFAULTS, + ...options + }; this.aborted = false; this.result = null; this.init(); } - - _createClass(Compressor, [{ - key: "init", - value: function init() { - var _this = this; - - var file = this.file, - options = this.options; - - if (!isBlob(file)) { - this.fail(new Error('The first argument must be a File or Blob object.')); - return; - } - - var mimeType = file.type; - - if (!isImageType(mimeType)) { - this.fail(new Error('The first argument must be an image File or Blob object.')); - return; - } - - if (!URL || !FileReader) { - this.fail(new Error('The current browser does not support image compression.')); - return; - } - - if (!ArrayBuffer$1) { - options.checkOrientation = false; - options.retainExif = false; - } - - if (URL && !options.checkOrientation && !options.retainExif) { - this.load({ - url: URL.createObjectURL(file) - }); - } else { - var reader = new FileReader(); - var checkOrientation = options.checkOrientation && mimeType === 'image/jpeg'; - this.reader = reader; - - reader.onload = function (_ref) { - var target = _ref.target; - var result = target.result; - var data = {}; - - if (checkOrientation) { - // Reset the orientation value to its default value 1 - // as some iOS browsers will render image with its orientation - var orientation = resetAndGetOrientation(result); - - if (orientation > 1 || !URL) { - // Generate a new URL which has the default orientation value - data.url = arrayBufferToDataURL(result, mimeType); - - if (orientation > 1) { - _extends(data, parseOrientation(orientation)); - } - } else { - data.url = URL.createObjectURL(file); - } - } else { - data.url = result; + init() { + const { + file, + options + } = this; + if (!isBlob(file)) { + this.fail(new Error('The first argument must be a File or Blob object.')); + return; + } + const mimeType = file.type; + if (!isImageType(mimeType)) { + this.fail(new Error('The first argument must be an image File or Blob object.')); + return; + } + if (!URL || !FileReader) { + this.fail(new Error('The current browser does not support image compression.')); + return; + } + if (!ArrayBuffer$1) { + options.checkOrientation = false; + options.retainExif = false; + } + const isJPEGImage = mimeType === 'image/jpeg'; + const checkOrientation = isJPEGImage && options.checkOrientation; + const retainExif = isJPEGImage && options.retainExif; + if (URL && !checkOrientation && !retainExif) { + this.load({ + url: URL.createObjectURL(file) + }); + } else { + const reader = new FileReader(); + this.reader = reader; + reader.onload = _ref => { + let { + target + } = _ref; + const { + result + } = target; + const data = {}; + let orientation = 1; + if (checkOrientation) { + // Reset the orientation value to its default value 1 + // as some iOS browsers will render image with its orientation + orientation = resetAndGetOrientation(result); + if (orientation > 1) { + _extends(data, parseOrientation(orientation)); } + } + if (retainExif) { + this.exif = getExif(result); + } + if (checkOrientation || retainExif) { + if (!URL - if (options.retainExif) { - _this.exif = getExif(result); + // Generate a new URL with the default orientation value 1. + || orientation > 1) { + data.url = arrayBufferToDataURL(result, mimeType); + } else { + data.url = URL.createObjectURL(file); } - - _this.load(data); - }; - - reader.onabort = function () { - _this.fail(new Error('Aborted to read the image with FileReader.')); - }; - - reader.onerror = function () { - _this.fail(new Error('Failed to read the image with FileReader.')); - }; - - reader.onloadend = function () { - _this.reader = null; - }; - - if (checkOrientation || options.retainExif) { - reader.readAsArrayBuffer(file); } else { - reader.readAsDataURL(file); + data.url = result; } - } - } - }, { - key: "load", - value: function load(data) { - var _this2 = this; - - var file = this.file, - image = this.image; - - image.onload = function () { - _this2.draw(_objectSpread2(_objectSpread2({}, data), {}, { - naturalWidth: image.naturalWidth, - naturalHeight: image.naturalHeight - })); + this.load(data); }; - - image.onabort = function () { - _this2.fail(new Error('Aborted to load the image.')); + reader.onabort = () => { + this.fail(new Error('Aborted to read the image with FileReader.')); }; - - image.onerror = function () { - _this2.fail(new Error('Failed to load the image.')); - }; // Match all browsers that use WebKit as the layout engine in iOS devices, - // such as Safari for iOS, Chrome for iOS, and in-app browsers. - - - if (WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent)) { - // Fix the `The operation is insecure` error (#57) - image.crossOrigin = 'anonymous'; + reader.onerror = () => { + this.fail(new Error('Failed to read the image with FileReader.')); + }; + reader.onloadend = () => { + this.reader = null; + }; + if (checkOrientation || retainExif) { + reader.readAsArrayBuffer(file); + } else { + reader.readAsDataURL(file); } - - image.alt = file.name; - image.src = data.url; } - }, { - key: "draw", - value: function draw(_ref2) { - var _this3 = this; - - var naturalWidth = _ref2.naturalWidth, - naturalHeight = _ref2.naturalHeight, - _ref2$rotate = _ref2.rotate, - rotate = _ref2$rotate === void 0 ? 0 : _ref2$rotate, - _ref2$scaleX = _ref2.scaleX, - scaleX = _ref2$scaleX === void 0 ? 1 : _ref2$scaleX, - _ref2$scaleY = _ref2.scaleY, - scaleY = _ref2$scaleY === void 0 ? 1 : _ref2$scaleY; - var file = this.file, - image = this.image, - options = this.options; - var canvas = document.createElement('canvas'); - var context = canvas.getContext('2d'); - var is90DegreesRotated = Math.abs(rotate) % 180 === 90; - var resizable = (options.resize === 'contain' || options.resize === 'cover') && isPositiveNumber(options.width) && isPositiveNumber(options.height); - 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 aspectRatio = naturalWidth / naturalHeight; - var width = options.width, - height = options.height; - - if (is90DegreesRotated) { - var _ref3 = [maxHeight, maxWidth]; - maxWidth = _ref3[0]; - maxHeight = _ref3[1]; - var _ref4 = [minHeight, minWidth]; - minWidth = _ref4[0]; - minHeight = _ref4[1]; - var _ref5 = [height, width]; - width = _ref5[0]; - height = _ref5[1]; - } - - if (resizable) { - aspectRatio = width / height; - } - - var _getAdjustedSizes = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: maxWidth, - height: maxHeight - }, 'contain'); - - maxWidth = _getAdjustedSizes.width; - maxHeight = _getAdjustedSizes.height; - - var _getAdjustedSizes2 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: minWidth, - height: minHeight - }, 'cover'); + } + load(data) { + const { + file, + image + } = this; + image.onload = () => { + this.draw({ + ...data, + naturalWidth: image.naturalWidth, + naturalHeight: image.naturalHeight + }); + }; + image.onabort = () => { + this.fail(new Error('Aborted to load the image.')); + }; + image.onerror = () => { + this.fail(new Error('Failed to load the image.')); + }; - minWidth = _getAdjustedSizes2.width; - minHeight = _getAdjustedSizes2.height; + // Match all browsers that use WebKit as the layout engine in iOS devices, + // such as Safari for iOS, Chrome for iOS, and in-app browsers. + if (WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent)) { + // Fix the `The operation is insecure` error (#57) + image.crossOrigin = 'anonymous'; + } + image.alt = file.name; + image.src = data.url; + } + draw(_ref2) { + let { + naturalWidth, + naturalHeight, + rotate = 0, + scaleX = 1, + scaleY = 1 + } = _ref2; + const { + file, + image, + options + } = this; + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + const is90DegreesRotated = Math.abs(rotate) % 180 === 90; + const resizable = (options.resize === 'contain' || options.resize === 'cover') && isPositiveNumber(options.width) && isPositiveNumber(options.height); + let maxWidth = Math.max(options.maxWidth, 0) || Infinity; + let maxHeight = Math.max(options.maxHeight, 0) || Infinity; + let minWidth = Math.max(options.minWidth, 0) || 0; + let minHeight = Math.max(options.minHeight, 0) || 0; + let aspectRatio = naturalWidth / naturalHeight; + let { + width, + height + } = options; + if (is90DegreesRotated) { + [maxWidth, maxHeight] = [maxHeight, maxWidth]; + [minWidth, minHeight] = [minHeight, minWidth]; + [width, height] = [height, width]; + } + if (resizable) { + aspectRatio = width / height; + } + ({ + width: maxWidth, + height: maxHeight + } = getAdjustedSizes({ + aspectRatio, + width: maxWidth, + height: maxHeight + }, 'contain')); + ({ + width: minWidth, + height: minHeight + } = getAdjustedSizes({ + aspectRatio, + width: minWidth, + height: minHeight + }, 'cover')); + if (resizable) { + ({ + width, + height + } = getAdjustedSizes({ + aspectRatio, + width, + height + }, options.resize)); + } else { + ({ + width = naturalWidth, + height = naturalHeight + } = getAdjustedSizes({ + aspectRatio, + width, + height + })); + } + width = Math.floor(normalizeDecimalNumber(Math.min(Math.max(width, minWidth), maxWidth))); + height = Math.floor(normalizeDecimalNumber(Math.min(Math.max(height, minHeight), maxHeight))); + const destX = -width / 2; + const destY = -height / 2; + const destWidth = width; + const destHeight = height; + const params = []; + if (resizable) { + let srcX = 0; + let srcY = 0; + let srcWidth = naturalWidth; + let srcHeight = naturalHeight; + ({ + width: srcWidth, + height: srcHeight + } = getAdjustedSizes({ + aspectRatio, + width: naturalWidth, + height: naturalHeight + }, { + contain: 'cover', + cover: 'contain' + }[options.resize])); + srcX = (naturalWidth - srcWidth) / 2; + srcY = (naturalHeight - srcHeight) / 2; + params.push(srcX, srcY, srcWidth, srcHeight); + } + params.push(destX, destY, destWidth, destHeight); + if (is90DegreesRotated) { + [width, height] = [height, width]; + } + canvas.width = width; + canvas.height = height; + if (!isImageType(options.mimeType)) { + options.mimeType = file.type; + } + let fillStyle = 'transparent'; - if (resizable) { - var _getAdjustedSizes3 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: width, - height: height - }, options.resize); + // Converts PNG files over the `convertSize` to JPEGs. + if (file.size > options.convertSize && options.convertTypes.indexOf(options.mimeType) >= 0) { + options.mimeType = 'image/jpeg'; + } + const isJPEGImage = options.mimeType === 'image/jpeg'; + if (isJPEGImage) { + fillStyle = '#fff'; + } - width = _getAdjustedSizes3.width; - height = _getAdjustedSizes3.height; - } else { - var _getAdjustedSizes4 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: width, - height: height + // Override the default fill color (#000, black) + context.fillStyle = fillStyle; + context.fillRect(0, 0, width, height); + if (options.beforeDraw) { + options.beforeDraw.call(this, context, canvas); + } + if (this.aborted) { + return; + } + context.save(); + context.translate(width / 2, height / 2); + context.rotate(rotate * Math.PI / 180); + context.scale(scaleX, scaleY); + context.drawImage(image, ...params); + context.restore(); + if (options.drew) { + options.drew.call(this, context, canvas); + } + if (this.aborted) { + return; + } + const callback = blob => { + if (!this.aborted) { + const done = result => this.done({ + naturalWidth, + naturalHeight, + result }); - - var _getAdjustedSizes4$wi = _getAdjustedSizes4.width; - width = _getAdjustedSizes4$wi === void 0 ? naturalWidth : _getAdjustedSizes4$wi; - var _getAdjustedSizes4$he = _getAdjustedSizes4.height; - height = _getAdjustedSizes4$he === void 0 ? naturalHeight : _getAdjustedSizes4$he; - } - - width = Math.floor(normalizeDecimalNumber(Math.min(Math.max(width, minWidth), maxWidth))); - height = Math.floor(normalizeDecimalNumber(Math.min(Math.max(height, minHeight), maxHeight))); - var destX = -width / 2; - var destY = -height / 2; - var destWidth = width; - var destHeight = height; - var params = []; - - if (resizable) { - var srcX = 0; - var srcY = 0; - var srcWidth = naturalWidth; - var srcHeight = naturalHeight; - - var _getAdjustedSizes5 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: naturalWidth, - height: naturalHeight - }, { - contain: 'cover', - cover: 'contain' - }[options.resize]); - - srcWidth = _getAdjustedSizes5.width; - srcHeight = _getAdjustedSizes5.height; - srcX = (naturalWidth - srcWidth) / 2; - srcY = (naturalHeight - srcHeight) / 2; - params.push(srcX, srcY, srcWidth, srcHeight); - } - - params.push(destX, destY, destWidth, destHeight); - - if (is90DegreesRotated) { - var _ref6 = [height, width]; - width = _ref6[0]; - height = _ref6[1]; - } - - canvas.width = width; - canvas.height = height; - - if (!isImageType(options.mimeType)) { - options.mimeType = file.type; - } - - var fillStyle = 'transparent'; // Converts PNG files over the `convertSize` to JPEGs. - - if (file.size > options.convertSize && options.convertTypes.indexOf(options.mimeType) >= 0) { - options.mimeType = 'image/jpeg'; - } - - if (options.mimeType === 'image/jpeg') { - fillStyle = '#fff'; - } // Override the default fill color (#000, black) - - - context.fillStyle = fillStyle; - context.fillRect(0, 0, width, height); - - if (options.beforeDraw) { - options.beforeDraw.call(this, context, canvas); - } - - if (this.aborted) { - return; - } - - context.save(); - context.translate(width / 2, height / 2); - context.rotate(rotate * Math.PI / 180); - context.scale(scaleX, scaleY); - context.drawImage.apply(context, [image].concat(params)); - context.restore(); - - if (options.drew) { - options.drew.call(this, context, canvas); - } - - if (this.aborted) { - return; - } - - var callback = function callback(blob) { - if (!_this3.aborted) { - var done = function done(result) { - return _this3.done({ - naturalWidth: naturalWidth, - naturalHeight: naturalHeight, - result: result + if (blob && isJPEGImage && options.retainExif && this.exif && this.exif.length > 0) { + const next = arrayBuffer => done(toBlob(arrayBufferToDataURL(insertExif(arrayBuffer, this.exif), options.mimeType))); + if (blob.arrayBuffer) { + blob.arrayBuffer().then(next).catch(() => { + this.fail(new Error('Failed to read the compressed image with Blob.arrayBuffer().')); }); - }; - - if (options.retainExif && blob) { - var next = function next(arrayBuffer) { - return done(toBlob(arrayBufferToDataURL(insertExif(arrayBuffer, _this3.exif), options.mimeType))); - }; - - if (blob.arrayBuffer) { - blob.arrayBuffer().then(next).catch(function () { - _this3.fail(new Error('Failed to read the compressed image with Blob.arrayBuffer().')); - }); - } else { - var reader = new FileReader(); - _this3.reader = reader; - - reader.onload = function (_ref7) { - var target = _ref7.target; - next(target.result); - }; - - reader.onabort = function () { - _this3.fail(new Error('Aborted to read the compressed image with FileReader.')); - }; - - reader.onerror = function () { - _this3.fail(new Error('Failed to read the compressed image with FileReader.')); - }; - - reader.onloadend = function () { - _this3.reader = null; - }; - - reader.readAsArrayBuffer(blob); - } } else { - done(blob); + const reader = new FileReader(); + this.reader = reader; + reader.onload = _ref3 => { + let { + target + } = _ref3; + next(target.result); + }; + reader.onabort = () => { + this.fail(new Error('Aborted to read the compressed image with FileReader.')); + }; + reader.onerror = () => { + this.fail(new Error('Failed to read the compressed image with FileReader.')); + }; + reader.onloadend = () => { + this.reader = null; + }; + reader.readAsArrayBuffer(blob); } - } - }; - - if (canvas.toBlob) { - canvas.toBlob(callback, options.mimeType, options.quality); - } else { - callback(toBlob(canvas.toDataURL(options.mimeType, options.quality))); - } - } - }, { - key: "done", - value: function done(_ref8) { - var naturalWidth = _ref8.naturalWidth, - naturalHeight = _ref8.naturalHeight, - result = _ref8.result; - var file = this.file, - image = this.image, - options = this.options; - - 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 (options.strict && result.size > file.size && options.mimeType === file.type && !(options.width > naturalWidth || options.height > naturalHeight || options.minWidth > naturalWidth || options.minHeight > naturalHeight || options.maxWidth < naturalWidth || options.maxHeight < 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)); - } + done(blob); } - } 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); } + }; + if (canvas.toBlob) { + canvas.toBlob(callback, options.mimeType, options.quality); + } else { + callback(toBlob(canvas.toDataURL(options.mimeType, options.quality))); } - }, { - key: "fail", - value: function fail(err) { - var options = this.options; - - if (options.error) { - options.error.call(this, err); - } else { - throw err; - } + } + done(_ref4) { + let { + naturalWidth, + naturalHeight, + result + } = _ref4; + const { + file, + image, + options + } = this; + if (URL && image.src.indexOf('blob:') === 0) { + URL.revokeObjectURL(image.src); } - }, { - key: "abort", - value: function abort() { - if (!this.aborted) { - this.aborted = true; - - if (this.reader) { - this.reader.abort(); - } else if (!this.image.complete) { - this.image.onload = null; - this.image.onabort(); - } else { - this.fail(new Error('The compression process has been aborted.')); + if (result) { + // Returns original file if the result is greater than it and without size related options + if (options.strict && !options.retainExif && result.size > file.size && options.mimeType === file.type && !(options.width > naturalWidth || options.height > naturalHeight || options.minWidth > naturalWidth || options.minHeight > naturalHeight || options.maxWidth < naturalWidth || options.maxHeight < naturalHeight)) { + result = file; + } else { + const 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; } - /** - * Get the no conflict compressor class. - * @returns {Compressor} The compressor class. - */ - - }], [{ - key: "noConflict", - value: function noConflict() { - window.Compressor = AnotherCompressor; - return Compressor; + this.result = result; + if (options.success) { + options.success.call(this, result); } - /** - * Change the default options. - * @param {Object} options - The new default options. - */ - - }, { - key: "setDefaults", - value: function setDefaults(options) { - _extends(DEFAULTS, options); + } + fail(err) { + const { + options + } = this; + if (options.error) { + options.error.call(this, err); + } else { + throw err; + } + } + abort() { + if (!this.aborted) { + this.aborted = true; + if (this.reader) { + this.reader.abort(); + } else if (!this.image.complete) { + this.image.onload = null; + this.image.onabort(); + } else { + this.fail(new Error('The compression process has been aborted.')); + } } - }]); + } + + /** + * Get the no conflict compressor class. + * @returns {Compressor} The compressor class. + */ + static noConflict() { + window.Compressor = AnotherCompressor; + return Compressor; + } - return Compressor; -}(); + /** + * Change the default options. + * @param {Object} options - The new default options. + */ + static setDefaults(options) { + _extends(DEFAULTS, options); + } +} module.exports = Compressor; -//# sourceMappingURL=compressor.common.js.map diff --git a/dist/compressor.esm.js b/dist/compressor.esm.js index c4a1f2a..38613ac 100644 --- a/dist/compressor.esm.js +++ b/dist/compressor.esm.js @@ -1,103 +1,25 @@ /*! - * Compressor.js v1.1.1 + * Compressor.js v1.2.0 * https://fengyuanchen.github.io/compressorjs * * Copyright 2018-present Chen Fengyuan * Released under the MIT license * - * Date: 2023-02-12T06:45:05.457Z + * Date: 2023-02-25T11:35:56.625Z */ -function ownKeys(object, enumerableOnly) { - var keys = Object.keys(object); - - if (Object.getOwnPropertySymbols) { - var symbols = Object.getOwnPropertySymbols(object); - - if (enumerableOnly) { - symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - }); - } - - keys.push.apply(keys, symbols); - } - - return keys; -} - -function _objectSpread2(target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i] != null ? arguments[i] : {}; - - if (i % 2) { - ownKeys(Object(source), true).forEach(function (key) { - _defineProperty(target, key, source[key]); - }); - } else if (Object.getOwnPropertyDescriptors) { - Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); - } else { - ownKeys(Object(source)).forEach(function (key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); - }); - } - } - - return target; -} - -function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a 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); - } -} - -function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; -} - -function _defineProperty(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - - return obj; -} - function _extends() { - _extends = Object.assign || function (target) { + _extends = Object.assign ? Object.assign.bind() : 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; }; - return _extends.apply(this, arguments); } @@ -116,16 +38,13 @@ var canvasToBlob = {exports: {}}; * Based on stackoverflow user Stoive's code snippet: * http://stackoverflow.com/q/4998908 */ - (function (module) { if (typeof window === 'undefined') { return; } - (function (window) { var CanvasPrototype = window.HTMLCanvasElement && window.HTMLCanvasElement.prototype; - var hasBlobConstructor = window.Blob && function () { try { return Boolean(new Blob()); @@ -133,7 +52,6 @@ var canvasToBlob = {exports: {}}; return false; } }(); - var hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && function () { try { return new Blob([new Uint8Array(100)]).size === 100; @@ -141,52 +59,42 @@ var canvasToBlob = {exports: {}}; 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 - + 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 - - + } + // 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: - - + } + // 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: - - + } + // 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) { @@ -221,7 +129,6 @@ var canvasToBlob = {exports: {}}; } } } - if (module.exports) { module.exports = dataURLtoBlob; } else { @@ -229,14 +136,12 @@ var canvasToBlob = {exports: {}}; } })(window); })(canvasToBlob); - var toBlob = canvasToBlob.exports; -var isBlob = function isBlob(value) { +var isBlob = value => { if (typeof Blob === 'undefined') { return false; } - return value instanceof Blob || Object.prototype.toString.call(value) === '[object Blob]'; }; @@ -247,65 +152,55 @@ var DEFAULTS = { * @type {boolean} */ strict: true, - /** * Indicates if read the image's Exif Orientation information, * and then rotate or flip the image automatically. * @type {boolean} */ checkOrientation: true, - /** * Indicates if retain the image's Exif information after compressed. * @type {boolean} */ retainExif: false, - /** * 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, - /** * Sets how the size of the image should be resized to the container * specified by the `width` and `height` options. * @type {string} */ resize: 'none', - /** * The quality of the output image. * It must be a number between `0` and `1`, @@ -314,28 +209,24 @@ var DEFAULTS = { * @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', - /** * Files whose file type is included in this list, * and whose file size exceeds the `convertSize` value will be converted to JPEGs. * @type {string|Array} */ convertTypes: ['image/png'], - /** * PNG files over this size (5 MB by default) will be converted to JPEGs. * To disable this, just set the value to `Infinity`. * @type {number} */ convertSize: 5000000, - /** * The hook function to execute before draw the image into the canvas for compression. * @type {Function} @@ -347,7 +238,6 @@ var DEFAULTS = { * } */ beforeDraw: null, - /** * The hook function to execute after drew the image into the canvas for compression. * @type {Function} @@ -359,7 +249,6 @@ var DEFAULTS = { * } */ drew: null, - /** * The hook function to execute when success to compress the image. * @type {Function} @@ -370,7 +259,6 @@ var DEFAULTS = { * } */ success: null, - /** * The hook function to execute when fail to compress the image. * @type {Function} @@ -383,54 +271,54 @@ var DEFAULTS = { error: null }; -var IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined'; -var WINDOW = IS_BROWSER ? window : {}; +const IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined'; +const WINDOW = IS_BROWSER ? window : {}; /** * Check if the given value is a positive number. * @param {*} value - The value to check. * @returns {boolean} Returns `true` if the given value is a positive number, else `false`. */ +const isPositiveNumber = value => value > 0 && value < Infinity; +const { + slice +} = Array.prototype; -var isPositiveNumber = function isPositiveNumber(value) { - return value > 0 && value < Infinity; -}; -var slice = Array.prototype.slice; /** * Convert array-like or iterable object to an array. * @param {*} value - The value to convert. * @returns {Array} Returns a new array. */ - function toArray(value) { return Array.from ? Array.from(value) : slice.call(value); } -var REGEXP_IMAGE_TYPE = /^image\/.+$/; +const 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. * @returns {boolean} Returns the image extension. */ - function imageTypeToExtension(value) { - var extension = isImageType(value) ? value.substr(6) : ''; - + let extension = isImageType(value) ? value.substr(6) : ''; if (extension === 'jpeg') { extension = 'jpg'; } - - return ".".concat(extension); + return `.${extension}`; } -var fromCharCode = String.fromCharCode; +const { + fromCharCode +} = String; + /** * Get string from char code in data view. * @param {DataView} dataView - The data view for read. @@ -438,83 +326,74 @@ var fromCharCode = String.fromCharCode; * @param {number} length - The read length. * @returns {string} The read result. */ - function getStringFromCharCode(dataView, start, length) { - var str = ''; - var i; + let str = ''; + let i; length += start; - for (i = start; i < length; i += 1) { str += fromCharCode(dataView.getUint8(i)); } - return str; } -var btoa = WINDOW.btoa; +const { + btoa +} = WINDOW; + /** * 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 chunks = []; - var chunkSize = 8192; - var uint8 = new Uint8Array(arrayBuffer); - + const chunks = []; + const chunkSize = 8192; + let uint8 = new Uint8Array(arrayBuffer); while (uint8.length > 0) { // XXX: Babel's `toConsumableArray` helper will throw error in IE or Safari 9 // eslint-disable-next-line prefer-spread chunks.push(fromCharCode.apply(null, toArray(uint8.subarray(0, chunkSize)))); uint8 = uint8.subarray(chunkSize); } - - return "data:".concat(mimeType, ";base64,").concat(btoa(chunks.join(''))); + return `data:${mimeType};base64,${btoa(chunks.join(''))}`; } + /** * Get orientation value from given array buffer. * @param {ArrayBuffer} arrayBuffer - The array buffer to read. * @returns {number} The read orientation value. */ - function resetAndGetOrientation(arrayBuffer) { - var dataView = new DataView(arrayBuffer); - var orientation; // Ignores range error when the image does not have correct Exif information + const dataView = new DataView(arrayBuffer); + let orientation; + // Ignores range error when the image does not have correct Exif information try { - var littleEndian; - var app1Start; - var ifdStart; // Only handle JPEG image (start by 0xFFD8) + let littleEndian; + let app1Start; + let ifdStart; + // Only handle JPEG image (start by 0xFFD8) if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { - var length = dataView.byteLength; - var offset = 2; - + const length = dataView.byteLength; + let offset = 2; while (offset + 1 < 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; - + const exifIDCode = app1Start + 4; + const tiffOffset = app1Start + 10; if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { - var endianness = dataView.getUint16(tiffOffset); + const endianness = dataView.getUint16(tiffOffset); littleEndian = endianness === 0x4949; - - if (littleEndian || endianness === 0x4D4D - /* bigEndian */ - ) { + if (littleEndian || endianness === 0x4D4D /* bigEndian */) { if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { - var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); - + const firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); if (firstIFDOffset >= 0x00000008) { ifdStart = tiffOffset + firstIFDOffset; } @@ -522,26 +401,21 @@ function resetAndGetOrientation(arrayBuffer) { } } } - if (ifdStart) { - var _length = dataView.getUint16(ifdStart, littleEndian); - - var _offset; - - var i; - - for (i = 0; i < _length; i += 1) { - _offset = ifdStart + i * 12 + 2; - - if (dataView.getUint16(_offset, littleEndian) === 0x0112 - /* Orientation */ - ) { + const length = dataView.getUint16(ifdStart, littleEndian); + let offset; + let i; + 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 + offset += 8; - orientation = dataView.getUint16(_offset, littleEndian); // Override the orientation with its default value + // Get the original orientation value + orientation = dataView.getUint16(offset, littleEndian); - dataView.setUint16(_offset, 1, littleEndian); + // Override the orientation with its default value + dataView.setUint16(offset, 1, littleEndian); break; } } @@ -549,66 +423,64 @@ function resetAndGetOrientation(arrayBuffer) { } catch (e) { orientation = 1; } - 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; - + let rotate = 0; + let scaleX = 1; + let scaleY = 1; switch (orientation) { // Flip horizontal case 2: scaleX = -1; break; - // Rotate left 180° + // Rotate left 180° case 3: rotate = -180; break; - // Flip vertical + // Flip vertical case 4: scaleY = -1; break; - // Flip vertical and rotate right 90° + // Flip vertical and rotate right 90° case 5: rotate = 90; scaleY = -1; break; - // Rotate right 90° + // Rotate right 90° case 6: rotate = 90; break; - // Flip horizontal and rotate right 90° + // Flip horizontal and rotate right 90° case 7: rotate = 90; scaleX = -1; break; - // Rotate left 90° + // Rotate left 90° case 8: rotate = -90; break; } - return { - rotate: rotate, - scaleX: scaleX, - scaleY: scaleY + rotate, + scaleX, + scaleY }; } -var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; +const REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; + /** * Normalize decimal number. * Check out {@link https://0.30000000000000004.com/} @@ -616,29 +488,28 @@ var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; * @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; + let times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000; return REGEXP_DECIMALS.test(value) ? Math.round(value * times) / times : value; } + /** * Get the max sizes in a rectangle under the given aspect ratio. * @param {Object} data - The original sizes. * @param {string} [type='contain'] - The adjust type. * @returns {Object} The result sizes. */ - function getAdjustedSizes(_ref) { - var aspectRatio = _ref.aspectRatio, - height = _ref.height, - width = _ref.width; - var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none'; - var isValidWidth = isPositiveNumber(width); - var isValidHeight = isPositiveNumber(height); - + let { + aspectRatio, + height, + width + } = _ref; + let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none'; + const isValidWidth = isPositiveNumber(width); + const isValidHeight = isPositiveNumber(height); if (isValidWidth && isValidHeight) { - var adjustedWidth = height * aspectRatio; - + const adjustedWidth = height * aspectRatio; if ((type === 'contain' || type === 'none') && adjustedWidth > width || type === 'cover' && adjustedWidth < width) { height = width / aspectRatio; } else { @@ -649,531 +520,467 @@ function getAdjustedSizes(_ref) { } else if (isValidHeight) { width = height * aspectRatio; } - return { - width: width, - height: height + width, + height }; } + /** * Get Exif information from the given array buffer. * @param {ArrayBuffer} arrayBuffer - The array buffer to read. * @returns {Array} The read Exif information. */ - function getExif(arrayBuffer) { - var array = toArray(new Uint8Array(arrayBuffer)); - var length = array.length; - var segments = []; - var head = 0; - var endPoint; + const array = toArray(new Uint8Array(arrayBuffer)); + const { + length + } = array; + const segments = []; + let start = 0; + while (start + 3 < length) { + const value = array[start]; + const next = array[start + 1]; - while (head + 1 < length) { // SOS (Start of Scan) - if (array[head] === 0xff && array[head + 1] === 0xda) { + if (value === 0xFF && next === 0xDA) { break; - } // SOI (Start of Image) - + } - if (array[head] === 0xff && array[head + 1] === 0xd8) { - head += 2; + // SOI (Start of Image) + if (value === 0xFF && next === 0xD8) { + start += 2; } else { - var len = array[head + 2] * 256 + array[head + 3]; - endPoint = head + len + 2; - var segment = array.slice(head, endPoint); + const offset = array[start + 2] * 256 + array[start + 3]; + const end = start + offset + 2; + const segment = array.slice(start, end); segments.push(segment); - head = endPoint; + start = end; } } - - return segments.reduce(function (exifArray, current) { - if (current[0] === 0xff && current[1] === 0xe1) { + return segments.reduce((exifArray, current) => { + if (current[0] === 0xFF && current[1] === 0xE1) { return exifArray.concat(current); } - return exifArray; }, []); } + /** * Insert Exif information into the given array buffer. - * @param {ArrayBuffer} arrayBuffer - The array buffer to insert. - * @param {Array} exifArray - The Exif information array. + * @param {ArrayBuffer} arrayBuffer - The array buffer to transform. + * @param {Array} exifArray - The Exif information to insert. * @returns {ArrayBuffer} The transformed array buffer. */ - function insertExif(arrayBuffer, exifArray) { - var array = toArray(new Uint8Array(arrayBuffer)); - - if (array[2] !== 0xff || array[3] !== 0xe0) { + const array = toArray(new Uint8Array(arrayBuffer)); + if (array[2] !== 0xFF || array[3] !== 0xE0) { return arrayBuffer; } - - var app0Length = array[4] * 256 + array[5]; - var newArrayBuffer = [0xff, 0xd8].concat(exifArray, array.slice(4 + app0Length)); + const app0Length = array[4] * 256 + array[5]; + const newArrayBuffer = [0xFF, 0xD8].concat(exifArray, array.slice(4 + app0Length)); return new Uint8Array(newArrayBuffer); } -var ArrayBuffer$1 = WINDOW.ArrayBuffer, - FileReader = WINDOW.FileReader; -var URL = WINDOW.URL || WINDOW.webkitURL; -var REGEXP_EXTENSION = /\.\w+$/; -var AnotherCompressor = WINDOW.Compressor; +const { + ArrayBuffer: ArrayBuffer$1, + FileReader +} = WINDOW; +const URL = WINDOW.URL || WINDOW.webkitURL; +const REGEXP_EXTENSION = /\.\w+$/; +const AnotherCompressor = WINDOW.Compressor; + /** * Creates a new image compressor. * @class */ - -var Compressor = /*#__PURE__*/function () { +class Compressor { /** * The constructor of Compressor. * @param {File|Blob} file - The target image file for compressing. * @param {Object} [options] - The options for compressing. */ - function Compressor(file, options) { - _classCallCheck(this, Compressor); - + constructor(file, options) { this.file = file; this.exif = []; this.image = new Image(); - this.options = _objectSpread2(_objectSpread2({}, DEFAULTS), options); + this.options = { + ...DEFAULTS, + ...options + }; this.aborted = false; this.result = null; this.init(); } - - _createClass(Compressor, [{ - key: "init", - value: function init() { - var _this = this; - - var file = this.file, - options = this.options; - - if (!isBlob(file)) { - this.fail(new Error('The first argument must be a File or Blob object.')); - return; - } - - var mimeType = file.type; - - if (!isImageType(mimeType)) { - this.fail(new Error('The first argument must be an image File or Blob object.')); - return; - } - - if (!URL || !FileReader) { - this.fail(new Error('The current browser does not support image compression.')); - return; - } - - if (!ArrayBuffer$1) { - options.checkOrientation = false; - options.retainExif = false; - } - - if (URL && !options.checkOrientation && !options.retainExif) { - this.load({ - url: URL.createObjectURL(file) - }); - } else { - var reader = new FileReader(); - var checkOrientation = options.checkOrientation && mimeType === 'image/jpeg'; - this.reader = reader; - - reader.onload = function (_ref) { - var target = _ref.target; - var result = target.result; - var data = {}; - - if (checkOrientation) { - // Reset the orientation value to its default value 1 - // as some iOS browsers will render image with its orientation - var orientation = resetAndGetOrientation(result); - - if (orientation > 1 || !URL) { - // Generate a new URL which has the default orientation value - data.url = arrayBufferToDataURL(result, mimeType); - - if (orientation > 1) { - _extends(data, parseOrientation(orientation)); - } - } else { - data.url = URL.createObjectURL(file); - } - } else { - data.url = result; + init() { + const { + file, + options + } = this; + if (!isBlob(file)) { + this.fail(new Error('The first argument must be a File or Blob object.')); + return; + } + const mimeType = file.type; + if (!isImageType(mimeType)) { + this.fail(new Error('The first argument must be an image File or Blob object.')); + return; + } + if (!URL || !FileReader) { + this.fail(new Error('The current browser does not support image compression.')); + return; + } + if (!ArrayBuffer$1) { + options.checkOrientation = false; + options.retainExif = false; + } + const isJPEGImage = mimeType === 'image/jpeg'; + const checkOrientation = isJPEGImage && options.checkOrientation; + const retainExif = isJPEGImage && options.retainExif; + if (URL && !checkOrientation && !retainExif) { + this.load({ + url: URL.createObjectURL(file) + }); + } else { + const reader = new FileReader(); + this.reader = reader; + reader.onload = _ref => { + let { + target + } = _ref; + const { + result + } = target; + const data = {}; + let orientation = 1; + if (checkOrientation) { + // Reset the orientation value to its default value 1 + // as some iOS browsers will render image with its orientation + orientation = resetAndGetOrientation(result); + if (orientation > 1) { + _extends(data, parseOrientation(orientation)); } + } + if (retainExif) { + this.exif = getExif(result); + } + if (checkOrientation || retainExif) { + if (!URL - if (options.retainExif) { - _this.exif = getExif(result); + // Generate a new URL with the default orientation value 1. + || orientation > 1) { + data.url = arrayBufferToDataURL(result, mimeType); + } else { + data.url = URL.createObjectURL(file); } - - _this.load(data); - }; - - reader.onabort = function () { - _this.fail(new Error('Aborted to read the image with FileReader.')); - }; - - reader.onerror = function () { - _this.fail(new Error('Failed to read the image with FileReader.')); - }; - - reader.onloadend = function () { - _this.reader = null; - }; - - if (checkOrientation || options.retainExif) { - reader.readAsArrayBuffer(file); } else { - reader.readAsDataURL(file); + data.url = result; } - } - } - }, { - key: "load", - value: function load(data) { - var _this2 = this; - - var file = this.file, - image = this.image; - - image.onload = function () { - _this2.draw(_objectSpread2(_objectSpread2({}, data), {}, { - naturalWidth: image.naturalWidth, - naturalHeight: image.naturalHeight - })); + this.load(data); }; - - image.onabort = function () { - _this2.fail(new Error('Aborted to load the image.')); + reader.onabort = () => { + this.fail(new Error('Aborted to read the image with FileReader.')); }; - - image.onerror = function () { - _this2.fail(new Error('Failed to load the image.')); - }; // Match all browsers that use WebKit as the layout engine in iOS devices, - // such as Safari for iOS, Chrome for iOS, and in-app browsers. - - - if (WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent)) { - // Fix the `The operation is insecure` error (#57) - image.crossOrigin = 'anonymous'; + reader.onerror = () => { + this.fail(new Error('Failed to read the image with FileReader.')); + }; + reader.onloadend = () => { + this.reader = null; + }; + if (checkOrientation || retainExif) { + reader.readAsArrayBuffer(file); + } else { + reader.readAsDataURL(file); } - - image.alt = file.name; - image.src = data.url; } - }, { - key: "draw", - value: function draw(_ref2) { - var _this3 = this; - - var naturalWidth = _ref2.naturalWidth, - naturalHeight = _ref2.naturalHeight, - _ref2$rotate = _ref2.rotate, - rotate = _ref2$rotate === void 0 ? 0 : _ref2$rotate, - _ref2$scaleX = _ref2.scaleX, - scaleX = _ref2$scaleX === void 0 ? 1 : _ref2$scaleX, - _ref2$scaleY = _ref2.scaleY, - scaleY = _ref2$scaleY === void 0 ? 1 : _ref2$scaleY; - var file = this.file, - image = this.image, - options = this.options; - var canvas = document.createElement('canvas'); - var context = canvas.getContext('2d'); - var is90DegreesRotated = Math.abs(rotate) % 180 === 90; - var resizable = (options.resize === 'contain' || options.resize === 'cover') && isPositiveNumber(options.width) && isPositiveNumber(options.height); - 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 aspectRatio = naturalWidth / naturalHeight; - var width = options.width, - height = options.height; - - if (is90DegreesRotated) { - var _ref3 = [maxHeight, maxWidth]; - maxWidth = _ref3[0]; - maxHeight = _ref3[1]; - var _ref4 = [minHeight, minWidth]; - minWidth = _ref4[0]; - minHeight = _ref4[1]; - var _ref5 = [height, width]; - width = _ref5[0]; - height = _ref5[1]; - } - - if (resizable) { - aspectRatio = width / height; - } - - var _getAdjustedSizes = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: maxWidth, - height: maxHeight - }, 'contain'); - - maxWidth = _getAdjustedSizes.width; - maxHeight = _getAdjustedSizes.height; - - var _getAdjustedSizes2 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: minWidth, - height: minHeight - }, 'cover'); + } + load(data) { + const { + file, + image + } = this; + image.onload = () => { + this.draw({ + ...data, + naturalWidth: image.naturalWidth, + naturalHeight: image.naturalHeight + }); + }; + image.onabort = () => { + this.fail(new Error('Aborted to load the image.')); + }; + image.onerror = () => { + this.fail(new Error('Failed to load the image.')); + }; - minWidth = _getAdjustedSizes2.width; - minHeight = _getAdjustedSizes2.height; + // Match all browsers that use WebKit as the layout engine in iOS devices, + // such as Safari for iOS, Chrome for iOS, and in-app browsers. + if (WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent)) { + // Fix the `The operation is insecure` error (#57) + image.crossOrigin = 'anonymous'; + } + image.alt = file.name; + image.src = data.url; + } + draw(_ref2) { + let { + naturalWidth, + naturalHeight, + rotate = 0, + scaleX = 1, + scaleY = 1 + } = _ref2; + const { + file, + image, + options + } = this; + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + const is90DegreesRotated = Math.abs(rotate) % 180 === 90; + const resizable = (options.resize === 'contain' || options.resize === 'cover') && isPositiveNumber(options.width) && isPositiveNumber(options.height); + let maxWidth = Math.max(options.maxWidth, 0) || Infinity; + let maxHeight = Math.max(options.maxHeight, 0) || Infinity; + let minWidth = Math.max(options.minWidth, 0) || 0; + let minHeight = Math.max(options.minHeight, 0) || 0; + let aspectRatio = naturalWidth / naturalHeight; + let { + width, + height + } = options; + if (is90DegreesRotated) { + [maxWidth, maxHeight] = [maxHeight, maxWidth]; + [minWidth, minHeight] = [minHeight, minWidth]; + [width, height] = [height, width]; + } + if (resizable) { + aspectRatio = width / height; + } + ({ + width: maxWidth, + height: maxHeight + } = getAdjustedSizes({ + aspectRatio, + width: maxWidth, + height: maxHeight + }, 'contain')); + ({ + width: minWidth, + height: minHeight + } = getAdjustedSizes({ + aspectRatio, + width: minWidth, + height: minHeight + }, 'cover')); + if (resizable) { + ({ + width, + height + } = getAdjustedSizes({ + aspectRatio, + width, + height + }, options.resize)); + } else { + ({ + width = naturalWidth, + height = naturalHeight + } = getAdjustedSizes({ + aspectRatio, + width, + height + })); + } + width = Math.floor(normalizeDecimalNumber(Math.min(Math.max(width, minWidth), maxWidth))); + height = Math.floor(normalizeDecimalNumber(Math.min(Math.max(height, minHeight), maxHeight))); + const destX = -width / 2; + const destY = -height / 2; + const destWidth = width; + const destHeight = height; + const params = []; + if (resizable) { + let srcX = 0; + let srcY = 0; + let srcWidth = naturalWidth; + let srcHeight = naturalHeight; + ({ + width: srcWidth, + height: srcHeight + } = getAdjustedSizes({ + aspectRatio, + width: naturalWidth, + height: naturalHeight + }, { + contain: 'cover', + cover: 'contain' + }[options.resize])); + srcX = (naturalWidth - srcWidth) / 2; + srcY = (naturalHeight - srcHeight) / 2; + params.push(srcX, srcY, srcWidth, srcHeight); + } + params.push(destX, destY, destWidth, destHeight); + if (is90DegreesRotated) { + [width, height] = [height, width]; + } + canvas.width = width; + canvas.height = height; + if (!isImageType(options.mimeType)) { + options.mimeType = file.type; + } + let fillStyle = 'transparent'; - if (resizable) { - var _getAdjustedSizes3 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: width, - height: height - }, options.resize); + // Converts PNG files over the `convertSize` to JPEGs. + if (file.size > options.convertSize && options.convertTypes.indexOf(options.mimeType) >= 0) { + options.mimeType = 'image/jpeg'; + } + const isJPEGImage = options.mimeType === 'image/jpeg'; + if (isJPEGImage) { + fillStyle = '#fff'; + } - width = _getAdjustedSizes3.width; - height = _getAdjustedSizes3.height; - } else { - var _getAdjustedSizes4 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: width, - height: height + // Override the default fill color (#000, black) + context.fillStyle = fillStyle; + context.fillRect(0, 0, width, height); + if (options.beforeDraw) { + options.beforeDraw.call(this, context, canvas); + } + if (this.aborted) { + return; + } + context.save(); + context.translate(width / 2, height / 2); + context.rotate(rotate * Math.PI / 180); + context.scale(scaleX, scaleY); + context.drawImage(image, ...params); + context.restore(); + if (options.drew) { + options.drew.call(this, context, canvas); + } + if (this.aborted) { + return; + } + const callback = blob => { + if (!this.aborted) { + const done = result => this.done({ + naturalWidth, + naturalHeight, + result }); - - var _getAdjustedSizes4$wi = _getAdjustedSizes4.width; - width = _getAdjustedSizes4$wi === void 0 ? naturalWidth : _getAdjustedSizes4$wi; - var _getAdjustedSizes4$he = _getAdjustedSizes4.height; - height = _getAdjustedSizes4$he === void 0 ? naturalHeight : _getAdjustedSizes4$he; - } - - width = Math.floor(normalizeDecimalNumber(Math.min(Math.max(width, minWidth), maxWidth))); - height = Math.floor(normalizeDecimalNumber(Math.min(Math.max(height, minHeight), maxHeight))); - var destX = -width / 2; - var destY = -height / 2; - var destWidth = width; - var destHeight = height; - var params = []; - - if (resizable) { - var srcX = 0; - var srcY = 0; - var srcWidth = naturalWidth; - var srcHeight = naturalHeight; - - var _getAdjustedSizes5 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: naturalWidth, - height: naturalHeight - }, { - contain: 'cover', - cover: 'contain' - }[options.resize]); - - srcWidth = _getAdjustedSizes5.width; - srcHeight = _getAdjustedSizes5.height; - srcX = (naturalWidth - srcWidth) / 2; - srcY = (naturalHeight - srcHeight) / 2; - params.push(srcX, srcY, srcWidth, srcHeight); - } - - params.push(destX, destY, destWidth, destHeight); - - if (is90DegreesRotated) { - var _ref6 = [height, width]; - width = _ref6[0]; - height = _ref6[1]; - } - - canvas.width = width; - canvas.height = height; - - if (!isImageType(options.mimeType)) { - options.mimeType = file.type; - } - - var fillStyle = 'transparent'; // Converts PNG files over the `convertSize` to JPEGs. - - if (file.size > options.convertSize && options.convertTypes.indexOf(options.mimeType) >= 0) { - options.mimeType = 'image/jpeg'; - } - - if (options.mimeType === 'image/jpeg') { - fillStyle = '#fff'; - } // Override the default fill color (#000, black) - - - context.fillStyle = fillStyle; - context.fillRect(0, 0, width, height); - - if (options.beforeDraw) { - options.beforeDraw.call(this, context, canvas); - } - - if (this.aborted) { - return; - } - - context.save(); - context.translate(width / 2, height / 2); - context.rotate(rotate * Math.PI / 180); - context.scale(scaleX, scaleY); - context.drawImage.apply(context, [image].concat(params)); - context.restore(); - - if (options.drew) { - options.drew.call(this, context, canvas); - } - - if (this.aborted) { - return; - } - - var callback = function callback(blob) { - if (!_this3.aborted) { - var done = function done(result) { - return _this3.done({ - naturalWidth: naturalWidth, - naturalHeight: naturalHeight, - result: result + if (blob && isJPEGImage && options.retainExif && this.exif && this.exif.length > 0) { + const next = arrayBuffer => done(toBlob(arrayBufferToDataURL(insertExif(arrayBuffer, this.exif), options.mimeType))); + if (blob.arrayBuffer) { + blob.arrayBuffer().then(next).catch(() => { + this.fail(new Error('Failed to read the compressed image with Blob.arrayBuffer().')); }); - }; - - if (options.retainExif && blob) { - var next = function next(arrayBuffer) { - return done(toBlob(arrayBufferToDataURL(insertExif(arrayBuffer, _this3.exif), options.mimeType))); - }; - - if (blob.arrayBuffer) { - blob.arrayBuffer().then(next).catch(function () { - _this3.fail(new Error('Failed to read the compressed image with Blob.arrayBuffer().')); - }); - } else { - var reader = new FileReader(); - _this3.reader = reader; - - reader.onload = function (_ref7) { - var target = _ref7.target; - next(target.result); - }; - - reader.onabort = function () { - _this3.fail(new Error('Aborted to read the compressed image with FileReader.')); - }; - - reader.onerror = function () { - _this3.fail(new Error('Failed to read the compressed image with FileReader.')); - }; - - reader.onloadend = function () { - _this3.reader = null; - }; - - reader.readAsArrayBuffer(blob); - } } else { - done(blob); + const reader = new FileReader(); + this.reader = reader; + reader.onload = _ref3 => { + let { + target + } = _ref3; + next(target.result); + }; + reader.onabort = () => { + this.fail(new Error('Aborted to read the compressed image with FileReader.')); + }; + reader.onerror = () => { + this.fail(new Error('Failed to read the compressed image with FileReader.')); + }; + reader.onloadend = () => { + this.reader = null; + }; + reader.readAsArrayBuffer(blob); } - } - }; - - if (canvas.toBlob) { - canvas.toBlob(callback, options.mimeType, options.quality); - } else { - callback(toBlob(canvas.toDataURL(options.mimeType, options.quality))); - } - } - }, { - key: "done", - value: function done(_ref8) { - var naturalWidth = _ref8.naturalWidth, - naturalHeight = _ref8.naturalHeight, - result = _ref8.result; - var file = this.file, - image = this.image, - options = this.options; - - 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 (options.strict && result.size > file.size && options.mimeType === file.type && !(options.width > naturalWidth || options.height > naturalHeight || options.minWidth > naturalWidth || options.minHeight > naturalHeight || options.maxWidth < naturalWidth || options.maxHeight < 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)); - } + done(blob); } - } 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); } + }; + if (canvas.toBlob) { + canvas.toBlob(callback, options.mimeType, options.quality); + } else { + callback(toBlob(canvas.toDataURL(options.mimeType, options.quality))); } - }, { - key: "fail", - value: function fail(err) { - var options = this.options; - - if (options.error) { - options.error.call(this, err); - } else { - throw err; - } + } + done(_ref4) { + let { + naturalWidth, + naturalHeight, + result + } = _ref4; + const { + file, + image, + options + } = this; + if (URL && image.src.indexOf('blob:') === 0) { + URL.revokeObjectURL(image.src); } - }, { - key: "abort", - value: function abort() { - if (!this.aborted) { - this.aborted = true; - - if (this.reader) { - this.reader.abort(); - } else if (!this.image.complete) { - this.image.onload = null; - this.image.onabort(); - } else { - this.fail(new Error('The compression process has been aborted.')); + if (result) { + // Returns original file if the result is greater than it and without size related options + if (options.strict && !options.retainExif && result.size > file.size && options.mimeType === file.type && !(options.width > naturalWidth || options.height > naturalHeight || options.minWidth > naturalWidth || options.minHeight > naturalHeight || options.maxWidth < naturalWidth || options.maxHeight < naturalHeight)) { + result = file; + } else { + const 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; } - /** - * Get the no conflict compressor class. - * @returns {Compressor} The compressor class. - */ - - }], [{ - key: "noConflict", - value: function noConflict() { - window.Compressor = AnotherCompressor; - return Compressor; + this.result = result; + if (options.success) { + options.success.call(this, result); } - /** - * Change the default options. - * @param {Object} options - The new default options. - */ - - }, { - key: "setDefaults", - value: function setDefaults(options) { - _extends(DEFAULTS, options); + } + fail(err) { + const { + options + } = this; + if (options.error) { + options.error.call(this, err); + } else { + throw err; + } + } + abort() { + if (!this.aborted) { + this.aborted = true; + if (this.reader) { + this.reader.abort(); + } else if (!this.image.complete) { + this.image.onload = null; + this.image.onabort(); + } else { + this.fail(new Error('The compression process has been aborted.')); + } } - }]); + } + + /** + * Get the no conflict compressor class. + * @returns {Compressor} The compressor class. + */ + static noConflict() { + window.Compressor = AnotherCompressor; + return Compressor; + } - return Compressor; -}(); + /** + * Change the default options. + * @param {Object} options - The new default options. + */ + static setDefaults(options) { + _extends(DEFAULTS, options); + } +} export { Compressor as default }; -//# sourceMappingURL=compressor.esm.js.map diff --git a/dist/compressor.js b/dist/compressor.js index 8b61206..f3abba8 100644 --- a/dist/compressor.js +++ b/dist/compressor.js @@ -1,11 +1,11 @@ /*! - * Compressor.js v1.1.1 + * Compressor.js v1.2.0 * https://fengyuanchen.github.io/compressorjs * * Copyright 2018-present Chen Fengyuan * Released under the MIT license * - * Date: 2023-02-12T06:45:05.457Z + * Date: 2023-02-25T11:35:56.625Z */ (function (global, factory) { @@ -14,96 +14,18 @@ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Compressor = factory()); })(this, (function () { 'use strict'; - function ownKeys(object, enumerableOnly) { - var keys = Object.keys(object); - - if (Object.getOwnPropertySymbols) { - var symbols = Object.getOwnPropertySymbols(object); - - if (enumerableOnly) { - symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - }); - } - - keys.push.apply(keys, symbols); - } - - return keys; - } - - function _objectSpread2(target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i] != null ? arguments[i] : {}; - - if (i % 2) { - ownKeys(Object(source), true).forEach(function (key) { - _defineProperty(target, key, source[key]); - }); - } else if (Object.getOwnPropertyDescriptors) { - Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); - } else { - ownKeys(Object(source)).forEach(function (key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); - }); - } - } - - return target; - } - - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a 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); - } - } - - function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; - } - - function _defineProperty(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - - return obj; - } - function _extends() { - _extends = Object.assign || function (target) { + _extends = Object.assign ? Object.assign.bind() : 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; }; - return _extends.apply(this, arguments); } @@ -122,16 +44,13 @@ * Based on stackoverflow user Stoive's code snippet: * http://stackoverflow.com/q/4998908 */ - (function (module) { if (typeof window === 'undefined') { return; } - (function (window) { var CanvasPrototype = window.HTMLCanvasElement && window.HTMLCanvasElement.prototype; - var hasBlobConstructor = window.Blob && function () { try { return Boolean(new Blob()); @@ -139,7 +58,6 @@ return false; } }(); - var hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && function () { try { return new Blob([new Uint8Array(100)]).size === 100; @@ -147,52 +65,42 @@ 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 - + 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 - - + } + // 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: - - + } + // 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: - - + } + // 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) { @@ -227,7 +135,6 @@ } } } - if (module.exports) { module.exports = dataURLtoBlob; } else { @@ -235,14 +142,12 @@ } })(window); })(canvasToBlob); - var toBlob = canvasToBlob.exports; - var isBlob = function isBlob(value) { + var isBlob = value => { if (typeof Blob === 'undefined') { return false; } - return value instanceof Blob || Object.prototype.toString.call(value) === '[object Blob]'; }; @@ -253,65 +158,55 @@ * @type {boolean} */ strict: true, - /** * Indicates if read the image's Exif Orientation information, * and then rotate or flip the image automatically. * @type {boolean} */ checkOrientation: true, - /** * Indicates if retain the image's Exif information after compressed. * @type {boolean} */ retainExif: false, - /** * 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, - /** * Sets how the size of the image should be resized to the container * specified by the `width` and `height` options. * @type {string} */ resize: 'none', - /** * The quality of the output image. * It must be a number between `0` and `1`, @@ -320,28 +215,24 @@ * @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', - /** * Files whose file type is included in this list, * and whose file size exceeds the `convertSize` value will be converted to JPEGs. * @type {string|Array} */ convertTypes: ['image/png'], - /** * PNG files over this size (5 MB by default) will be converted to JPEGs. * To disable this, just set the value to `Infinity`. * @type {number} */ convertSize: 5000000, - /** * The hook function to execute before draw the image into the canvas for compression. * @type {Function} @@ -353,7 +244,6 @@ * } */ beforeDraw: null, - /** * The hook function to execute after drew the image into the canvas for compression. * @type {Function} @@ -365,7 +255,6 @@ * } */ drew: null, - /** * The hook function to execute when success to compress the image. * @type {Function} @@ -376,7 +265,6 @@ * } */ success: null, - /** * The hook function to execute when fail to compress the image. * @type {Function} @@ -389,54 +277,54 @@ error: null }; - var IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined'; - var WINDOW = IS_BROWSER ? window : {}; + const IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined'; + const WINDOW = IS_BROWSER ? window : {}; /** * Check if the given value is a positive number. * @param {*} value - The value to check. * @returns {boolean} Returns `true` if the given value is a positive number, else `false`. */ + const isPositiveNumber = value => value > 0 && value < Infinity; + const { + slice + } = Array.prototype; - var isPositiveNumber = function isPositiveNumber(value) { - return value > 0 && value < Infinity; - }; - var slice = Array.prototype.slice; /** * Convert array-like or iterable object to an array. * @param {*} value - The value to convert. * @returns {Array} Returns a new array. */ - function toArray(value) { return Array.from ? Array.from(value) : slice.call(value); } - var REGEXP_IMAGE_TYPE = /^image\/.+$/; + const 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. * @returns {boolean} Returns the image extension. */ - function imageTypeToExtension(value) { - var extension = isImageType(value) ? value.substr(6) : ''; - + let extension = isImageType(value) ? value.substr(6) : ''; if (extension === 'jpeg') { extension = 'jpg'; } - - return ".".concat(extension); + return `.${extension}`; } - var fromCharCode = String.fromCharCode; + const { + fromCharCode + } = String; + /** * Get string from char code in data view. * @param {DataView} dataView - The data view for read. @@ -444,83 +332,74 @@ * @param {number} length - The read length. * @returns {string} The read result. */ - function getStringFromCharCode(dataView, start, length) { - var str = ''; - var i; + let str = ''; + let i; length += start; - for (i = start; i < length; i += 1) { str += fromCharCode(dataView.getUint8(i)); } - return str; } - var btoa = WINDOW.btoa; + const { + btoa + } = WINDOW; + /** * 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 chunks = []; - var chunkSize = 8192; - var uint8 = new Uint8Array(arrayBuffer); - + const chunks = []; + const chunkSize = 8192; + let uint8 = new Uint8Array(arrayBuffer); while (uint8.length > 0) { // XXX: Babel's `toConsumableArray` helper will throw error in IE or Safari 9 // eslint-disable-next-line prefer-spread chunks.push(fromCharCode.apply(null, toArray(uint8.subarray(0, chunkSize)))); uint8 = uint8.subarray(chunkSize); } - - return "data:".concat(mimeType, ";base64,").concat(btoa(chunks.join(''))); + return `data:${mimeType};base64,${btoa(chunks.join(''))}`; } + /** * Get orientation value from given array buffer. * @param {ArrayBuffer} arrayBuffer - The array buffer to read. * @returns {number} The read orientation value. */ - function resetAndGetOrientation(arrayBuffer) { - var dataView = new DataView(arrayBuffer); - var orientation; // Ignores range error when the image does not have correct Exif information + const dataView = new DataView(arrayBuffer); + let orientation; + // Ignores range error when the image does not have correct Exif information try { - var littleEndian; - var app1Start; - var ifdStart; // Only handle JPEG image (start by 0xFFD8) + let littleEndian; + let app1Start; + let ifdStart; + // Only handle JPEG image (start by 0xFFD8) if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { - var length = dataView.byteLength; - var offset = 2; - + const length = dataView.byteLength; + let offset = 2; while (offset + 1 < 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; - + const exifIDCode = app1Start + 4; + const tiffOffset = app1Start + 10; if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { - var endianness = dataView.getUint16(tiffOffset); + const endianness = dataView.getUint16(tiffOffset); littleEndian = endianness === 0x4949; - - if (littleEndian || endianness === 0x4D4D - /* bigEndian */ - ) { + if (littleEndian || endianness === 0x4D4D /* bigEndian */) { if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { - var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); - + const firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); if (firstIFDOffset >= 0x00000008) { ifdStart = tiffOffset + firstIFDOffset; } @@ -528,26 +407,21 @@ } } } - if (ifdStart) { - var _length = dataView.getUint16(ifdStart, littleEndian); - - var _offset; - - var i; - - for (i = 0; i < _length; i += 1) { - _offset = ifdStart + i * 12 + 2; - - if (dataView.getUint16(_offset, littleEndian) === 0x0112 - /* Orientation */ - ) { + const length = dataView.getUint16(ifdStart, littleEndian); + let offset; + let i; + 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 + offset += 8; - orientation = dataView.getUint16(_offset, littleEndian); // Override the orientation with its default value + // Get the original orientation value + orientation = dataView.getUint16(offset, littleEndian); - dataView.setUint16(_offset, 1, littleEndian); + // Override the orientation with its default value + dataView.setUint16(offset, 1, littleEndian); break; } } @@ -555,66 +429,64 @@ } catch (e) { orientation = 1; } - 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; - + let rotate = 0; + let scaleX = 1; + let scaleY = 1; switch (orientation) { // Flip horizontal case 2: scaleX = -1; break; - // Rotate left 180° + // Rotate left 180° case 3: rotate = -180; break; - // Flip vertical + // Flip vertical case 4: scaleY = -1; break; - // Flip vertical and rotate right 90° + // Flip vertical and rotate right 90° case 5: rotate = 90; scaleY = -1; break; - // Rotate right 90° + // Rotate right 90° case 6: rotate = 90; break; - // Flip horizontal and rotate right 90° + // Flip horizontal and rotate right 90° case 7: rotate = 90; scaleX = -1; break; - // Rotate left 90° + // Rotate left 90° case 8: rotate = -90; break; } - return { - rotate: rotate, - scaleX: scaleX, - scaleY: scaleY + rotate, + scaleX, + scaleY }; } - var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; + const REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; + /** * Normalize decimal number. * Check out {@link https://0.30000000000000004.com/} @@ -622,29 +494,28 @@ * @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; + let times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000; return REGEXP_DECIMALS.test(value) ? Math.round(value * times) / times : value; } + /** * Get the max sizes in a rectangle under the given aspect ratio. * @param {Object} data - The original sizes. * @param {string} [type='contain'] - The adjust type. * @returns {Object} The result sizes. */ - function getAdjustedSizes(_ref) { - var aspectRatio = _ref.aspectRatio, - height = _ref.height, - width = _ref.width; - var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none'; - var isValidWidth = isPositiveNumber(width); - var isValidHeight = isPositiveNumber(height); - + let { + aspectRatio, + height, + width + } = _ref; + let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none'; + const isValidWidth = isPositiveNumber(width); + const isValidHeight = isPositiveNumber(height); if (isValidWidth && isValidHeight) { - var adjustedWidth = height * aspectRatio; - + const adjustedWidth = height * aspectRatio; if ((type === 'contain' || type === 'none') && adjustedWidth > width || type === 'cover' && adjustedWidth < width) { height = width / aspectRatio; } else { @@ -655,533 +526,469 @@ } else if (isValidHeight) { width = height * aspectRatio; } - return { - width: width, - height: height + width, + height }; } + /** * Get Exif information from the given array buffer. * @param {ArrayBuffer} arrayBuffer - The array buffer to read. * @returns {Array} The read Exif information. */ - function getExif(arrayBuffer) { - var array = toArray(new Uint8Array(arrayBuffer)); - var length = array.length; - var segments = []; - var head = 0; - var endPoint; + const array = toArray(new Uint8Array(arrayBuffer)); + const { + length + } = array; + const segments = []; + let start = 0; + while (start + 3 < length) { + const value = array[start]; + const next = array[start + 1]; - while (head + 1 < length) { // SOS (Start of Scan) - if (array[head] === 0xff && array[head + 1] === 0xda) { + if (value === 0xFF && next === 0xDA) { break; - } // SOI (Start of Image) - + } - if (array[head] === 0xff && array[head + 1] === 0xd8) { - head += 2; + // SOI (Start of Image) + if (value === 0xFF && next === 0xD8) { + start += 2; } else { - var len = array[head + 2] * 256 + array[head + 3]; - endPoint = head + len + 2; - var segment = array.slice(head, endPoint); + const offset = array[start + 2] * 256 + array[start + 3]; + const end = start + offset + 2; + const segment = array.slice(start, end); segments.push(segment); - head = endPoint; + start = end; } } - - return segments.reduce(function (exifArray, current) { - if (current[0] === 0xff && current[1] === 0xe1) { + return segments.reduce((exifArray, current) => { + if (current[0] === 0xFF && current[1] === 0xE1) { return exifArray.concat(current); } - return exifArray; }, []); } + /** * Insert Exif information into the given array buffer. - * @param {ArrayBuffer} arrayBuffer - The array buffer to insert. - * @param {Array} exifArray - The Exif information array. + * @param {ArrayBuffer} arrayBuffer - The array buffer to transform. + * @param {Array} exifArray - The Exif information to insert. * @returns {ArrayBuffer} The transformed array buffer. */ - function insertExif(arrayBuffer, exifArray) { - var array = toArray(new Uint8Array(arrayBuffer)); - - if (array[2] !== 0xff || array[3] !== 0xe0) { + const array = toArray(new Uint8Array(arrayBuffer)); + if (array[2] !== 0xFF || array[3] !== 0xE0) { return arrayBuffer; } - - var app0Length = array[4] * 256 + array[5]; - var newArrayBuffer = [0xff, 0xd8].concat(exifArray, array.slice(4 + app0Length)); + const app0Length = array[4] * 256 + array[5]; + const newArrayBuffer = [0xFF, 0xD8].concat(exifArray, array.slice(4 + app0Length)); return new Uint8Array(newArrayBuffer); } - var ArrayBuffer$1 = WINDOW.ArrayBuffer, - FileReader = WINDOW.FileReader; - var URL = WINDOW.URL || WINDOW.webkitURL; - var REGEXP_EXTENSION = /\.\w+$/; - var AnotherCompressor = WINDOW.Compressor; + const { + ArrayBuffer: ArrayBuffer$1, + FileReader + } = WINDOW; + const URL = WINDOW.URL || WINDOW.webkitURL; + const REGEXP_EXTENSION = /\.\w+$/; + const AnotherCompressor = WINDOW.Compressor; + /** * Creates a new image compressor. * @class */ - - var Compressor = /*#__PURE__*/function () { + class Compressor { /** * The constructor of Compressor. * @param {File|Blob} file - The target image file for compressing. * @param {Object} [options] - The options for compressing. */ - function Compressor(file, options) { - _classCallCheck(this, Compressor); - + constructor(file, options) { this.file = file; this.exif = []; this.image = new Image(); - this.options = _objectSpread2(_objectSpread2({}, DEFAULTS), options); + this.options = { + ...DEFAULTS, + ...options + }; this.aborted = false; this.result = null; this.init(); } - - _createClass(Compressor, [{ - key: "init", - value: function init() { - var _this = this; - - var file = this.file, - options = this.options; - - if (!isBlob(file)) { - this.fail(new Error('The first argument must be a File or Blob object.')); - return; - } - - var mimeType = file.type; - - if (!isImageType(mimeType)) { - this.fail(new Error('The first argument must be an image File or Blob object.')); - return; - } - - if (!URL || !FileReader) { - this.fail(new Error('The current browser does not support image compression.')); - return; - } - - if (!ArrayBuffer$1) { - options.checkOrientation = false; - options.retainExif = false; - } - - if (URL && !options.checkOrientation && !options.retainExif) { - this.load({ - url: URL.createObjectURL(file) - }); - } else { - var reader = new FileReader(); - var checkOrientation = options.checkOrientation && mimeType === 'image/jpeg'; - this.reader = reader; - - reader.onload = function (_ref) { - var target = _ref.target; - var result = target.result; - var data = {}; - - if (checkOrientation) { - // Reset the orientation value to its default value 1 - // as some iOS browsers will render image with its orientation - var orientation = resetAndGetOrientation(result); - - if (orientation > 1 || !URL) { - // Generate a new URL which has the default orientation value - data.url = arrayBufferToDataURL(result, mimeType); - - if (orientation > 1) { - _extends(data, parseOrientation(orientation)); - } - } else { - data.url = URL.createObjectURL(file); - } - } else { - data.url = result; + init() { + const { + file, + options + } = this; + if (!isBlob(file)) { + this.fail(new Error('The first argument must be a File or Blob object.')); + return; + } + const mimeType = file.type; + if (!isImageType(mimeType)) { + this.fail(new Error('The first argument must be an image File or Blob object.')); + return; + } + if (!URL || !FileReader) { + this.fail(new Error('The current browser does not support image compression.')); + return; + } + if (!ArrayBuffer$1) { + options.checkOrientation = false; + options.retainExif = false; + } + const isJPEGImage = mimeType === 'image/jpeg'; + const checkOrientation = isJPEGImage && options.checkOrientation; + const retainExif = isJPEGImage && options.retainExif; + if (URL && !checkOrientation && !retainExif) { + this.load({ + url: URL.createObjectURL(file) + }); + } else { + const reader = new FileReader(); + this.reader = reader; + reader.onload = _ref => { + let { + target + } = _ref; + const { + result + } = target; + const data = {}; + let orientation = 1; + if (checkOrientation) { + // Reset the orientation value to its default value 1 + // as some iOS browsers will render image with its orientation + orientation = resetAndGetOrientation(result); + if (orientation > 1) { + _extends(data, parseOrientation(orientation)); } + } + if (retainExif) { + this.exif = getExif(result); + } + if (checkOrientation || retainExif) { + if (!URL - if (options.retainExif) { - _this.exif = getExif(result); + // Generate a new URL with the default orientation value 1. + || orientation > 1) { + data.url = arrayBufferToDataURL(result, mimeType); + } else { + data.url = URL.createObjectURL(file); } - - _this.load(data); - }; - - reader.onabort = function () { - _this.fail(new Error('Aborted to read the image with FileReader.')); - }; - - reader.onerror = function () { - _this.fail(new Error('Failed to read the image with FileReader.')); - }; - - reader.onloadend = function () { - _this.reader = null; - }; - - if (checkOrientation || options.retainExif) { - reader.readAsArrayBuffer(file); } else { - reader.readAsDataURL(file); + data.url = result; } - } - } - }, { - key: "load", - value: function load(data) { - var _this2 = this; - - var file = this.file, - image = this.image; - - image.onload = function () { - _this2.draw(_objectSpread2(_objectSpread2({}, data), {}, { - naturalWidth: image.naturalWidth, - naturalHeight: image.naturalHeight - })); + this.load(data); }; - - image.onabort = function () { - _this2.fail(new Error('Aborted to load the image.')); + reader.onabort = () => { + this.fail(new Error('Aborted to read the image with FileReader.')); }; - - image.onerror = function () { - _this2.fail(new Error('Failed to load the image.')); - }; // Match all browsers that use WebKit as the layout engine in iOS devices, - // such as Safari for iOS, Chrome for iOS, and in-app browsers. - - - if (WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent)) { - // Fix the `The operation is insecure` error (#57) - image.crossOrigin = 'anonymous'; + reader.onerror = () => { + this.fail(new Error('Failed to read the image with FileReader.')); + }; + reader.onloadend = () => { + this.reader = null; + }; + if (checkOrientation || retainExif) { + reader.readAsArrayBuffer(file); + } else { + reader.readAsDataURL(file); } - - image.alt = file.name; - image.src = data.url; } - }, { - key: "draw", - value: function draw(_ref2) { - var _this3 = this; - - var naturalWidth = _ref2.naturalWidth, - naturalHeight = _ref2.naturalHeight, - _ref2$rotate = _ref2.rotate, - rotate = _ref2$rotate === void 0 ? 0 : _ref2$rotate, - _ref2$scaleX = _ref2.scaleX, - scaleX = _ref2$scaleX === void 0 ? 1 : _ref2$scaleX, - _ref2$scaleY = _ref2.scaleY, - scaleY = _ref2$scaleY === void 0 ? 1 : _ref2$scaleY; - var file = this.file, - image = this.image, - options = this.options; - var canvas = document.createElement('canvas'); - var context = canvas.getContext('2d'); - var is90DegreesRotated = Math.abs(rotate) % 180 === 90; - var resizable = (options.resize === 'contain' || options.resize === 'cover') && isPositiveNumber(options.width) && isPositiveNumber(options.height); - 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 aspectRatio = naturalWidth / naturalHeight; - var width = options.width, - height = options.height; - - if (is90DegreesRotated) { - var _ref3 = [maxHeight, maxWidth]; - maxWidth = _ref3[0]; - maxHeight = _ref3[1]; - var _ref4 = [minHeight, minWidth]; - minWidth = _ref4[0]; - minHeight = _ref4[1]; - var _ref5 = [height, width]; - width = _ref5[0]; - height = _ref5[1]; - } - - if (resizable) { - aspectRatio = width / height; - } - - var _getAdjustedSizes = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: maxWidth, - height: maxHeight - }, 'contain'); - - maxWidth = _getAdjustedSizes.width; - maxHeight = _getAdjustedSizes.height; - - var _getAdjustedSizes2 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: minWidth, - height: minHeight - }, 'cover'); + } + load(data) { + const { + file, + image + } = this; + image.onload = () => { + this.draw({ + ...data, + naturalWidth: image.naturalWidth, + naturalHeight: image.naturalHeight + }); + }; + image.onabort = () => { + this.fail(new Error('Aborted to load the image.')); + }; + image.onerror = () => { + this.fail(new Error('Failed to load the image.')); + }; - minWidth = _getAdjustedSizes2.width; - minHeight = _getAdjustedSizes2.height; + // Match all browsers that use WebKit as the layout engine in iOS devices, + // such as Safari for iOS, Chrome for iOS, and in-app browsers. + if (WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent)) { + // Fix the `The operation is insecure` error (#57) + image.crossOrigin = 'anonymous'; + } + image.alt = file.name; + image.src = data.url; + } + draw(_ref2) { + let { + naturalWidth, + naturalHeight, + rotate = 0, + scaleX = 1, + scaleY = 1 + } = _ref2; + const { + file, + image, + options + } = this; + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + const is90DegreesRotated = Math.abs(rotate) % 180 === 90; + const resizable = (options.resize === 'contain' || options.resize === 'cover') && isPositiveNumber(options.width) && isPositiveNumber(options.height); + let maxWidth = Math.max(options.maxWidth, 0) || Infinity; + let maxHeight = Math.max(options.maxHeight, 0) || Infinity; + let minWidth = Math.max(options.minWidth, 0) || 0; + let minHeight = Math.max(options.minHeight, 0) || 0; + let aspectRatio = naturalWidth / naturalHeight; + let { + width, + height + } = options; + if (is90DegreesRotated) { + [maxWidth, maxHeight] = [maxHeight, maxWidth]; + [minWidth, minHeight] = [minHeight, minWidth]; + [width, height] = [height, width]; + } + if (resizable) { + aspectRatio = width / height; + } + ({ + width: maxWidth, + height: maxHeight + } = getAdjustedSizes({ + aspectRatio, + width: maxWidth, + height: maxHeight + }, 'contain')); + ({ + width: minWidth, + height: minHeight + } = getAdjustedSizes({ + aspectRatio, + width: minWidth, + height: minHeight + }, 'cover')); + if (resizable) { + ({ + width, + height + } = getAdjustedSizes({ + aspectRatio, + width, + height + }, options.resize)); + } else { + ({ + width = naturalWidth, + height = naturalHeight + } = getAdjustedSizes({ + aspectRatio, + width, + height + })); + } + width = Math.floor(normalizeDecimalNumber(Math.min(Math.max(width, minWidth), maxWidth))); + height = Math.floor(normalizeDecimalNumber(Math.min(Math.max(height, minHeight), maxHeight))); + const destX = -width / 2; + const destY = -height / 2; + const destWidth = width; + const destHeight = height; + const params = []; + if (resizable) { + let srcX = 0; + let srcY = 0; + let srcWidth = naturalWidth; + let srcHeight = naturalHeight; + ({ + width: srcWidth, + height: srcHeight + } = getAdjustedSizes({ + aspectRatio, + width: naturalWidth, + height: naturalHeight + }, { + contain: 'cover', + cover: 'contain' + }[options.resize])); + srcX = (naturalWidth - srcWidth) / 2; + srcY = (naturalHeight - srcHeight) / 2; + params.push(srcX, srcY, srcWidth, srcHeight); + } + params.push(destX, destY, destWidth, destHeight); + if (is90DegreesRotated) { + [width, height] = [height, width]; + } + canvas.width = width; + canvas.height = height; + if (!isImageType(options.mimeType)) { + options.mimeType = file.type; + } + let fillStyle = 'transparent'; - if (resizable) { - var _getAdjustedSizes3 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: width, - height: height - }, options.resize); + // Converts PNG files over the `convertSize` to JPEGs. + if (file.size > options.convertSize && options.convertTypes.indexOf(options.mimeType) >= 0) { + options.mimeType = 'image/jpeg'; + } + const isJPEGImage = options.mimeType === 'image/jpeg'; + if (isJPEGImage) { + fillStyle = '#fff'; + } - width = _getAdjustedSizes3.width; - height = _getAdjustedSizes3.height; - } else { - var _getAdjustedSizes4 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: width, - height: height + // Override the default fill color (#000, black) + context.fillStyle = fillStyle; + context.fillRect(0, 0, width, height); + if (options.beforeDraw) { + options.beforeDraw.call(this, context, canvas); + } + if (this.aborted) { + return; + } + context.save(); + context.translate(width / 2, height / 2); + context.rotate(rotate * Math.PI / 180); + context.scale(scaleX, scaleY); + context.drawImage(image, ...params); + context.restore(); + if (options.drew) { + options.drew.call(this, context, canvas); + } + if (this.aborted) { + return; + } + const callback = blob => { + if (!this.aborted) { + const done = result => this.done({ + naturalWidth, + naturalHeight, + result }); - - var _getAdjustedSizes4$wi = _getAdjustedSizes4.width; - width = _getAdjustedSizes4$wi === void 0 ? naturalWidth : _getAdjustedSizes4$wi; - var _getAdjustedSizes4$he = _getAdjustedSizes4.height; - height = _getAdjustedSizes4$he === void 0 ? naturalHeight : _getAdjustedSizes4$he; - } - - width = Math.floor(normalizeDecimalNumber(Math.min(Math.max(width, minWidth), maxWidth))); - height = Math.floor(normalizeDecimalNumber(Math.min(Math.max(height, minHeight), maxHeight))); - var destX = -width / 2; - var destY = -height / 2; - var destWidth = width; - var destHeight = height; - var params = []; - - if (resizable) { - var srcX = 0; - var srcY = 0; - var srcWidth = naturalWidth; - var srcHeight = naturalHeight; - - var _getAdjustedSizes5 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: naturalWidth, - height: naturalHeight - }, { - contain: 'cover', - cover: 'contain' - }[options.resize]); - - srcWidth = _getAdjustedSizes5.width; - srcHeight = _getAdjustedSizes5.height; - srcX = (naturalWidth - srcWidth) / 2; - srcY = (naturalHeight - srcHeight) / 2; - params.push(srcX, srcY, srcWidth, srcHeight); - } - - params.push(destX, destY, destWidth, destHeight); - - if (is90DegreesRotated) { - var _ref6 = [height, width]; - width = _ref6[0]; - height = _ref6[1]; - } - - canvas.width = width; - canvas.height = height; - - if (!isImageType(options.mimeType)) { - options.mimeType = file.type; - } - - var fillStyle = 'transparent'; // Converts PNG files over the `convertSize` to JPEGs. - - if (file.size > options.convertSize && options.convertTypes.indexOf(options.mimeType) >= 0) { - options.mimeType = 'image/jpeg'; - } - - if (options.mimeType === 'image/jpeg') { - fillStyle = '#fff'; - } // Override the default fill color (#000, black) - - - context.fillStyle = fillStyle; - context.fillRect(0, 0, width, height); - - if (options.beforeDraw) { - options.beforeDraw.call(this, context, canvas); - } - - if (this.aborted) { - return; - } - - context.save(); - context.translate(width / 2, height / 2); - context.rotate(rotate * Math.PI / 180); - context.scale(scaleX, scaleY); - context.drawImage.apply(context, [image].concat(params)); - context.restore(); - - if (options.drew) { - options.drew.call(this, context, canvas); - } - - if (this.aborted) { - return; - } - - var callback = function callback(blob) { - if (!_this3.aborted) { - var done = function done(result) { - return _this3.done({ - naturalWidth: naturalWidth, - naturalHeight: naturalHeight, - result: result + if (blob && isJPEGImage && options.retainExif && this.exif && this.exif.length > 0) { + const next = arrayBuffer => done(toBlob(arrayBufferToDataURL(insertExif(arrayBuffer, this.exif), options.mimeType))); + if (blob.arrayBuffer) { + blob.arrayBuffer().then(next).catch(() => { + this.fail(new Error('Failed to read the compressed image with Blob.arrayBuffer().')); }); - }; - - if (options.retainExif && blob) { - var next = function next(arrayBuffer) { - return done(toBlob(arrayBufferToDataURL(insertExif(arrayBuffer, _this3.exif), options.mimeType))); - }; - - if (blob.arrayBuffer) { - blob.arrayBuffer().then(next).catch(function () { - _this3.fail(new Error('Failed to read the compressed image with Blob.arrayBuffer().')); - }); - } else { - var reader = new FileReader(); - _this3.reader = reader; - - reader.onload = function (_ref7) { - var target = _ref7.target; - next(target.result); - }; - - reader.onabort = function () { - _this3.fail(new Error('Aborted to read the compressed image with FileReader.')); - }; - - reader.onerror = function () { - _this3.fail(new Error('Failed to read the compressed image with FileReader.')); - }; - - reader.onloadend = function () { - _this3.reader = null; - }; - - reader.readAsArrayBuffer(blob); - } } else { - done(blob); + const reader = new FileReader(); + this.reader = reader; + reader.onload = _ref3 => { + let { + target + } = _ref3; + next(target.result); + }; + reader.onabort = () => { + this.fail(new Error('Aborted to read the compressed image with FileReader.')); + }; + reader.onerror = () => { + this.fail(new Error('Failed to read the compressed image with FileReader.')); + }; + reader.onloadend = () => { + this.reader = null; + }; + reader.readAsArrayBuffer(blob); } - } - }; - - if (canvas.toBlob) { - canvas.toBlob(callback, options.mimeType, options.quality); - } else { - callback(toBlob(canvas.toDataURL(options.mimeType, options.quality))); - } - } - }, { - key: "done", - value: function done(_ref8) { - var naturalWidth = _ref8.naturalWidth, - naturalHeight = _ref8.naturalHeight, - result = _ref8.result; - var file = this.file, - image = this.image, - options = this.options; - - 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 (options.strict && result.size > file.size && options.mimeType === file.type && !(options.width > naturalWidth || options.height > naturalHeight || options.minWidth > naturalWidth || options.minHeight > naturalHeight || options.maxWidth < naturalWidth || options.maxHeight < 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)); - } + done(blob); } - } 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); } + }; + if (canvas.toBlob) { + canvas.toBlob(callback, options.mimeType, options.quality); + } else { + callback(toBlob(canvas.toDataURL(options.mimeType, options.quality))); } - }, { - key: "fail", - value: function fail(err) { - var options = this.options; - - if (options.error) { - options.error.call(this, err); - } else { - throw err; - } + } + done(_ref4) { + let { + naturalWidth, + naturalHeight, + result + } = _ref4; + const { + file, + image, + options + } = this; + if (URL && image.src.indexOf('blob:') === 0) { + URL.revokeObjectURL(image.src); } - }, { - key: "abort", - value: function abort() { - if (!this.aborted) { - this.aborted = true; - - if (this.reader) { - this.reader.abort(); - } else if (!this.image.complete) { - this.image.onload = null; - this.image.onabort(); - } else { - this.fail(new Error('The compression process has been aborted.')); + if (result) { + // Returns original file if the result is greater than it and without size related options + if (options.strict && !options.retainExif && result.size > file.size && options.mimeType === file.type && !(options.width > naturalWidth || options.height > naturalHeight || options.minWidth > naturalWidth || options.minHeight > naturalHeight || options.maxWidth < naturalWidth || options.maxHeight < naturalHeight)) { + result = file; + } else { + const 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; } - /** - * Get the no conflict compressor class. - * @returns {Compressor} The compressor class. - */ - - }], [{ - key: "noConflict", - value: function noConflict() { - window.Compressor = AnotherCompressor; - return Compressor; + this.result = result; + if (options.success) { + options.success.call(this, result); } - /** - * Change the default options. - * @param {Object} options - The new default options. - */ - - }, { - key: "setDefaults", - value: function setDefaults(options) { - _extends(DEFAULTS, options); + } + fail(err) { + const { + options + } = this; + if (options.error) { + options.error.call(this, err); + } else { + throw err; + } + } + abort() { + if (!this.aborted) { + this.aborted = true; + if (this.reader) { + this.reader.abort(); + } else if (!this.image.complete) { + this.image.onload = null; + this.image.onabort(); + } else { + this.fail(new Error('The compression process has been aborted.')); + } } - }]); + } + + /** + * Get the no conflict compressor class. + * @returns {Compressor} The compressor class. + */ + static noConflict() { + window.Compressor = AnotherCompressor; + return Compressor; + } - return Compressor; - }(); + /** + * Change the default options. + * @param {Object} options - The new default options. + */ + static setDefaults(options) { + _extends(DEFAULTS, options); + } + } return Compressor; })); -//# sourceMappingURL=compressor.js.map diff --git a/dist/compressor.min.js b/dist/compressor.min.js index f18770a..24ec287 100644 --- a/dist/compressor.min.js +++ b/dist/compressor.min.js @@ -1,10 +1,10 @@ /*! - * Compressor.js v1.1.1 + * Compressor.js v1.2.0 * https://fengyuanchen.github.io/compressorjs * * Copyright 2018-present Chen Fengyuan * Released under the MIT license * - * Date: 2021-10-05T02:32:40.212Z + * Date: 2023-02-25T11:35:56.625Z */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Compressor=t()}(this,function(){"use strict";function t(t,e){var r,i=Object.keys(t);return Object.getOwnPropertySymbols&&(r=Object.getOwnPropertySymbols(t),e&&(r=r.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),i.push.apply(i,r)),i}function a(i){for(var e=1;ef.convertSize&&0<=f.convertTypes.indexOf(f.mimeType)&&(f.mimeType="image/jpeg"),"image/jpeg"===f.mimeType&&(B="#fff"),m.fillStyle=B,m.fillRect(0,0,e,l),f.beforeDraw&&f.beforeDraw.call(this,m,d),this.aborted||(m.save(),m.translate(e/2,l/2),m.rotate(n*Math.PI/180),m.scale(s,c),m.drawImage.apply(m,[u].concat(a)),m.restore(),f.drew&&f.drew.call(this,m,d),this.aborted||(m=function(e){t.aborted||t.done({naturalWidth:r,naturalHeight:i,result:e})},d.toBlob?d.toBlob(m,f.mimeType,f.quality):m(T(d.toDataURL(f.mimeType,f.quality)))))}},{key:"done",value:function(e){var t=e.naturalWidth,r=e.naturalHeight,i=e.result,a=this.file,n=this.image,e=this.options;A&&!e.checkOrientation&&A.revokeObjectURL(n.src),!i||e.strict&&i.size>a.size&&e.mimeType===a.type&&!(e.width>t||e.height>r||e.minWidth>t||e.minHeight>r||e.maxWidth0a||"cover"===e&&o{var e=(e=e.target).result,t={};let i=1;o&&1<(i=b(e))&&s(t,function(e){let t=0,i=1,r=1;switch(e){case 2:i=-1;break;case 3:t=-180;break;case 4:r=-1;break;case 5:t=90,r=-1;break;case 6:t=90;break;case 7:t=90,i=-1;break;case 8:t=-90}return{rotate:t,scaleX:i,scaleY:r}}(i)),n&&(this.exif=function(e){var t=D(new Uint8Array(e)),i=t.length,r=[];let a=0;for(;a+3255===t[0]&&225===t[1]?e.concat(t):e,[])}(e)),o||n?!y||1{this.fail(new Error("Aborted to read the image with FileReader."))},t.onerror=()=>{this.fail(new Error("Failed to read the image with FileReader."))},t.onloadend=()=>{this.reader=null},o||n?t.readAsArrayBuffer(r):t.readAsDataURL(r)):this.load({url:y.createObjectURL(r)})}else this.fail(new Error("The current browser does not support image compression."));else this.fail(new Error("The first argument must be an image File or Blob object."))}else this.fail(new Error("The first argument must be a File or Blob object."))}load(e){const{file:t,image:i}=this;i.onload=()=>{this.draw({...e,naturalWidth:i.naturalWidth,naturalHeight:i.naturalHeight})},i.onabort=()=>{this.fail(new Error("Aborted to load the image."))},i.onerror=()=>{this.fail(new Error("Failed to load the image."))},n.navigator&&/(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(n.navigator.userAgent)&&(i.crossOrigin="anonymous"),i.alt=t.name,i.src=e.url}draw(e){let{naturalWidth:a,naturalHeight:o,rotate:t=0,scaleX:i=1,scaleY:r=1}=e;const{file:n,image:s,options:l}=this;var h=(e=document.createElement("canvas")).getContext("2d"),c=Math.abs(t)%180==90,d=("contain"===l.resize||"cover"===l.resize)&&j(l.width)&&j(l.height);let f=Math.max(l.maxWidth,0)||1/0,u=Math.max(l.maxHeight,0)||1/0,m=Math.max(l.minWidth,0)||0,g=Math.max(l.minHeight,0)||0,b=a/o,{width:p,height:w}=l;c&&([f,u]=[u,f],[m,g]=[g,m],[p,w]=[w,p]),d&&(b=p/w),{width:f,height:u}=O({aspectRatio:b,width:f,height:u},"contain"),{width:m,height:g}=O({aspectRatio:b,width:m,height:g},"cover"),d?{width:p,height:w}=O({aspectRatio:b,width:p,height:w},l.resize):{width:p=a,height:w=o}=O({aspectRatio:b,width:p,height:w}),p=Math.floor(H(Math.min(Math.max(p,m),f))),w=Math.floor(H(Math.min(Math.max(w,g),u)));var y,v,B,U=-p/2,x=-w/2,A=p,R=w,T=[];d&&(y=d=0,v=a,B=o,{width:v,height:B}=O({aspectRatio:b,width:a,height:o},{contain:"cover",cover:"contain"}[l.resize]),d=(a-v)/2,y=(o-B)/2,T.push(d,y,v,B)),T.push(U,x,A,R),c&&([p,w]=[w,p]),e.width=p,e.height=w,k(l.mimeType)||(l.mimeType=n.type);let E="transparent";n.size>l.convertSize&&0<=l.convertTypes.indexOf(l.mimeType)&&(l.mimeType="image/jpeg");const M="image/jpeg"===l.mimeType;M&&(E="#fff"),h.fillStyle=E,h.fillRect(0,0,p,w),l.beforeDraw&&l.beforeDraw.call(this,h,e),this.aborted||(h.save(),h.translate(p/2,w/2),h.rotate(t*Math.PI/180),h.scale(i,r),h.drawImage(s,...T),h.restore(),l.drew&&l.drew.call(this,h,e),this.aborted)||(d=e=>{if(!this.aborted){const r=e=>this.done({naturalWidth:a,naturalHeight:o,result:e});if(e&&M&&l.retainExif&&this.exif&&0{return r(L(z((t=this.exif,255!==(i=D(new Uint8Array(e)))[2]||224!==i[3]?e:(e=256*i[4]+i[5],t=[255,216].concat(t,i.slice(4+e)),new Uint8Array(t))),l.mimeType)));var t,i};var t;e.arrayBuffer?e.arrayBuffer().then(i).catch(()=>{this.fail(new Error("Failed to read the compressed image with Blob.arrayBuffer()."))}):(t=new C,(this.reader=t).onload=e=>{e=e.target,i(e.result)},t.onabort=()=>{this.fail(new Error("Aborted to read the compressed image with FileReader."))},t.onerror=()=>{this.fail(new Error("Failed to read the compressed image with FileReader."))},t.onloadend=()=>{this.reader=null},t.readAsArrayBuffer(e))}else r(e)}},e.toBlob?e.toBlob(d,l.mimeType,l.quality):d(L(e.toDataURL(l.mimeType,l.quality))))}done(e){let{naturalWidth:t,naturalHeight:i,result:r}=e;var{file:e,image:a,options:o}=this;y&&0===a.src.indexOf("blob:")&&y.revokeObjectURL(a.src),!r||o.strict&&!o.retainExif&&r.size>e.size&&o.mimeType===e.type&&!(o.width>t||o.height>i||o.minWidth>t||o.minHeight>i||o.maxWidth
-

Compressor.js v1.1.1

+

Compressor.js v1.2.0

JavaScript image compressor.

diff --git a/docs/js/compressor.js b/docs/js/compressor.js index 8b61206..f3abba8 100755 --- a/docs/js/compressor.js +++ b/docs/js/compressor.js @@ -1,11 +1,11 @@ /*! - * Compressor.js v1.1.1 + * Compressor.js v1.2.0 * https://fengyuanchen.github.io/compressorjs * * Copyright 2018-present Chen Fengyuan * Released under the MIT license * - * Date: 2023-02-12T06:45:05.457Z + * Date: 2023-02-25T11:35:56.625Z */ (function (global, factory) { @@ -14,96 +14,18 @@ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Compressor = factory()); })(this, (function () { 'use strict'; - function ownKeys(object, enumerableOnly) { - var keys = Object.keys(object); - - if (Object.getOwnPropertySymbols) { - var symbols = Object.getOwnPropertySymbols(object); - - if (enumerableOnly) { - symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - }); - } - - keys.push.apply(keys, symbols); - } - - return keys; - } - - function _objectSpread2(target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i] != null ? arguments[i] : {}; - - if (i % 2) { - ownKeys(Object(source), true).forEach(function (key) { - _defineProperty(target, key, source[key]); - }); - } else if (Object.getOwnPropertyDescriptors) { - Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); - } else { - ownKeys(Object(source)).forEach(function (key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); - }); - } - } - - return target; - } - - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a 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); - } - } - - function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; - } - - function _defineProperty(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - - return obj; - } - function _extends() { - _extends = Object.assign || function (target) { + _extends = Object.assign ? Object.assign.bind() : 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; }; - return _extends.apply(this, arguments); } @@ -122,16 +44,13 @@ * Based on stackoverflow user Stoive's code snippet: * http://stackoverflow.com/q/4998908 */ - (function (module) { if (typeof window === 'undefined') { return; } - (function (window) { var CanvasPrototype = window.HTMLCanvasElement && window.HTMLCanvasElement.prototype; - var hasBlobConstructor = window.Blob && function () { try { return Boolean(new Blob()); @@ -139,7 +58,6 @@ return false; } }(); - var hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && function () { try { return new Blob([new Uint8Array(100)]).size === 100; @@ -147,52 +65,42 @@ 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 - + 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 - - + } + // 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: - - + } + // 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: - - + } + // 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) { @@ -227,7 +135,6 @@ } } } - if (module.exports) { module.exports = dataURLtoBlob; } else { @@ -235,14 +142,12 @@ } })(window); })(canvasToBlob); - var toBlob = canvasToBlob.exports; - var isBlob = function isBlob(value) { + var isBlob = value => { if (typeof Blob === 'undefined') { return false; } - return value instanceof Blob || Object.prototype.toString.call(value) === '[object Blob]'; }; @@ -253,65 +158,55 @@ * @type {boolean} */ strict: true, - /** * Indicates if read the image's Exif Orientation information, * and then rotate or flip the image automatically. * @type {boolean} */ checkOrientation: true, - /** * Indicates if retain the image's Exif information after compressed. * @type {boolean} */ retainExif: false, - /** * 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, - /** * Sets how the size of the image should be resized to the container * specified by the `width` and `height` options. * @type {string} */ resize: 'none', - /** * The quality of the output image. * It must be a number between `0` and `1`, @@ -320,28 +215,24 @@ * @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', - /** * Files whose file type is included in this list, * and whose file size exceeds the `convertSize` value will be converted to JPEGs. * @type {string|Array} */ convertTypes: ['image/png'], - /** * PNG files over this size (5 MB by default) will be converted to JPEGs. * To disable this, just set the value to `Infinity`. * @type {number} */ convertSize: 5000000, - /** * The hook function to execute before draw the image into the canvas for compression. * @type {Function} @@ -353,7 +244,6 @@ * } */ beforeDraw: null, - /** * The hook function to execute after drew the image into the canvas for compression. * @type {Function} @@ -365,7 +255,6 @@ * } */ drew: null, - /** * The hook function to execute when success to compress the image. * @type {Function} @@ -376,7 +265,6 @@ * } */ success: null, - /** * The hook function to execute when fail to compress the image. * @type {Function} @@ -389,54 +277,54 @@ error: null }; - var IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined'; - var WINDOW = IS_BROWSER ? window : {}; + const IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined'; + const WINDOW = IS_BROWSER ? window : {}; /** * Check if the given value is a positive number. * @param {*} value - The value to check. * @returns {boolean} Returns `true` if the given value is a positive number, else `false`. */ + const isPositiveNumber = value => value > 0 && value < Infinity; + const { + slice + } = Array.prototype; - var isPositiveNumber = function isPositiveNumber(value) { - return value > 0 && value < Infinity; - }; - var slice = Array.prototype.slice; /** * Convert array-like or iterable object to an array. * @param {*} value - The value to convert. * @returns {Array} Returns a new array. */ - function toArray(value) { return Array.from ? Array.from(value) : slice.call(value); } - var REGEXP_IMAGE_TYPE = /^image\/.+$/; + const 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. * @returns {boolean} Returns the image extension. */ - function imageTypeToExtension(value) { - var extension = isImageType(value) ? value.substr(6) : ''; - + let extension = isImageType(value) ? value.substr(6) : ''; if (extension === 'jpeg') { extension = 'jpg'; } - - return ".".concat(extension); + return `.${extension}`; } - var fromCharCode = String.fromCharCode; + const { + fromCharCode + } = String; + /** * Get string from char code in data view. * @param {DataView} dataView - The data view for read. @@ -444,83 +332,74 @@ * @param {number} length - The read length. * @returns {string} The read result. */ - function getStringFromCharCode(dataView, start, length) { - var str = ''; - var i; + let str = ''; + let i; length += start; - for (i = start; i < length; i += 1) { str += fromCharCode(dataView.getUint8(i)); } - return str; } - var btoa = WINDOW.btoa; + const { + btoa + } = WINDOW; + /** * 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 chunks = []; - var chunkSize = 8192; - var uint8 = new Uint8Array(arrayBuffer); - + const chunks = []; + const chunkSize = 8192; + let uint8 = new Uint8Array(arrayBuffer); while (uint8.length > 0) { // XXX: Babel's `toConsumableArray` helper will throw error in IE or Safari 9 // eslint-disable-next-line prefer-spread chunks.push(fromCharCode.apply(null, toArray(uint8.subarray(0, chunkSize)))); uint8 = uint8.subarray(chunkSize); } - - return "data:".concat(mimeType, ";base64,").concat(btoa(chunks.join(''))); + return `data:${mimeType};base64,${btoa(chunks.join(''))}`; } + /** * Get orientation value from given array buffer. * @param {ArrayBuffer} arrayBuffer - The array buffer to read. * @returns {number} The read orientation value. */ - function resetAndGetOrientation(arrayBuffer) { - var dataView = new DataView(arrayBuffer); - var orientation; // Ignores range error when the image does not have correct Exif information + const dataView = new DataView(arrayBuffer); + let orientation; + // Ignores range error when the image does not have correct Exif information try { - var littleEndian; - var app1Start; - var ifdStart; // Only handle JPEG image (start by 0xFFD8) + let littleEndian; + let app1Start; + let ifdStart; + // Only handle JPEG image (start by 0xFFD8) if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { - var length = dataView.byteLength; - var offset = 2; - + const length = dataView.byteLength; + let offset = 2; while (offset + 1 < 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; - + const exifIDCode = app1Start + 4; + const tiffOffset = app1Start + 10; if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { - var endianness = dataView.getUint16(tiffOffset); + const endianness = dataView.getUint16(tiffOffset); littleEndian = endianness === 0x4949; - - if (littleEndian || endianness === 0x4D4D - /* bigEndian */ - ) { + if (littleEndian || endianness === 0x4D4D /* bigEndian */) { if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { - var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); - + const firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); if (firstIFDOffset >= 0x00000008) { ifdStart = tiffOffset + firstIFDOffset; } @@ -528,26 +407,21 @@ } } } - if (ifdStart) { - var _length = dataView.getUint16(ifdStart, littleEndian); - - var _offset; - - var i; - - for (i = 0; i < _length; i += 1) { - _offset = ifdStart + i * 12 + 2; - - if (dataView.getUint16(_offset, littleEndian) === 0x0112 - /* Orientation */ - ) { + const length = dataView.getUint16(ifdStart, littleEndian); + let offset; + let i; + 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 + offset += 8; - orientation = dataView.getUint16(_offset, littleEndian); // Override the orientation with its default value + // Get the original orientation value + orientation = dataView.getUint16(offset, littleEndian); - dataView.setUint16(_offset, 1, littleEndian); + // Override the orientation with its default value + dataView.setUint16(offset, 1, littleEndian); break; } } @@ -555,66 +429,64 @@ } catch (e) { orientation = 1; } - 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; - + let rotate = 0; + let scaleX = 1; + let scaleY = 1; switch (orientation) { // Flip horizontal case 2: scaleX = -1; break; - // Rotate left 180° + // Rotate left 180° case 3: rotate = -180; break; - // Flip vertical + // Flip vertical case 4: scaleY = -1; break; - // Flip vertical and rotate right 90° + // Flip vertical and rotate right 90° case 5: rotate = 90; scaleY = -1; break; - // Rotate right 90° + // Rotate right 90° case 6: rotate = 90; break; - // Flip horizontal and rotate right 90° + // Flip horizontal and rotate right 90° case 7: rotate = 90; scaleX = -1; break; - // Rotate left 90° + // Rotate left 90° case 8: rotate = -90; break; } - return { - rotate: rotate, - scaleX: scaleX, - scaleY: scaleY + rotate, + scaleX, + scaleY }; } - var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; + const REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/; + /** * Normalize decimal number. * Check out {@link https://0.30000000000000004.com/} @@ -622,29 +494,28 @@ * @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; + let times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000; return REGEXP_DECIMALS.test(value) ? Math.round(value * times) / times : value; } + /** * Get the max sizes in a rectangle under the given aspect ratio. * @param {Object} data - The original sizes. * @param {string} [type='contain'] - The adjust type. * @returns {Object} The result sizes. */ - function getAdjustedSizes(_ref) { - var aspectRatio = _ref.aspectRatio, - height = _ref.height, - width = _ref.width; - var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none'; - var isValidWidth = isPositiveNumber(width); - var isValidHeight = isPositiveNumber(height); - + let { + aspectRatio, + height, + width + } = _ref; + let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none'; + const isValidWidth = isPositiveNumber(width); + const isValidHeight = isPositiveNumber(height); if (isValidWidth && isValidHeight) { - var adjustedWidth = height * aspectRatio; - + const adjustedWidth = height * aspectRatio; if ((type === 'contain' || type === 'none') && adjustedWidth > width || type === 'cover' && adjustedWidth < width) { height = width / aspectRatio; } else { @@ -655,533 +526,469 @@ } else if (isValidHeight) { width = height * aspectRatio; } - return { - width: width, - height: height + width, + height }; } + /** * Get Exif information from the given array buffer. * @param {ArrayBuffer} arrayBuffer - The array buffer to read. * @returns {Array} The read Exif information. */ - function getExif(arrayBuffer) { - var array = toArray(new Uint8Array(arrayBuffer)); - var length = array.length; - var segments = []; - var head = 0; - var endPoint; + const array = toArray(new Uint8Array(arrayBuffer)); + const { + length + } = array; + const segments = []; + let start = 0; + while (start + 3 < length) { + const value = array[start]; + const next = array[start + 1]; - while (head + 1 < length) { // SOS (Start of Scan) - if (array[head] === 0xff && array[head + 1] === 0xda) { + if (value === 0xFF && next === 0xDA) { break; - } // SOI (Start of Image) - + } - if (array[head] === 0xff && array[head + 1] === 0xd8) { - head += 2; + // SOI (Start of Image) + if (value === 0xFF && next === 0xD8) { + start += 2; } else { - var len = array[head + 2] * 256 + array[head + 3]; - endPoint = head + len + 2; - var segment = array.slice(head, endPoint); + const offset = array[start + 2] * 256 + array[start + 3]; + const end = start + offset + 2; + const segment = array.slice(start, end); segments.push(segment); - head = endPoint; + start = end; } } - - return segments.reduce(function (exifArray, current) { - if (current[0] === 0xff && current[1] === 0xe1) { + return segments.reduce((exifArray, current) => { + if (current[0] === 0xFF && current[1] === 0xE1) { return exifArray.concat(current); } - return exifArray; }, []); } + /** * Insert Exif information into the given array buffer. - * @param {ArrayBuffer} arrayBuffer - The array buffer to insert. - * @param {Array} exifArray - The Exif information array. + * @param {ArrayBuffer} arrayBuffer - The array buffer to transform. + * @param {Array} exifArray - The Exif information to insert. * @returns {ArrayBuffer} The transformed array buffer. */ - function insertExif(arrayBuffer, exifArray) { - var array = toArray(new Uint8Array(arrayBuffer)); - - if (array[2] !== 0xff || array[3] !== 0xe0) { + const array = toArray(new Uint8Array(arrayBuffer)); + if (array[2] !== 0xFF || array[3] !== 0xE0) { return arrayBuffer; } - - var app0Length = array[4] * 256 + array[5]; - var newArrayBuffer = [0xff, 0xd8].concat(exifArray, array.slice(4 + app0Length)); + const app0Length = array[4] * 256 + array[5]; + const newArrayBuffer = [0xFF, 0xD8].concat(exifArray, array.slice(4 + app0Length)); return new Uint8Array(newArrayBuffer); } - var ArrayBuffer$1 = WINDOW.ArrayBuffer, - FileReader = WINDOW.FileReader; - var URL = WINDOW.URL || WINDOW.webkitURL; - var REGEXP_EXTENSION = /\.\w+$/; - var AnotherCompressor = WINDOW.Compressor; + const { + ArrayBuffer: ArrayBuffer$1, + FileReader + } = WINDOW; + const URL = WINDOW.URL || WINDOW.webkitURL; + const REGEXP_EXTENSION = /\.\w+$/; + const AnotherCompressor = WINDOW.Compressor; + /** * Creates a new image compressor. * @class */ - - var Compressor = /*#__PURE__*/function () { + class Compressor { /** * The constructor of Compressor. * @param {File|Blob} file - The target image file for compressing. * @param {Object} [options] - The options for compressing. */ - function Compressor(file, options) { - _classCallCheck(this, Compressor); - + constructor(file, options) { this.file = file; this.exif = []; this.image = new Image(); - this.options = _objectSpread2(_objectSpread2({}, DEFAULTS), options); + this.options = { + ...DEFAULTS, + ...options + }; this.aborted = false; this.result = null; this.init(); } - - _createClass(Compressor, [{ - key: "init", - value: function init() { - var _this = this; - - var file = this.file, - options = this.options; - - if (!isBlob(file)) { - this.fail(new Error('The first argument must be a File or Blob object.')); - return; - } - - var mimeType = file.type; - - if (!isImageType(mimeType)) { - this.fail(new Error('The first argument must be an image File or Blob object.')); - return; - } - - if (!URL || !FileReader) { - this.fail(new Error('The current browser does not support image compression.')); - return; - } - - if (!ArrayBuffer$1) { - options.checkOrientation = false; - options.retainExif = false; - } - - if (URL && !options.checkOrientation && !options.retainExif) { - this.load({ - url: URL.createObjectURL(file) - }); - } else { - var reader = new FileReader(); - var checkOrientation = options.checkOrientation && mimeType === 'image/jpeg'; - this.reader = reader; - - reader.onload = function (_ref) { - var target = _ref.target; - var result = target.result; - var data = {}; - - if (checkOrientation) { - // Reset the orientation value to its default value 1 - // as some iOS browsers will render image with its orientation - var orientation = resetAndGetOrientation(result); - - if (orientation > 1 || !URL) { - // Generate a new URL which has the default orientation value - data.url = arrayBufferToDataURL(result, mimeType); - - if (orientation > 1) { - _extends(data, parseOrientation(orientation)); - } - } else { - data.url = URL.createObjectURL(file); - } - } else { - data.url = result; + init() { + const { + file, + options + } = this; + if (!isBlob(file)) { + this.fail(new Error('The first argument must be a File or Blob object.')); + return; + } + const mimeType = file.type; + if (!isImageType(mimeType)) { + this.fail(new Error('The first argument must be an image File or Blob object.')); + return; + } + if (!URL || !FileReader) { + this.fail(new Error('The current browser does not support image compression.')); + return; + } + if (!ArrayBuffer$1) { + options.checkOrientation = false; + options.retainExif = false; + } + const isJPEGImage = mimeType === 'image/jpeg'; + const checkOrientation = isJPEGImage && options.checkOrientation; + const retainExif = isJPEGImage && options.retainExif; + if (URL && !checkOrientation && !retainExif) { + this.load({ + url: URL.createObjectURL(file) + }); + } else { + const reader = new FileReader(); + this.reader = reader; + reader.onload = _ref => { + let { + target + } = _ref; + const { + result + } = target; + const data = {}; + let orientation = 1; + if (checkOrientation) { + // Reset the orientation value to its default value 1 + // as some iOS browsers will render image with its orientation + orientation = resetAndGetOrientation(result); + if (orientation > 1) { + _extends(data, parseOrientation(orientation)); } + } + if (retainExif) { + this.exif = getExif(result); + } + if (checkOrientation || retainExif) { + if (!URL - if (options.retainExif) { - _this.exif = getExif(result); + // Generate a new URL with the default orientation value 1. + || orientation > 1) { + data.url = arrayBufferToDataURL(result, mimeType); + } else { + data.url = URL.createObjectURL(file); } - - _this.load(data); - }; - - reader.onabort = function () { - _this.fail(new Error('Aborted to read the image with FileReader.')); - }; - - reader.onerror = function () { - _this.fail(new Error('Failed to read the image with FileReader.')); - }; - - reader.onloadend = function () { - _this.reader = null; - }; - - if (checkOrientation || options.retainExif) { - reader.readAsArrayBuffer(file); } else { - reader.readAsDataURL(file); + data.url = result; } - } - } - }, { - key: "load", - value: function load(data) { - var _this2 = this; - - var file = this.file, - image = this.image; - - image.onload = function () { - _this2.draw(_objectSpread2(_objectSpread2({}, data), {}, { - naturalWidth: image.naturalWidth, - naturalHeight: image.naturalHeight - })); + this.load(data); }; - - image.onabort = function () { - _this2.fail(new Error('Aborted to load the image.')); + reader.onabort = () => { + this.fail(new Error('Aborted to read the image with FileReader.')); }; - - image.onerror = function () { - _this2.fail(new Error('Failed to load the image.')); - }; // Match all browsers that use WebKit as the layout engine in iOS devices, - // such as Safari for iOS, Chrome for iOS, and in-app browsers. - - - if (WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent)) { - // Fix the `The operation is insecure` error (#57) - image.crossOrigin = 'anonymous'; + reader.onerror = () => { + this.fail(new Error('Failed to read the image with FileReader.')); + }; + reader.onloadend = () => { + this.reader = null; + }; + if (checkOrientation || retainExif) { + reader.readAsArrayBuffer(file); + } else { + reader.readAsDataURL(file); } - - image.alt = file.name; - image.src = data.url; } - }, { - key: "draw", - value: function draw(_ref2) { - var _this3 = this; - - var naturalWidth = _ref2.naturalWidth, - naturalHeight = _ref2.naturalHeight, - _ref2$rotate = _ref2.rotate, - rotate = _ref2$rotate === void 0 ? 0 : _ref2$rotate, - _ref2$scaleX = _ref2.scaleX, - scaleX = _ref2$scaleX === void 0 ? 1 : _ref2$scaleX, - _ref2$scaleY = _ref2.scaleY, - scaleY = _ref2$scaleY === void 0 ? 1 : _ref2$scaleY; - var file = this.file, - image = this.image, - options = this.options; - var canvas = document.createElement('canvas'); - var context = canvas.getContext('2d'); - var is90DegreesRotated = Math.abs(rotate) % 180 === 90; - var resizable = (options.resize === 'contain' || options.resize === 'cover') && isPositiveNumber(options.width) && isPositiveNumber(options.height); - 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 aspectRatio = naturalWidth / naturalHeight; - var width = options.width, - height = options.height; - - if (is90DegreesRotated) { - var _ref3 = [maxHeight, maxWidth]; - maxWidth = _ref3[0]; - maxHeight = _ref3[1]; - var _ref4 = [minHeight, minWidth]; - minWidth = _ref4[0]; - minHeight = _ref4[1]; - var _ref5 = [height, width]; - width = _ref5[0]; - height = _ref5[1]; - } - - if (resizable) { - aspectRatio = width / height; - } - - var _getAdjustedSizes = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: maxWidth, - height: maxHeight - }, 'contain'); - - maxWidth = _getAdjustedSizes.width; - maxHeight = _getAdjustedSizes.height; - - var _getAdjustedSizes2 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: minWidth, - height: minHeight - }, 'cover'); + } + load(data) { + const { + file, + image + } = this; + image.onload = () => { + this.draw({ + ...data, + naturalWidth: image.naturalWidth, + naturalHeight: image.naturalHeight + }); + }; + image.onabort = () => { + this.fail(new Error('Aborted to load the image.')); + }; + image.onerror = () => { + this.fail(new Error('Failed to load the image.')); + }; - minWidth = _getAdjustedSizes2.width; - minHeight = _getAdjustedSizes2.height; + // Match all browsers that use WebKit as the layout engine in iOS devices, + // such as Safari for iOS, Chrome for iOS, and in-app browsers. + if (WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent)) { + // Fix the `The operation is insecure` error (#57) + image.crossOrigin = 'anonymous'; + } + image.alt = file.name; + image.src = data.url; + } + draw(_ref2) { + let { + naturalWidth, + naturalHeight, + rotate = 0, + scaleX = 1, + scaleY = 1 + } = _ref2; + const { + file, + image, + options + } = this; + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + const is90DegreesRotated = Math.abs(rotate) % 180 === 90; + const resizable = (options.resize === 'contain' || options.resize === 'cover') && isPositiveNumber(options.width) && isPositiveNumber(options.height); + let maxWidth = Math.max(options.maxWidth, 0) || Infinity; + let maxHeight = Math.max(options.maxHeight, 0) || Infinity; + let minWidth = Math.max(options.minWidth, 0) || 0; + let minHeight = Math.max(options.minHeight, 0) || 0; + let aspectRatio = naturalWidth / naturalHeight; + let { + width, + height + } = options; + if (is90DegreesRotated) { + [maxWidth, maxHeight] = [maxHeight, maxWidth]; + [minWidth, minHeight] = [minHeight, minWidth]; + [width, height] = [height, width]; + } + if (resizable) { + aspectRatio = width / height; + } + ({ + width: maxWidth, + height: maxHeight + } = getAdjustedSizes({ + aspectRatio, + width: maxWidth, + height: maxHeight + }, 'contain')); + ({ + width: minWidth, + height: minHeight + } = getAdjustedSizes({ + aspectRatio, + width: minWidth, + height: minHeight + }, 'cover')); + if (resizable) { + ({ + width, + height + } = getAdjustedSizes({ + aspectRatio, + width, + height + }, options.resize)); + } else { + ({ + width = naturalWidth, + height = naturalHeight + } = getAdjustedSizes({ + aspectRatio, + width, + height + })); + } + width = Math.floor(normalizeDecimalNumber(Math.min(Math.max(width, minWidth), maxWidth))); + height = Math.floor(normalizeDecimalNumber(Math.min(Math.max(height, minHeight), maxHeight))); + const destX = -width / 2; + const destY = -height / 2; + const destWidth = width; + const destHeight = height; + const params = []; + if (resizable) { + let srcX = 0; + let srcY = 0; + let srcWidth = naturalWidth; + let srcHeight = naturalHeight; + ({ + width: srcWidth, + height: srcHeight + } = getAdjustedSizes({ + aspectRatio, + width: naturalWidth, + height: naturalHeight + }, { + contain: 'cover', + cover: 'contain' + }[options.resize])); + srcX = (naturalWidth - srcWidth) / 2; + srcY = (naturalHeight - srcHeight) / 2; + params.push(srcX, srcY, srcWidth, srcHeight); + } + params.push(destX, destY, destWidth, destHeight); + if (is90DegreesRotated) { + [width, height] = [height, width]; + } + canvas.width = width; + canvas.height = height; + if (!isImageType(options.mimeType)) { + options.mimeType = file.type; + } + let fillStyle = 'transparent'; - if (resizable) { - var _getAdjustedSizes3 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: width, - height: height - }, options.resize); + // Converts PNG files over the `convertSize` to JPEGs. + if (file.size > options.convertSize && options.convertTypes.indexOf(options.mimeType) >= 0) { + options.mimeType = 'image/jpeg'; + } + const isJPEGImage = options.mimeType === 'image/jpeg'; + if (isJPEGImage) { + fillStyle = '#fff'; + } - width = _getAdjustedSizes3.width; - height = _getAdjustedSizes3.height; - } else { - var _getAdjustedSizes4 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: width, - height: height + // Override the default fill color (#000, black) + context.fillStyle = fillStyle; + context.fillRect(0, 0, width, height); + if (options.beforeDraw) { + options.beforeDraw.call(this, context, canvas); + } + if (this.aborted) { + return; + } + context.save(); + context.translate(width / 2, height / 2); + context.rotate(rotate * Math.PI / 180); + context.scale(scaleX, scaleY); + context.drawImage(image, ...params); + context.restore(); + if (options.drew) { + options.drew.call(this, context, canvas); + } + if (this.aborted) { + return; + } + const callback = blob => { + if (!this.aborted) { + const done = result => this.done({ + naturalWidth, + naturalHeight, + result }); - - var _getAdjustedSizes4$wi = _getAdjustedSizes4.width; - width = _getAdjustedSizes4$wi === void 0 ? naturalWidth : _getAdjustedSizes4$wi; - var _getAdjustedSizes4$he = _getAdjustedSizes4.height; - height = _getAdjustedSizes4$he === void 0 ? naturalHeight : _getAdjustedSizes4$he; - } - - width = Math.floor(normalizeDecimalNumber(Math.min(Math.max(width, minWidth), maxWidth))); - height = Math.floor(normalizeDecimalNumber(Math.min(Math.max(height, minHeight), maxHeight))); - var destX = -width / 2; - var destY = -height / 2; - var destWidth = width; - var destHeight = height; - var params = []; - - if (resizable) { - var srcX = 0; - var srcY = 0; - var srcWidth = naturalWidth; - var srcHeight = naturalHeight; - - var _getAdjustedSizes5 = getAdjustedSizes({ - aspectRatio: aspectRatio, - width: naturalWidth, - height: naturalHeight - }, { - contain: 'cover', - cover: 'contain' - }[options.resize]); - - srcWidth = _getAdjustedSizes5.width; - srcHeight = _getAdjustedSizes5.height; - srcX = (naturalWidth - srcWidth) / 2; - srcY = (naturalHeight - srcHeight) / 2; - params.push(srcX, srcY, srcWidth, srcHeight); - } - - params.push(destX, destY, destWidth, destHeight); - - if (is90DegreesRotated) { - var _ref6 = [height, width]; - width = _ref6[0]; - height = _ref6[1]; - } - - canvas.width = width; - canvas.height = height; - - if (!isImageType(options.mimeType)) { - options.mimeType = file.type; - } - - var fillStyle = 'transparent'; // Converts PNG files over the `convertSize` to JPEGs. - - if (file.size > options.convertSize && options.convertTypes.indexOf(options.mimeType) >= 0) { - options.mimeType = 'image/jpeg'; - } - - if (options.mimeType === 'image/jpeg') { - fillStyle = '#fff'; - } // Override the default fill color (#000, black) - - - context.fillStyle = fillStyle; - context.fillRect(0, 0, width, height); - - if (options.beforeDraw) { - options.beforeDraw.call(this, context, canvas); - } - - if (this.aborted) { - return; - } - - context.save(); - context.translate(width / 2, height / 2); - context.rotate(rotate * Math.PI / 180); - context.scale(scaleX, scaleY); - context.drawImage.apply(context, [image].concat(params)); - context.restore(); - - if (options.drew) { - options.drew.call(this, context, canvas); - } - - if (this.aborted) { - return; - } - - var callback = function callback(blob) { - if (!_this3.aborted) { - var done = function done(result) { - return _this3.done({ - naturalWidth: naturalWidth, - naturalHeight: naturalHeight, - result: result + if (blob && isJPEGImage && options.retainExif && this.exif && this.exif.length > 0) { + const next = arrayBuffer => done(toBlob(arrayBufferToDataURL(insertExif(arrayBuffer, this.exif), options.mimeType))); + if (blob.arrayBuffer) { + blob.arrayBuffer().then(next).catch(() => { + this.fail(new Error('Failed to read the compressed image with Blob.arrayBuffer().')); }); - }; - - if (options.retainExif && blob) { - var next = function next(arrayBuffer) { - return done(toBlob(arrayBufferToDataURL(insertExif(arrayBuffer, _this3.exif), options.mimeType))); - }; - - if (blob.arrayBuffer) { - blob.arrayBuffer().then(next).catch(function () { - _this3.fail(new Error('Failed to read the compressed image with Blob.arrayBuffer().')); - }); - } else { - var reader = new FileReader(); - _this3.reader = reader; - - reader.onload = function (_ref7) { - var target = _ref7.target; - next(target.result); - }; - - reader.onabort = function () { - _this3.fail(new Error('Aborted to read the compressed image with FileReader.')); - }; - - reader.onerror = function () { - _this3.fail(new Error('Failed to read the compressed image with FileReader.')); - }; - - reader.onloadend = function () { - _this3.reader = null; - }; - - reader.readAsArrayBuffer(blob); - } } else { - done(blob); + const reader = new FileReader(); + this.reader = reader; + reader.onload = _ref3 => { + let { + target + } = _ref3; + next(target.result); + }; + reader.onabort = () => { + this.fail(new Error('Aborted to read the compressed image with FileReader.')); + }; + reader.onerror = () => { + this.fail(new Error('Failed to read the compressed image with FileReader.')); + }; + reader.onloadend = () => { + this.reader = null; + }; + reader.readAsArrayBuffer(blob); } - } - }; - - if (canvas.toBlob) { - canvas.toBlob(callback, options.mimeType, options.quality); - } else { - callback(toBlob(canvas.toDataURL(options.mimeType, options.quality))); - } - } - }, { - key: "done", - value: function done(_ref8) { - var naturalWidth = _ref8.naturalWidth, - naturalHeight = _ref8.naturalHeight, - result = _ref8.result; - var file = this.file, - image = this.image, - options = this.options; - - 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 (options.strict && result.size > file.size && options.mimeType === file.type && !(options.width > naturalWidth || options.height > naturalHeight || options.minWidth > naturalWidth || options.minHeight > naturalHeight || options.maxWidth < naturalWidth || options.maxHeight < 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)); - } + done(blob); } - } 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); } + }; + if (canvas.toBlob) { + canvas.toBlob(callback, options.mimeType, options.quality); + } else { + callback(toBlob(canvas.toDataURL(options.mimeType, options.quality))); } - }, { - key: "fail", - value: function fail(err) { - var options = this.options; - - if (options.error) { - options.error.call(this, err); - } else { - throw err; - } + } + done(_ref4) { + let { + naturalWidth, + naturalHeight, + result + } = _ref4; + const { + file, + image, + options + } = this; + if (URL && image.src.indexOf('blob:') === 0) { + URL.revokeObjectURL(image.src); } - }, { - key: "abort", - value: function abort() { - if (!this.aborted) { - this.aborted = true; - - if (this.reader) { - this.reader.abort(); - } else if (!this.image.complete) { - this.image.onload = null; - this.image.onabort(); - } else { - this.fail(new Error('The compression process has been aborted.')); + if (result) { + // Returns original file if the result is greater than it and without size related options + if (options.strict && !options.retainExif && result.size > file.size && options.mimeType === file.type && !(options.width > naturalWidth || options.height > naturalHeight || options.minWidth > naturalWidth || options.minHeight > naturalHeight || options.maxWidth < naturalWidth || options.maxHeight < naturalHeight)) { + result = file; + } else { + const 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; } - /** - * Get the no conflict compressor class. - * @returns {Compressor} The compressor class. - */ - - }], [{ - key: "noConflict", - value: function noConflict() { - window.Compressor = AnotherCompressor; - return Compressor; + this.result = result; + if (options.success) { + options.success.call(this, result); } - /** - * Change the default options. - * @param {Object} options - The new default options. - */ - - }, { - key: "setDefaults", - value: function setDefaults(options) { - _extends(DEFAULTS, options); + } + fail(err) { + const { + options + } = this; + if (options.error) { + options.error.call(this, err); + } else { + throw err; + } + } + abort() { + if (!this.aborted) { + this.aborted = true; + if (this.reader) { + this.reader.abort(); + } else if (!this.image.complete) { + this.image.onload = null; + this.image.onabort(); + } else { + this.fail(new Error('The compression process has been aborted.')); + } } - }]); + } + + /** + * Get the no conflict compressor class. + * @returns {Compressor} The compressor class. + */ + static noConflict() { + window.Compressor = AnotherCompressor; + return Compressor; + } - return Compressor; - }(); + /** + * Change the default options. + * @param {Object} options - The new default options. + */ + static setDefaults(options) { + _extends(DEFAULTS, options); + } + } return Compressor; })); -//# sourceMappingURL=compressor.js.map diff --git a/package-lock.json b/package-lock.json index 28501d1..c6ed5e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,23 +1,23 @@ { "name": "compressorjs", - "version": "1.1.1", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "compressorjs", - "version": "1.1.1", + "version": "1.2.0", "license": "MIT", "dependencies": { "blueimp-canvas-to-blob": "^3.29.0", "is-blob": "^2.1.0" }, "devDependencies": { - "@babel/core": "^7.20.12", + "@babel/core": "^7.21.0", "@babel/plugin-transform-object-assign": "^7.18.6", "@babel/preset-env": "^7.20.2", - "@commitlint/cli": "^17.4.2", - "@commitlint/config-conventional": "^17.4.2", + "@commitlint/cli": "^17.4.4", + "@commitlint/config-conventional": "^17.4.4", "@rollup/plugin-babel": "^5.3.1", "@rollup/plugin-commonjs": "^21.1.0", "@rollup/plugin-node-resolve": "^13.3.0", @@ -40,11 +40,11 @@ "karma-mocha": "^2.0.1", "karma-mocha-reporter": "^2.2.5", "karma-rollup-preprocessor": "^7.0.8", - "lint-staged": "^13.1.1", + "lint-staged": "^13.1.2", "mocha": "^10.2.0", - "puppeteer": "^19.6.3", + "puppeteer": "^19.7.2", "rollup": "^2.79.1", - "stylelint": "^15.1.0", + "stylelint": "^15.2.0", "stylelint-config-standard": "^30.0.1", "stylelint-order": "^6.0.2", "uglify-js": "^3.17.4" @@ -85,21 +85,21 @@ } }, "node_modules/@babel/core": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", - "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", + "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", "dev": true, "dependencies": { - "@ampproject/remapping": "^2.1.0", + "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", + "@babel/generator": "^7.21.0", "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", + "@babel/helper-module-transforms": "^7.21.0", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.0", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.12", - "@babel/types": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -115,13 +115,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.20.14", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz", - "integrity": "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==", + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", + "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", "dev": true, "dependencies": { - "@babel/types": "^7.20.7", + "@babel/types": "^7.21.0", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -263,13 +264,13 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "dev": true, "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -312,9 +313,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", - "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", @@ -323,8 +324,8 @@ "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.10", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" }, "engines": { "node": ">=6.9.0" @@ -465,14 +466,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.13.tgz", - "integrity": "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", "dev": true, "dependencies": { "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.13", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -493,9 +494,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.15", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.15.tgz", - "integrity": "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1637,19 +1638,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz", - "integrity": "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", + "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", + "@babel/generator": "^7.21.1", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.13", - "@babel/types": "^7.20.7", + "@babel/parser": "^7.21.2", + "@babel/types": "^7.21.2", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1658,9 +1659,9 @@ } }, "node_modules/@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", + "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.19.4", @@ -1681,16 +1682,16 @@ } }, "node_modules/@commitlint/cli": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.4.2.tgz", - "integrity": "sha512-0rPGJ2O1owhpxMIXL9YJ2CgPkdrFLKZElIZHXDN8L8+qWK1DGH7Q7IelBT1pchXTYTuDlqkOTdh//aTvT3bSUA==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.4.4.tgz", + "integrity": "sha512-HwKlD7CPVMVGTAeFZylVNy14Vm5POVY0WxPkZr7EXLC/os0LH/obs6z4HRvJtH/nHCMYBvUBQhGwnufKfTjd5g==", "dev": true, "dependencies": { - "@commitlint/format": "^17.4.0", - "@commitlint/lint": "^17.4.2", - "@commitlint/load": "^17.4.2", - "@commitlint/read": "^17.4.2", - "@commitlint/types": "^17.4.0", + "@commitlint/format": "^17.4.4", + "@commitlint/lint": "^17.4.4", + "@commitlint/load": "^17.4.4", + "@commitlint/read": "^17.4.4", + "@commitlint/types": "^17.4.4", "execa": "^5.0.0", "lodash.isfunction": "^3.0.9", "resolve-from": "5.0.0", @@ -1705,9 +1706,9 @@ } }, "node_modules/@commitlint/config-conventional": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.4.2.tgz", - "integrity": "sha512-JVo1moSj5eDMoql159q8zKCU8lkOhQ+b23Vl3LVVrS6PXDLQIELnJ34ChQmFVbBdSSRNAbbXnRDhosFU+wnuHw==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.4.4.tgz", + "integrity": "sha512-u6ztvxqzi6NuhrcEDR7a+z0yrh11elY66nRrQIpqsqW6sZmpxYkDLtpRH8jRML+mmxYQ8s4qqF06Q/IQx5aJeQ==", "dev": true, "dependencies": { "conventional-changelog-conventionalcommits": "^5.0.0" @@ -1717,12 +1718,12 @@ } }, "node_modules/@commitlint/config-validator": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.4.0.tgz", - "integrity": "sha512-Sa/+8KNpDXz4zT4bVbz2fpFjvgkPO6u2V2fP4TKgt6FjmOw2z3eEX859vtfeaTav/ukBw0/0jr+5ZTZp9zCBhA==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.4.4.tgz", + "integrity": "sha512-bi0+TstqMiqoBAQDvdEP4AFh0GaKyLFlPPEObgI29utoKEYoPQTvF0EYqIwYYLEoJYhj5GfMIhPHJkTJhagfeg==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.0", + "@commitlint/types": "^17.4.4", "ajv": "^8.11.0" }, "engines": { @@ -1730,12 +1731,12 @@ } }, "node_modules/@commitlint/ensure": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.4.0.tgz", - "integrity": "sha512-7oAxt25je0jeQ/E0O/M8L3ADb1Cvweu/5lc/kYF8g/kXatI0wxGE5La52onnAUAWeWlsuvBNar15WcrmDmr5Mw==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.4.4.tgz", + "integrity": "sha512-AHsFCNh8hbhJiuZ2qHv/m59W/GRE9UeOXbkOqxYMNNg9pJ7qELnFcwj5oYpa6vzTSHtPGKf3C2yUFNy1GGHq6g==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.0", + "@commitlint/types": "^17.4.4", "lodash.camelcase": "^4.3.0", "lodash.kebabcase": "^4.1.1", "lodash.snakecase": "^4.1.1", @@ -1756,12 +1757,12 @@ } }, "node_modules/@commitlint/format": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.4.0.tgz", - "integrity": "sha512-Z2bWAU5+f1YZh9W76c84J8iLIWIvvm+mzqogTz0Nsc1x6EHW0Z2gI38g5HAjB0r0I3ZjR15IDEJKhsxyblcyhA==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.4.4.tgz", + "integrity": "sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.0", + "@commitlint/types": "^17.4.4", "chalk": "^4.1.0" }, "engines": { @@ -1839,12 +1840,12 @@ } }, "node_modules/@commitlint/is-ignored": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.4.2.tgz", - "integrity": "sha512-1b2Y2qJ6n7bHG9K6h8S4lBGUl6kc7mMhJN9gy1SQfUZqe92ToDjUTtgNWb6LbzR1X8Cq4SEus4VU8Z/riEa94Q==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.4.4.tgz", + "integrity": "sha512-Y3eo1SFJ2JQDik4rWkBC4tlRIxlXEFrRWxcyrzb1PUT2k3kZ/XGNuCDfk/u0bU2/yS0tOA/mTjFsV+C4qyACHw==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.0", + "@commitlint/types": "^17.4.4", "semver": "7.3.8" }, "engines": { @@ -1885,30 +1886,30 @@ "dev": true }, "node_modules/@commitlint/lint": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.4.2.tgz", - "integrity": "sha512-HcymabrdBhsDMNzIv146+ZPNBPBK5gMNsVH+el2lCagnYgCi/4ixrHooeVyS64Fgce2K26+MC7OQ4vVH8wQWVw==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.4.4.tgz", + "integrity": "sha512-qgkCRRFjyhbMDWsti/5jRYVJkgYZj4r+ZmweZObnbYqPUl5UKLWMf9a/ZZisOI4JfiPmRktYRZ2JmqlSvg+ccw==", "dev": true, "dependencies": { - "@commitlint/is-ignored": "^17.4.2", - "@commitlint/parse": "^17.4.2", - "@commitlint/rules": "^17.4.2", - "@commitlint/types": "^17.4.0" + "@commitlint/is-ignored": "^17.4.4", + "@commitlint/parse": "^17.4.4", + "@commitlint/rules": "^17.4.4", + "@commitlint/types": "^17.4.4" }, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/load": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.4.2.tgz", - "integrity": "sha512-Si++F85rJ9t4hw6JcOw1i2h0fdpdFQt0YKwjuK4bk9KhFjyFkRxvR3SB2dPaMs+EwWlDrDBGL+ygip1QD6gmPw==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.4.4.tgz", + "integrity": "sha512-z6uFIQ7wfKX5FGBe1AkOF4l/ShOQsaa1ml/nLMkbW7R/xF8galGS7Zh0yHvzVp/srtfS0brC+0bUfQfmpMPFVQ==", "dev": true, "dependencies": { - "@commitlint/config-validator": "^17.4.0", + "@commitlint/config-validator": "^17.4.4", "@commitlint/execute-rule": "^17.4.0", - "@commitlint/resolve-extends": "^17.4.0", - "@commitlint/types": "^17.4.0", + "@commitlint/resolve-extends": "^17.4.4", + "@commitlint/types": "^17.4.4", "@types/node": "*", "chalk": "^4.1.0", "cosmiconfig": "^8.0.0", @@ -2004,12 +2005,12 @@ } }, "node_modules/@commitlint/parse": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.4.2.tgz", - "integrity": "sha512-DK4EwqhxfXpyCA+UH8TBRIAXAfmmX4q9QRBz/2h9F9sI91yt6mltTrL6TKURMcjUVmgaB80wgS9QybNIyVBIJA==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.4.4.tgz", + "integrity": "sha512-EKzz4f49d3/OU0Fplog7nwz/lAfXMaDxtriidyGF9PtR+SRbgv4FhsfF310tKxs6EPj8Y+aWWuX3beN5s+yqGg==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.0", + "@commitlint/types": "^17.4.4", "conventional-changelog-angular": "^5.0.11", "conventional-commits-parser": "^3.2.2" }, @@ -2018,13 +2019,13 @@ } }, "node_modules/@commitlint/read": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.4.2.tgz", - "integrity": "sha512-hasYOdbhEg+W4hi0InmXHxtD/1favB4WdwyFxs1eOy/DvMw6+2IZBmATgGOlqhahsypk4kChhxjAFJAZ2F+JBg==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.4.4.tgz", + "integrity": "sha512-B2TvUMJKK+Svzs6eji23WXsRJ8PAD+orI44lVuVNsm5zmI7O8RSGJMvdEZEikiA4Vohfb+HevaPoWZ7PiFZ3zA==", "dev": true, "dependencies": { "@commitlint/top-level": "^17.4.0", - "@commitlint/types": "^17.4.0", + "@commitlint/types": "^17.4.4", "fs-extra": "^11.0.0", "git-raw-commits": "^2.0.0", "minimist": "^1.2.6" @@ -2034,13 +2035,13 @@ } }, "node_modules/@commitlint/resolve-extends": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.4.0.tgz", - "integrity": "sha512-3JsmwkrCzoK8sO22AzLBvNEvC1Pmdn/65RKXzEtQMy6oYMl0Snrq97a5bQQEFETF0VsvbtUuKttLqqgn99OXRQ==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.4.4.tgz", + "integrity": "sha512-znXr1S0Rr8adInptHw0JeLgumS11lWbk5xAWFVno+HUFVN45875kUtqjrI6AppmD3JI+4s0uZlqqlkepjJd99A==", "dev": true, "dependencies": { - "@commitlint/config-validator": "^17.4.0", - "@commitlint/types": "^17.4.0", + "@commitlint/config-validator": "^17.4.4", + "@commitlint/types": "^17.4.4", "import-fresh": "^3.0.0", "lodash.mergewith": "^4.6.2", "resolve-from": "^5.0.0", @@ -2051,15 +2052,15 @@ } }, "node_modules/@commitlint/rules": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.4.2.tgz", - "integrity": "sha512-OGrPsMb9Fx3/bZ64/EzJehY9YDSGWzp81Pj+zJiY+r/NSgJI3nUYdlS37jykNIugzazdEXfMtQ10kmA+Kx2pZQ==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.4.4.tgz", + "integrity": "sha512-0tgvXnHi/mVcyR8Y8mjTFZIa/FEQXA4uEutXS/imH2v1UNkYDSEMsK/68wiXRpfW1euSgEdwRkvE1z23+yhNrQ==", "dev": true, "dependencies": { - "@commitlint/ensure": "^17.4.0", + "@commitlint/ensure": "^17.4.4", "@commitlint/message": "^17.4.2", "@commitlint/to-lines": "^17.4.0", - "@commitlint/types": "^17.4.0", + "@commitlint/types": "^17.4.4", "execa": "^5.0.0" }, "engines": { @@ -2088,9 +2089,9 @@ } }, "node_modules/@commitlint/types": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.0.tgz", - "integrity": "sha512-2NjAnq5IcxY9kXtUeO2Ac0aPpvkuOmwbH/BxIm36XXK5LtWFObWJWjXOA+kcaABMrthjWu6la+FUpyYFMHRvbA==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.4.tgz", + "integrity": "sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==", "dev": true, "dependencies": { "chalk": "^4.1.0" @@ -3473,6 +3474,18 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, + "node_modules/chromium-bidi": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.4.tgz", + "integrity": "sha512-4BX5cSaponuvVT1+SbLYTOAgDoVtX/Khoc9UsbFJ/AsPVUeFAM3RiIDFI6XFhLYMi9WmVJqh1ZH+dRpNKkKwiQ==", + "dev": true, + "dependencies": { + "mitt": "3.0.0" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, "node_modules/clean-stack": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", @@ -4306,9 +4319,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1082910", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1082910.tgz", - "integrity": "sha512-RqoZ2GmqaNxyx+99L/RemY5CkwG9D0WEfOKxekwCRXOGrDCep62ngezEJUVMq6rISYQ+085fJnWDQqGHlxVNww==", + "version": "0.0.1094867", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1094867.tgz", + "integrity": "sha512-pmMDBKiRVjh0uKK6CT1WqZmM3hBVSgD+N2MrgyV1uNizAZMw4tx6i/RTc+/uCsKSCmg0xXx7arCP/OFcIwTsiQ==", "dev": true }, "node_modules/di": { @@ -6941,9 +6954,9 @@ "dev": true }, "node_modules/lint-staged": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.1.1.tgz", - "integrity": "sha512-LLJLO0Kdbcv2a+CvSF4p1M7jBZOajKSMpBUvyR8+bXccsqPER0/NxTFQSpNHjqwV9kM3tkHczYerTB5wI+bksQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.1.2.tgz", + "integrity": "sha512-K9b4FPbWkpnupvK3WXZLbgu9pchUJ6N7TtVZjbaPsoizkqFUDkUReUL25xdrCljJs7uLUF3tZ7nVPeo/6lp+6w==", "dev": true, "dependencies": { "cli-truncate": "^3.1.0", @@ -7722,6 +7735,12 @@ "node": ">= 6" } }, + "node_modules/mitt": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", + "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==", + "dev": true + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -8659,9 +8678,9 @@ } }, "node_modules/puppeteer": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.6.3.tgz", - "integrity": "sha512-K03xTtGDwS6cBXX/EoqoZxglCUKcX2SLIl92fMnGMRjYpPGXoAV2yKEh3QXmXzKqfZXd8TxjjFww+tEttWv8kw==", + "version": "19.7.2", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.7.2.tgz", + "integrity": "sha512-4Lm7Qpe/LU95Svirei/jDLDvR5oMrl9BPGd7HMY5+Q28n+BhvKuW97gKkR+1LlI86bO8J3g8rG/Ll5kv9J1nlQ==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -8669,21 +8688,22 @@ "https-proxy-agent": "5.0.1", "progress": "2.0.3", "proxy-from-env": "1.1.0", - "puppeteer-core": "19.6.3" + "puppeteer-core": "19.7.2" }, "engines": { "node": ">=14.1.0" } }, "node_modules/puppeteer-core": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.6.3.tgz", - "integrity": "sha512-8MbhioSlkDaHkmolpQf9Z7ui7jplFfOFTnN8d5kPsCazRRTNIH6/bVxPskn0v5Gh9oqOBlknw0eHH0/OBQAxpQ==", + "version": "19.7.2", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.7.2.tgz", + "integrity": "sha512-PvI+fXqgP0uGJxkyZcX51bnzjFA73MODZOAv0fSD35yR7tvbqwtMV3/Y+hxQ0AMMwzxkEebP6c7po/muqxJvmQ==", "dev": true, "dependencies": { + "chromium-bidi": "0.4.4", "cross-fetch": "3.1.5", "debug": "4.3.4", - "devtools-protocol": "0.0.1082910", + "devtools-protocol": "0.0.1094867", "extract-zip": "2.0.1", "https-proxy-agent": "5.0.1", "proxy-from-env": "1.1.0", @@ -8694,6 +8714,14 @@ }, "engines": { "node": ">=14.1.0" + }, + "peerDependencies": { + "typescript": ">= 4.7.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/q": { @@ -8922,9 +8950,9 @@ } }, "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", + "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", "dev": true, "dependencies": { "inherits": "^2.0.3", @@ -9720,9 +9748,9 @@ "dev": true }, "node_modules/stylelint": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.1.0.tgz", - "integrity": "sha512-Tw8OyIiYhxnIHUzgoLlCyWgCUKsPYiP3TDgs7M1VbayS+q5qZly2yxABg+YPe/hFRWiu0cOtptCtpyrn1CrnYw==", + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.2.0.tgz", + "integrity": "sha512-wjg5OLn8zQwjlj5cYUgyQpMWKzct42AG5dYlqkHRJQJqsystFFn3onqEc263KH4xfEI0W3lZCnlIhFfS64uwSA==", "dev": true, "dependencies": { "@csstools/css-parser-algorithms": "^2.0.1", diff --git a/package.json b/package.json index 75417e4..83db218 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "compressorjs", - "version": "1.1.1", + "version": "1.2.0", "description": "JavaScript image compressor.", "main": "dist/compressor.common.js", "module": "dist/compressor.esm.js", @@ -48,11 +48,11 @@ "is-blob": "^2.1.0" }, "devDependencies": { - "@babel/core": "^7.20.12", + "@babel/core": "^7.21.0", "@babel/plugin-transform-object-assign": "^7.18.6", "@babel/preset-env": "^7.20.2", - "@commitlint/cli": "^17.4.2", - "@commitlint/config-conventional": "^17.4.2", + "@commitlint/cli": "^17.4.4", + "@commitlint/config-conventional": "^17.4.4", "@rollup/plugin-babel": "^5.3.1", "@rollup/plugin-commonjs": "^21.1.0", "@rollup/plugin-node-resolve": "^13.3.0", @@ -75,11 +75,11 @@ "karma-mocha": "^2.0.1", "karma-mocha-reporter": "^2.2.5", "karma-rollup-preprocessor": "^7.0.8", - "lint-staged": "^13.1.1", + "lint-staged": "^13.1.2", "mocha": "^10.2.0", - "puppeteer": "^19.6.3", + "puppeteer": "^19.7.2", "rollup": "^2.79.1", - "stylelint": "^15.1.0", + "stylelint": "^15.2.0", "stylelint-config-standard": "^30.0.1", "stylelint-order": "^6.0.2", "uglify-js": "^3.17.4"