compressorjs 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,105 +1,27 @@
1
1
  /*!
2
- * Compressor.js v1.1.1
2
+ * Compressor.js v1.2.0
3
3
  * https://fengyuanchen.github.io/compressorjs
4
4
  *
5
5
  * Copyright 2018-present Chen Fengyuan
6
6
  * Released under the MIT license
7
7
  *
8
- * Date: 2021-10-05T02:32:40.212Z
8
+ * Date: 2023-02-25T11:35:56.625Z
9
9
  */
10
10
 
11
11
  'use strict';
12
12
 
13
- function ownKeys(object, enumerableOnly) {
14
- var keys = Object.keys(object);
15
-
16
- if (Object.getOwnPropertySymbols) {
17
- var symbols = Object.getOwnPropertySymbols(object);
18
-
19
- if (enumerableOnly) {
20
- symbols = symbols.filter(function (sym) {
21
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
22
- });
23
- }
24
-
25
- keys.push.apply(keys, symbols);
26
- }
27
-
28
- return keys;
29
- }
30
-
31
- function _objectSpread2(target) {
32
- for (var i = 1; i < arguments.length; i++) {
33
- var source = arguments[i] != null ? arguments[i] : {};
34
-
35
- if (i % 2) {
36
- ownKeys(Object(source), true).forEach(function (key) {
37
- _defineProperty(target, key, source[key]);
38
- });
39
- } else if (Object.getOwnPropertyDescriptors) {
40
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
41
- } else {
42
- ownKeys(Object(source)).forEach(function (key) {
43
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
44
- });
45
- }
46
- }
47
-
48
- return target;
49
- }
50
-
51
- function _classCallCheck(instance, Constructor) {
52
- if (!(instance instanceof Constructor)) {
53
- throw new TypeError("Cannot call a class as a function");
54
- }
55
- }
56
-
57
- function _defineProperties(target, props) {
58
- for (var i = 0; i < props.length; i++) {
59
- var descriptor = props[i];
60
- descriptor.enumerable = descriptor.enumerable || false;
61
- descriptor.configurable = true;
62
- if ("value" in descriptor) descriptor.writable = true;
63
- Object.defineProperty(target, descriptor.key, descriptor);
64
- }
65
- }
66
-
67
- function _createClass(Constructor, protoProps, staticProps) {
68
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
69
- if (staticProps) _defineProperties(Constructor, staticProps);
70
- return Constructor;
71
- }
72
-
73
- function _defineProperty(obj, key, value) {
74
- if (key in obj) {
75
- Object.defineProperty(obj, key, {
76
- value: value,
77
- enumerable: true,
78
- configurable: true,
79
- writable: true
80
- });
81
- } else {
82
- obj[key] = value;
83
- }
84
-
85
- return obj;
86
- }
87
-
88
13
  function _extends() {
89
- _extends = Object.assign || function (target) {
14
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
90
15
  for (var i = 1; i < arguments.length; i++) {
91
16
  var source = arguments[i];
92
-
93
17
  for (var key in source) {
94
18
  if (Object.prototype.hasOwnProperty.call(source, key)) {
95
19
  target[key] = source[key];
96
20
  }
97
21
  }
98
22
  }
99
-
100
23
  return target;
101
24
  };
102
-
103
25
  return _extends.apply(this, arguments);
104
26
  }
105
27
 
@@ -118,16 +40,13 @@ var canvasToBlob = {exports: {}};
118
40
  * Based on stackoverflow user Stoive's code snippet:
119
41
  * http://stackoverflow.com/q/4998908
120
42
  */
121
-
122
43
  (function (module) {
123
44
  if (typeof window === 'undefined') {
124
45
  return;
125
46
  }
126
-
127
47
  (function (window) {
128
48
 
129
49
  var CanvasPrototype = window.HTMLCanvasElement && window.HTMLCanvasElement.prototype;
130
-
131
50
  var hasBlobConstructor = window.Blob && function () {
132
51
  try {
133
52
  return Boolean(new Blob());
@@ -135,7 +54,6 @@ var canvasToBlob = {exports: {}};
135
54
  return false;
136
55
  }
137
56
  }();
138
-
139
57
  var hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && function () {
140
58
  try {
141
59
  return new Blob([new Uint8Array(100)]).size === 100;
@@ -143,52 +61,42 @@ var canvasToBlob = {exports: {}};
143
61
  return false;
144
62
  }
145
63
  }();
146
-
147
64
  var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
148
65
  var dataURIPattern = /^data:((.*?)(;charset=.*?)?)(;base64)?,/;
149
-
150
66
  var dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob && window.ArrayBuffer && window.Uint8Array && function (dataURI) {
151
- var matches, mediaType, isBase64, dataString, byteString, arrayBuffer, intArray, i, bb; // Parse the dataURI components as per RFC 2397
152
-
67
+ var matches, mediaType, isBase64, dataString, byteString, arrayBuffer, intArray, i, bb;
68
+ // Parse the dataURI components as per RFC 2397
153
69
  matches = dataURI.match(dataURIPattern);
154
-
155
70
  if (!matches) {
156
71
  throw new Error('invalid data URI');
157
- } // Default to text/plain;charset=US-ASCII
158
-
159
-
72
+ }
73
+ // Default to text/plain;charset=US-ASCII
160
74
  mediaType = matches[2] ? matches[1] : 'text/plain' + (matches[3] || ';charset=US-ASCII');
161
75
  isBase64 = !!matches[4];
162
76
  dataString = dataURI.slice(matches[0].length);
163
-
164
77
  if (isBase64) {
165
78
  // Convert base64 to raw binary data held in a string:
166
79
  byteString = atob(dataString);
167
80
  } else {
168
81
  // Convert base64/URLEncoded data component to raw binary:
169
82
  byteString = decodeURIComponent(dataString);
170
- } // Write the bytes of the string to an ArrayBuffer:
171
-
172
-
83
+ }
84
+ // Write the bytes of the string to an ArrayBuffer:
173
85
  arrayBuffer = new ArrayBuffer(byteString.length);
174
86
  intArray = new Uint8Array(arrayBuffer);
175
-
176
87
  for (i = 0; i < byteString.length; i += 1) {
177
88
  intArray[i] = byteString.charCodeAt(i);
178
- } // Write the ArrayBuffer (or ArrayBufferView) to a blob:
179
-
180
-
89
+ }
90
+ // Write the ArrayBuffer (or ArrayBufferView) to a blob:
181
91
  if (hasBlobConstructor) {
182
92
  return new Blob([hasArrayBufferViewSupport ? intArray : arrayBuffer], {
183
93
  type: mediaType
184
94
  });
185
95
  }
186
-
187
96
  bb = new BlobBuilder();
188
97
  bb.append(arrayBuffer);
189
98
  return bb.getBlob(mediaType);
190
99
  };
191
-
192
100
  if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {
193
101
  if (CanvasPrototype.mozGetAsFile) {
194
102
  CanvasPrototype.toBlob = function (callback, type, quality) {
@@ -223,7 +131,6 @@ var canvasToBlob = {exports: {}};
223
131
  }
224
132
  }
225
133
  }
226
-
227
134
  if (module.exports) {
228
135
  module.exports = dataURLtoBlob;
229
136
  } else {
@@ -231,14 +138,12 @@ var canvasToBlob = {exports: {}};
231
138
  }
232
139
  })(window);
233
140
  })(canvasToBlob);
234
-
235
141
  var toBlob = canvasToBlob.exports;
236
142
 
237
- var isBlob = function isBlob(value) {
143
+ var isBlob = value => {
238
144
  if (typeof Blob === 'undefined') {
239
145
  return false;
240
146
  }
241
-
242
147
  return value instanceof Blob || Object.prototype.toString.call(value) === '[object Blob]';
243
148
  };
244
149
 
@@ -249,59 +154,55 @@ var DEFAULTS = {
249
154
  * @type {boolean}
250
155
  */
251
156
  strict: true,
252
-
253
157
  /**
254
158
  * Indicates if read the image's Exif Orientation information,
255
159
  * and then rotate or flip the image automatically.
256
160
  * @type {boolean}
257
161
  */
258
162
  checkOrientation: true,
259
-
163
+ /**
164
+ * Indicates if retain the image's Exif information after compressed.
165
+ * @type {boolean}
166
+ */
167
+ retainExif: false,
260
168
  /**
261
169
  * The max width of the output image.
262
170
  * @type {number}
263
171
  */
264
172
  maxWidth: Infinity,
265
-
266
173
  /**
267
174
  * The max height of the output image.
268
175
  * @type {number}
269
176
  */
270
177
  maxHeight: Infinity,
271
-
272
178
  /**
273
179
  * The min width of the output image.
274
180
  * @type {number}
275
181
  */
276
182
  minWidth: 0,
277
-
278
183
  /**
279
184
  * The min height of the output image.
280
185
  * @type {number}
281
186
  */
282
187
  minHeight: 0,
283
-
284
188
  /**
285
189
  * The width of the output image.
286
190
  * If not specified, the natural width of the source image will be used.
287
191
  * @type {number}
288
192
  */
289
193
  width: undefined,
290
-
291
194
  /**
292
195
  * The height of the output image.
293
196
  * If not specified, the natural height of the source image will be used.
294
197
  * @type {number}
295
198
  */
296
199
  height: undefined,
297
-
298
200
  /**
299
201
  * Sets how the size of the image should be resized to the container
300
202
  * specified by the `width` and `height` options.
301
203
  * @type {string}
302
204
  */
303
205
  resize: 'none',
304
-
305
206
  /**
306
207
  * The quality of the output image.
307
208
  * It must be a number between `0` and `1`,
@@ -310,28 +211,24 @@ var DEFAULTS = {
310
211
  * @type {number}
311
212
  */
312
213
  quality: 0.8,
313
-
314
214
  /**
315
215
  * The mime type of the output image.
316
216
  * By default, the original mime type of the source image file will be used.
317
217
  * @type {string}
318
218
  */
319
219
  mimeType: 'auto',
320
-
321
220
  /**
322
221
  * Files whose file type is included in this list,
323
222
  * and whose file size exceeds the `convertSize` value will be converted to JPEGs.
324
223
  * @type {string|Array}
325
224
  */
326
225
  convertTypes: ['image/png'],
327
-
328
226
  /**
329
227
  * PNG files over this size (5 MB by default) will be converted to JPEGs.
330
228
  * To disable this, just set the value to `Infinity`.
331
229
  * @type {number}
332
230
  */
333
231
  convertSize: 5000000,
334
-
335
232
  /**
336
233
  * The hook function to execute before draw the image into the canvas for compression.
337
234
  * @type {Function}
@@ -343,7 +240,6 @@ var DEFAULTS = {
343
240
  * }
344
241
  */
345
242
  beforeDraw: null,
346
-
347
243
  /**
348
244
  * The hook function to execute after drew the image into the canvas for compression.
349
245
  * @type {Function}
@@ -355,7 +251,6 @@ var DEFAULTS = {
355
251
  * }
356
252
  */
357
253
  drew: null,
358
-
359
254
  /**
360
255
  * The hook function to execute when success to compress the image.
361
256
  * @type {Function}
@@ -366,7 +261,6 @@ var DEFAULTS = {
366
261
  * }
367
262
  */
368
263
  success: null,
369
-
370
264
  /**
371
265
  * The hook function to execute when fail to compress the image.
372
266
  * @type {Function}
@@ -379,54 +273,54 @@ var DEFAULTS = {
379
273
  error: null
380
274
  };
381
275
 
382
- var IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined';
383
- var WINDOW = IS_BROWSER ? window : {};
276
+ const IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined';
277
+ const WINDOW = IS_BROWSER ? window : {};
384
278
 
385
279
  /**
386
280
  * Check if the given value is a positive number.
387
281
  * @param {*} value - The value to check.
388
282
  * @returns {boolean} Returns `true` if the given value is a positive number, else `false`.
389
283
  */
284
+ const isPositiveNumber = value => value > 0 && value < Infinity;
285
+ const {
286
+ slice
287
+ } = Array.prototype;
390
288
 
391
- var isPositiveNumber = function isPositiveNumber(value) {
392
- return value > 0 && value < Infinity;
393
- };
394
- var slice = Array.prototype.slice;
395
289
  /**
396
290
  * Convert array-like or iterable object to an array.
397
291
  * @param {*} value - The value to convert.
398
292
  * @returns {Array} Returns a new array.
399
293
  */
400
-
401
294
  function toArray(value) {
402
295
  return Array.from ? Array.from(value) : slice.call(value);
403
296
  }
404
- var REGEXP_IMAGE_TYPE = /^image\/.+$/;
297
+ const REGEXP_IMAGE_TYPE = /^image\/.+$/;
298
+
405
299
  /**
406
300
  * Check if the given value is a mime type of image.
407
301
  * @param {*} value - The value to check.
408
302
  * @returns {boolean} Returns `true` if the given is a mime type of image, else `false`.
409
303
  */
410
-
411
304
  function isImageType(value) {
412
305
  return REGEXP_IMAGE_TYPE.test(value);
413
306
  }
307
+
414
308
  /**
415
309
  * Convert image type to extension.
416
310
  * @param {string} value - The image type to convert.
417
311
  * @returns {boolean} Returns the image extension.
418
312
  */
419
-
420
313
  function imageTypeToExtension(value) {
421
- var extension = isImageType(value) ? value.substr(6) : '';
422
-
314
+ let extension = isImageType(value) ? value.substr(6) : '';
423
315
  if (extension === 'jpeg') {
424
316
  extension = 'jpg';
425
317
  }
426
-
427
- return ".".concat(extension);
318
+ return `.${extension}`;
428
319
  }
429
- var fromCharCode = String.fromCharCode;
320
+ const {
321
+ fromCharCode
322
+ } = String;
323
+
430
324
  /**
431
325
  * Get string from char code in data view.
432
326
  * @param {DataView} dataView - The data view for read.
@@ -434,83 +328,74 @@ var fromCharCode = String.fromCharCode;
434
328
  * @param {number} length - The read length.
435
329
  * @returns {string} The read result.
436
330
  */
437
-
438
331
  function getStringFromCharCode(dataView, start, length) {
439
- var str = '';
440
- var i;
332
+ let str = '';
333
+ let i;
441
334
  length += start;
442
-
443
335
  for (i = start; i < length; i += 1) {
444
336
  str += fromCharCode(dataView.getUint8(i));
445
337
  }
446
-
447
338
  return str;
448
339
  }
449
- var btoa = WINDOW.btoa;
340
+ const {
341
+ btoa
342
+ } = WINDOW;
343
+
450
344
  /**
451
345
  * Transform array buffer to Data URL.
452
346
  * @param {ArrayBuffer} arrayBuffer - The array buffer to transform.
453
347
  * @param {string} mimeType - The mime type of the Data URL.
454
348
  * @returns {string} The result Data URL.
455
349
  */
456
-
457
350
  function arrayBufferToDataURL(arrayBuffer, mimeType) {
458
- var chunks = [];
459
- var chunkSize = 8192;
460
- var uint8 = new Uint8Array(arrayBuffer);
461
-
351
+ const chunks = [];
352
+ const chunkSize = 8192;
353
+ let uint8 = new Uint8Array(arrayBuffer);
462
354
  while (uint8.length > 0) {
463
355
  // XXX: Babel's `toConsumableArray` helper will throw error in IE or Safari 9
464
356
  // eslint-disable-next-line prefer-spread
465
357
  chunks.push(fromCharCode.apply(null, toArray(uint8.subarray(0, chunkSize))));
466
358
  uint8 = uint8.subarray(chunkSize);
467
359
  }
468
-
469
- return "data:".concat(mimeType, ";base64,").concat(btoa(chunks.join('')));
360
+ return `data:${mimeType};base64,${btoa(chunks.join(''))}`;
470
361
  }
362
+
471
363
  /**
472
364
  * Get orientation value from given array buffer.
473
365
  * @param {ArrayBuffer} arrayBuffer - The array buffer to read.
474
366
  * @returns {number} The read orientation value.
475
367
  */
476
-
477
368
  function resetAndGetOrientation(arrayBuffer) {
478
- var dataView = new DataView(arrayBuffer);
479
- var orientation; // Ignores range error when the image does not have correct Exif information
369
+ const dataView = new DataView(arrayBuffer);
370
+ let orientation;
480
371
 
372
+ // Ignores range error when the image does not have correct Exif information
481
373
  try {
482
- var littleEndian;
483
- var app1Start;
484
- var ifdStart; // Only handle JPEG image (start by 0xFFD8)
374
+ let littleEndian;
375
+ let app1Start;
376
+ let ifdStart;
485
377
 
378
+ // Only handle JPEG image (start by 0xFFD8)
486
379
  if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
487
- var length = dataView.byteLength;
488
- var offset = 2;
489
-
380
+ const length = dataView.byteLength;
381
+ let offset = 2;
490
382
  while (offset + 1 < length) {
491
383
  if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
492
384
  app1Start = offset;
493
385
  break;
494
386
  }
495
-
496
387
  offset += 1;
497
388
  }
498
389
  }
499
-
500
390
  if (app1Start) {
501
- var exifIDCode = app1Start + 4;
502
- var tiffOffset = app1Start + 10;
503
-
391
+ const exifIDCode = app1Start + 4;
392
+ const tiffOffset = app1Start + 10;
504
393
  if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
505
- var endianness = dataView.getUint16(tiffOffset);
394
+ const endianness = dataView.getUint16(tiffOffset);
506
395
  littleEndian = endianness === 0x4949;
507
-
508
- if (littleEndian || endianness === 0x4D4D
509
- /* bigEndian */
510
- ) {
396
+ if (littleEndian || endianness === 0x4D4D /* bigEndian */) {
511
397
  if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
512
- var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
513
-
398
+ const firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
514
399
  if (firstIFDOffset >= 0x00000008) {
515
400
  ifdStart = tiffOffset + firstIFDOffset;
516
401
  }
@@ -518,26 +403,21 @@ function resetAndGetOrientation(arrayBuffer) {
518
403
  }
519
404
  }
520
405
  }
521
-
522
406
  if (ifdStart) {
523
- var _length = dataView.getUint16(ifdStart, littleEndian);
524
-
525
- var _offset;
526
-
527
- var i;
528
-
529
- for (i = 0; i < _length; i += 1) {
530
- _offset = ifdStart + i * 12 + 2;
531
-
532
- if (dataView.getUint16(_offset, littleEndian) === 0x0112
533
- /* Orientation */
534
- ) {
407
+ const length = dataView.getUint16(ifdStart, littleEndian);
408
+ let offset;
409
+ let i;
410
+ for (i = 0; i < length; i += 1) {
411
+ offset = ifdStart + i * 12 + 2;
412
+ if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) {
535
413
  // 8 is the offset of the current tag's value
536
- _offset += 8; // Get the original orientation value
414
+ offset += 8;
537
415
 
538
- orientation = dataView.getUint16(_offset, littleEndian); // Override the orientation with its default value
416
+ // Get the original orientation value
417
+ orientation = dataView.getUint16(offset, littleEndian);
539
418
 
540
- dataView.setUint16(_offset, 1, littleEndian);
419
+ // Override the orientation with its default value
420
+ dataView.setUint16(offset, 1, littleEndian);
541
421
  break;
542
422
  }
543
423
  }
@@ -545,66 +425,64 @@ function resetAndGetOrientation(arrayBuffer) {
545
425
  } catch (e) {
546
426
  orientation = 1;
547
427
  }
548
-
549
428
  return orientation;
550
429
  }
430
+
551
431
  /**
552
432
  * Parse Exif Orientation value.
553
433
  * @param {number} orientation - The orientation to parse.
554
434
  * @returns {Object} The parsed result.
555
435
  */
556
-
557
436
  function parseOrientation(orientation) {
558
- var rotate = 0;
559
- var scaleX = 1;
560
- var scaleY = 1;
561
-
437
+ let rotate = 0;
438
+ let scaleX = 1;
439
+ let scaleY = 1;
562
440
  switch (orientation) {
563
441
  // Flip horizontal
564
442
  case 2:
565
443
  scaleX = -1;
566
444
  break;
567
- // Rotate left 180°
568
445
 
446
+ // Rotate left 180°
569
447
  case 3:
570
448
  rotate = -180;
571
449
  break;
572
- // Flip vertical
573
450
 
451
+ // Flip vertical
574
452
  case 4:
575
453
  scaleY = -1;
576
454
  break;
577
- // Flip vertical and rotate right 90°
578
455
 
456
+ // Flip vertical and rotate right 90°
579
457
  case 5:
580
458
  rotate = 90;
581
459
  scaleY = -1;
582
460
  break;
583
- // Rotate right 90°
584
461
 
462
+ // Rotate right 90°
585
463
  case 6:
586
464
  rotate = 90;
587
465
  break;
588
- // Flip horizontal and rotate right 90°
589
466
 
467
+ // Flip horizontal and rotate right 90°
590
468
  case 7:
591
469
  rotate = 90;
592
470
  scaleX = -1;
593
471
  break;
594
- // Rotate left 90°
595
472
 
473
+ // Rotate left 90°
596
474
  case 8:
597
475
  rotate = -90;
598
476
  break;
599
477
  }
600
-
601
478
  return {
602
- rotate: rotate,
603
- scaleX: scaleX,
604
- scaleY: scaleY
479
+ rotate,
480
+ scaleX,
481
+ scaleY
605
482
  };
606
483
  }
607
- var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/;
484
+ const REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/;
485
+
608
486
  /**
609
487
  * Normalize decimal number.
610
488
  * Check out {@link https://0.30000000000000004.com/}
@@ -612,29 +490,28 @@ var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/;
612
490
  * @param {number} [times=100000000000] - The times for normalizing.
613
491
  * @returns {number} Returns the normalized number.
614
492
  */
615
-
616
493
  function normalizeDecimalNumber(value) {
617
- var times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000;
494
+ let times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000;
618
495
  return REGEXP_DECIMALS.test(value) ? Math.round(value * times) / times : value;
619
496
  }
497
+
620
498
  /**
621
499
  * Get the max sizes in a rectangle under the given aspect ratio.
622
500
  * @param {Object} data - The original sizes.
623
501
  * @param {string} [type='contain'] - The adjust type.
624
502
  * @returns {Object} The result sizes.
625
503
  */
626
-
627
504
  function getAdjustedSizes(_ref) {
628
- var aspectRatio = _ref.aspectRatio,
629
- height = _ref.height,
630
- width = _ref.width;
631
- var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none';
632
- var isValidWidth = isPositiveNumber(width);
633
- var isValidHeight = isPositiveNumber(height);
634
-
505
+ let {
506
+ aspectRatio,
507
+ height,
508
+ width
509
+ } = _ref;
510
+ let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'none';
511
+ const isValidWidth = isPositiveNumber(width);
512
+ const isValidHeight = isPositiveNumber(height);
635
513
  if (isValidWidth && isValidHeight) {
636
- var adjustedWidth = height * aspectRatio;
637
-
514
+ const adjustedWidth = height * aspectRatio;
638
515
  if ((type === 'contain' || type === 'none') && adjustedWidth > width || type === 'cover' && adjustedWidth < width) {
639
516
  height = width / aspectRatio;
640
517
  } else {
@@ -645,429 +522,467 @@ function getAdjustedSizes(_ref) {
645
522
  } else if (isValidHeight) {
646
523
  width = height * aspectRatio;
647
524
  }
648
-
649
525
  return {
650
- width: width,
651
- height: height
526
+ width,
527
+ height
652
528
  };
653
529
  }
654
530
 
655
- var ArrayBuffer$1 = WINDOW.ArrayBuffer,
656
- FileReader = WINDOW.FileReader;
657
- var URL = WINDOW.URL || WINDOW.webkitURL;
658
- var REGEXP_EXTENSION = /\.\w+$/;
659
- var AnotherCompressor = WINDOW.Compressor;
531
+ /**
532
+ * Get Exif information from the given array buffer.
533
+ * @param {ArrayBuffer} arrayBuffer - The array buffer to read.
534
+ * @returns {Array} The read Exif information.
535
+ */
536
+ function getExif(arrayBuffer) {
537
+ const array = toArray(new Uint8Array(arrayBuffer));
538
+ const {
539
+ length
540
+ } = array;
541
+ const segments = [];
542
+ let start = 0;
543
+ while (start + 3 < length) {
544
+ const value = array[start];
545
+ const next = array[start + 1];
546
+
547
+ // SOS (Start of Scan)
548
+ if (value === 0xFF && next === 0xDA) {
549
+ break;
550
+ }
551
+
552
+ // SOI (Start of Image)
553
+ if (value === 0xFF && next === 0xD8) {
554
+ start += 2;
555
+ } else {
556
+ const offset = array[start + 2] * 256 + array[start + 3];
557
+ const end = start + offset + 2;
558
+ const segment = array.slice(start, end);
559
+ segments.push(segment);
560
+ start = end;
561
+ }
562
+ }
563
+ return segments.reduce((exifArray, current) => {
564
+ if (current[0] === 0xFF && current[1] === 0xE1) {
565
+ return exifArray.concat(current);
566
+ }
567
+ return exifArray;
568
+ }, []);
569
+ }
570
+
571
+ /**
572
+ * Insert Exif information into the given array buffer.
573
+ * @param {ArrayBuffer} arrayBuffer - The array buffer to transform.
574
+ * @param {Array} exifArray - The Exif information to insert.
575
+ * @returns {ArrayBuffer} The transformed array buffer.
576
+ */
577
+ function insertExif(arrayBuffer, exifArray) {
578
+ const array = toArray(new Uint8Array(arrayBuffer));
579
+ if (array[2] !== 0xFF || array[3] !== 0xE0) {
580
+ return arrayBuffer;
581
+ }
582
+ const app0Length = array[4] * 256 + array[5];
583
+ const newArrayBuffer = [0xFF, 0xD8].concat(exifArray, array.slice(4 + app0Length));
584
+ return new Uint8Array(newArrayBuffer);
585
+ }
586
+
587
+ const {
588
+ ArrayBuffer: ArrayBuffer$1,
589
+ FileReader
590
+ } = WINDOW;
591
+ const URL = WINDOW.URL || WINDOW.webkitURL;
592
+ const REGEXP_EXTENSION = /\.\w+$/;
593
+ const AnotherCompressor = WINDOW.Compressor;
594
+
660
595
  /**
661
596
  * Creates a new image compressor.
662
597
  * @class
663
598
  */
664
-
665
- var Compressor = /*#__PURE__*/function () {
599
+ class Compressor {
666
600
  /**
667
601
  * The constructor of Compressor.
668
602
  * @param {File|Blob} file - The target image file for compressing.
669
603
  * @param {Object} [options] - The options for compressing.
670
604
  */
671
- function Compressor(file, options) {
672
- _classCallCheck(this, Compressor);
673
-
605
+ constructor(file, options) {
674
606
  this.file = file;
607
+ this.exif = [];
675
608
  this.image = new Image();
676
- this.options = _objectSpread2(_objectSpread2({}, DEFAULTS), options);
609
+ this.options = {
610
+ ...DEFAULTS,
611
+ ...options
612
+ };
677
613
  this.aborted = false;
678
614
  this.result = null;
679
615
  this.init();
680
616
  }
617
+ init() {
618
+ const {
619
+ file,
620
+ options
621
+ } = this;
622
+ if (!isBlob(file)) {
623
+ this.fail(new Error('The first argument must be a File or Blob object.'));
624
+ return;
625
+ }
626
+ const mimeType = file.type;
627
+ if (!isImageType(mimeType)) {
628
+ this.fail(new Error('The first argument must be an image File or Blob object.'));
629
+ return;
630
+ }
631
+ if (!URL || !FileReader) {
632
+ this.fail(new Error('The current browser does not support image compression.'));
633
+ return;
634
+ }
635
+ if (!ArrayBuffer$1) {
636
+ options.checkOrientation = false;
637
+ options.retainExif = false;
638
+ }
639
+ const isJPEGImage = mimeType === 'image/jpeg';
640
+ const checkOrientation = isJPEGImage && options.checkOrientation;
641
+ const retainExif = isJPEGImage && options.retainExif;
642
+ if (URL && !checkOrientation && !retainExif) {
643
+ this.load({
644
+ url: URL.createObjectURL(file)
645
+ });
646
+ } else {
647
+ const reader = new FileReader();
648
+ this.reader = reader;
649
+ reader.onload = _ref => {
650
+ let {
651
+ target
652
+ } = _ref;
653
+ const {
654
+ result
655
+ } = target;
656
+ const data = {};
657
+ let orientation = 1;
658
+ if (checkOrientation) {
659
+ // Reset the orientation value to its default value 1
660
+ // as some iOS browsers will render image with its orientation
661
+ orientation = resetAndGetOrientation(result);
662
+ if (orientation > 1) {
663
+ _extends(data, parseOrientation(orientation));
664
+ }
665
+ }
666
+ if (retainExif) {
667
+ this.exif = getExif(result);
668
+ }
669
+ if (checkOrientation || retainExif) {
670
+ if (!URL
681
671
 
682
- _createClass(Compressor, [{
683
- key: "init",
684
- value: function init() {
685
- var _this = this;
686
-
687
- var file = this.file,
688
- options = this.options;
689
-
690
- if (!isBlob(file)) {
691
- this.fail(new Error('The first argument must be a File or Blob object.'));
692
- return;
693
- }
694
-
695
- var mimeType = file.type;
696
-
697
- if (!isImageType(mimeType)) {
698
- this.fail(new Error('The first argument must be an image File or Blob object.'));
699
- return;
700
- }
701
-
702
- if (!URL || !FileReader) {
703
- this.fail(new Error('The current browser does not support image compression.'));
704
- return;
705
- }
706
-
707
- if (!ArrayBuffer$1) {
708
- options.checkOrientation = false;
709
- }
710
-
711
- if (URL && !options.checkOrientation) {
712
- this.load({
713
- url: URL.createObjectURL(file)
714
- });
715
- } else {
716
- var reader = new FileReader();
717
- var checkOrientation = options.checkOrientation && mimeType === 'image/jpeg';
718
- this.reader = reader;
719
-
720
- reader.onload = function (_ref) {
721
- var target = _ref.target;
722
- var result = target.result;
723
- var data = {};
724
-
725
- if (checkOrientation) {
726
- // Reset the orientation value to its default value 1
727
- // as some iOS browsers will render image with its orientation
728
- var orientation = resetAndGetOrientation(result);
729
-
730
- if (orientation > 1 || !URL) {
731
- // Generate a new URL which has the default orientation value
732
- data.url = arrayBufferToDataURL(result, mimeType);
733
-
734
- if (orientation > 1) {
735
- _extends(data, parseOrientation(orientation));
736
- }
737
- } else {
738
- data.url = URL.createObjectURL(file);
739
- }
672
+ // Generate a new URL with the default orientation value 1.
673
+ || orientation > 1) {
674
+ data.url = arrayBufferToDataURL(result, mimeType);
740
675
  } else {
741
- data.url = result;
676
+ data.url = URL.createObjectURL(file);
742
677
  }
743
-
744
- _this.load(data);
745
- };
746
-
747
- reader.onabort = function () {
748
- _this.fail(new Error('Aborted to read the image with FileReader.'));
749
- };
750
-
751
- reader.onerror = function () {
752
- _this.fail(new Error('Failed to read the image with FileReader.'));
753
- };
754
-
755
- reader.onloadend = function () {
756
- _this.reader = null;
757
- };
758
-
759
- if (checkOrientation) {
760
- reader.readAsArrayBuffer(file);
761
678
  } else {
762
- reader.readAsDataURL(file);
679
+ data.url = result;
763
680
  }
764
- }
765
- }
766
- }, {
767
- key: "load",
768
- value: function load(data) {
769
- var _this2 = this;
770
-
771
- var file = this.file,
772
- image = this.image;
773
-
774
- image.onload = function () {
775
- _this2.draw(_objectSpread2(_objectSpread2({}, data), {}, {
776
- naturalWidth: image.naturalWidth,
777
- naturalHeight: image.naturalHeight
778
- }));
681
+ this.load(data);
779
682
  };
780
-
781
- image.onabort = function () {
782
- _this2.fail(new Error('Aborted to load the image.'));
683
+ reader.onabort = () => {
684
+ this.fail(new Error('Aborted to read the image with FileReader.'));
783
685
  };
784
-
785
- image.onerror = function () {
786
- _this2.fail(new Error('Failed to load the image.'));
787
- }; // Match all browsers that use WebKit as the layout engine in iOS devices,
788
- // such as Safari for iOS, Chrome for iOS, and in-app browsers.
789
-
790
-
791
- if (WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent)) {
792
- // Fix the `The operation is insecure` error (#57)
793
- image.crossOrigin = 'anonymous';
794
- }
795
-
796
- image.alt = file.name;
797
- image.src = data.url;
798
- }
799
- }, {
800
- key: "draw",
801
- value: function draw(_ref2) {
802
- var _this3 = this;
803
-
804
- var naturalWidth = _ref2.naturalWidth,
805
- naturalHeight = _ref2.naturalHeight,
806
- _ref2$rotate = _ref2.rotate,
807
- rotate = _ref2$rotate === void 0 ? 0 : _ref2$rotate,
808
- _ref2$scaleX = _ref2.scaleX,
809
- scaleX = _ref2$scaleX === void 0 ? 1 : _ref2$scaleX,
810
- _ref2$scaleY = _ref2.scaleY,
811
- scaleY = _ref2$scaleY === void 0 ? 1 : _ref2$scaleY;
812
- var file = this.file,
813
- image = this.image,
814
- options = this.options;
815
- var canvas = document.createElement('canvas');
816
- var context = canvas.getContext('2d');
817
- var is90DegreesRotated = Math.abs(rotate) % 180 === 90;
818
- var resizable = (options.resize === 'contain' || options.resize === 'cover') && isPositiveNumber(options.width) && isPositiveNumber(options.height);
819
- var maxWidth = Math.max(options.maxWidth, 0) || Infinity;
820
- var maxHeight = Math.max(options.maxHeight, 0) || Infinity;
821
- var minWidth = Math.max(options.minWidth, 0) || 0;
822
- var minHeight = Math.max(options.minHeight, 0) || 0;
823
- var aspectRatio = naturalWidth / naturalHeight;
824
- var width = options.width,
825
- height = options.height;
826
-
827
- if (is90DegreesRotated) {
828
- var _ref3 = [maxHeight, maxWidth];
829
- maxWidth = _ref3[0];
830
- maxHeight = _ref3[1];
831
- var _ref4 = [minHeight, minWidth];
832
- minWidth = _ref4[0];
833
- minHeight = _ref4[1];
834
- var _ref5 = [height, width];
835
- width = _ref5[0];
836
- height = _ref5[1];
837
- }
838
-
839
- if (resizable) {
840
- aspectRatio = width / height;
841
- }
842
-
843
- var _getAdjustedSizes = getAdjustedSizes({
844
- aspectRatio: aspectRatio,
845
- width: maxWidth,
846
- height: maxHeight
847
- }, 'contain');
848
-
849
- maxWidth = _getAdjustedSizes.width;
850
- maxHeight = _getAdjustedSizes.height;
851
-
852
- var _getAdjustedSizes2 = getAdjustedSizes({
853
- aspectRatio: aspectRatio,
854
- width: minWidth,
855
- height: minHeight
856
- }, 'cover');
857
-
858
- minWidth = _getAdjustedSizes2.width;
859
- minHeight = _getAdjustedSizes2.height;
860
-
861
- if (resizable) {
862
- var _getAdjustedSizes3 = getAdjustedSizes({
863
- aspectRatio: aspectRatio,
864
- width: width,
865
- height: height
866
- }, options.resize);
867
-
868
- width = _getAdjustedSizes3.width;
869
- height = _getAdjustedSizes3.height;
870
- } else {
871
- var _getAdjustedSizes4 = getAdjustedSizes({
872
- aspectRatio: aspectRatio,
873
- width: width,
874
- height: height
875
- });
876
-
877
- var _getAdjustedSizes4$wi = _getAdjustedSizes4.width;
878
- width = _getAdjustedSizes4$wi === void 0 ? naturalWidth : _getAdjustedSizes4$wi;
879
- var _getAdjustedSizes4$he = _getAdjustedSizes4.height;
880
- height = _getAdjustedSizes4$he === void 0 ? naturalHeight : _getAdjustedSizes4$he;
881
- }
882
-
883
- width = Math.floor(normalizeDecimalNumber(Math.min(Math.max(width, minWidth), maxWidth)));
884
- height = Math.floor(normalizeDecimalNumber(Math.min(Math.max(height, minHeight), maxHeight)));
885
- var destX = -width / 2;
886
- var destY = -height / 2;
887
- var destWidth = width;
888
- var destHeight = height;
889
- var params = [];
890
-
891
- if (resizable) {
892
- var srcX = 0;
893
- var srcY = 0;
894
- var srcWidth = naturalWidth;
895
- var srcHeight = naturalHeight;
896
-
897
- var _getAdjustedSizes5 = getAdjustedSizes({
898
- aspectRatio: aspectRatio,
899
- width: naturalWidth,
900
- height: naturalHeight
901
- }, {
902
- contain: 'cover',
903
- cover: 'contain'
904
- }[options.resize]);
905
-
906
- srcWidth = _getAdjustedSizes5.width;
907
- srcHeight = _getAdjustedSizes5.height;
908
- srcX = (naturalWidth - srcWidth) / 2;
909
- srcY = (naturalHeight - srcHeight) / 2;
910
- params.push(srcX, srcY, srcWidth, srcHeight);
911
- }
912
-
913
- params.push(destX, destY, destWidth, destHeight);
914
-
915
- if (is90DegreesRotated) {
916
- var _ref6 = [height, width];
917
- width = _ref6[0];
918
- height = _ref6[1];
919
- }
920
-
921
- canvas.width = width;
922
- canvas.height = height;
923
-
924
- if (!isImageType(options.mimeType)) {
925
- options.mimeType = file.type;
926
- }
927
-
928
- var fillStyle = 'transparent'; // Converts PNG files over the `convertSize` to JPEGs.
929
-
930
- if (file.size > options.convertSize && options.convertTypes.indexOf(options.mimeType) >= 0) {
931
- options.mimeType = 'image/jpeg';
932
- }
933
-
934
- if (options.mimeType === 'image/jpeg') {
935
- fillStyle = '#fff';
936
- } // Override the default fill color (#000, black)
937
-
938
-
939
- context.fillStyle = fillStyle;
940
- context.fillRect(0, 0, width, height);
941
-
942
- if (options.beforeDraw) {
943
- options.beforeDraw.call(this, context, canvas);
944
- }
945
-
946
- if (this.aborted) {
947
- return;
948
- }
949
-
950
- context.save();
951
- context.translate(width / 2, height / 2);
952
- context.rotate(rotate * Math.PI / 180);
953
- context.scale(scaleX, scaleY);
954
- context.drawImage.apply(context, [image].concat(params));
955
- context.restore();
956
-
957
- if (options.drew) {
958
- options.drew.call(this, context, canvas);
959
- }
960
-
961
- if (this.aborted) {
962
- return;
963
- }
964
-
965
- var done = function done(result) {
966
- if (!_this3.aborted) {
967
- _this3.done({
968
- naturalWidth: naturalWidth,
969
- naturalHeight: naturalHeight,
970
- result: result
971
- });
972
- }
686
+ reader.onerror = () => {
687
+ this.fail(new Error('Failed to read the image with FileReader.'));
973
688
  };
974
-
975
- if (canvas.toBlob) {
976
- canvas.toBlob(done, options.mimeType, options.quality);
689
+ reader.onloadend = () => {
690
+ this.reader = null;
691
+ };
692
+ if (checkOrientation || retainExif) {
693
+ reader.readAsArrayBuffer(file);
977
694
  } else {
978
- done(toBlob(canvas.toDataURL(options.mimeType, options.quality)));
695
+ reader.readAsDataURL(file);
979
696
  }
980
697
  }
981
- }, {
982
- key: "done",
983
- value: function done(_ref7) {
984
- var naturalWidth = _ref7.naturalWidth,
985
- naturalHeight = _ref7.naturalHeight,
986
- result = _ref7.result;
987
- var file = this.file,
988
- image = this.image,
989
- options = this.options;
698
+ }
699
+ load(data) {
700
+ const {
701
+ file,
702
+ image
703
+ } = this;
704
+ image.onload = () => {
705
+ this.draw({
706
+ ...data,
707
+ naturalWidth: image.naturalWidth,
708
+ naturalHeight: image.naturalHeight
709
+ });
710
+ };
711
+ image.onabort = () => {
712
+ this.fail(new Error('Aborted to load the image.'));
713
+ };
714
+ image.onerror = () => {
715
+ this.fail(new Error('Failed to load the image.'));
716
+ };
990
717
 
991
- if (URL && !options.checkOrientation) {
992
- URL.revokeObjectURL(image.src);
993
- }
718
+ // Match all browsers that use WebKit as the layout engine in iOS devices,
719
+ // such as Safari for iOS, Chrome for iOS, and in-app browsers.
720
+ if (WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent)) {
721
+ // Fix the `The operation is insecure` error (#57)
722
+ image.crossOrigin = 'anonymous';
723
+ }
724
+ image.alt = file.name;
725
+ image.src = data.url;
726
+ }
727
+ draw(_ref2) {
728
+ let {
729
+ naturalWidth,
730
+ naturalHeight,
731
+ rotate = 0,
732
+ scaleX = 1,
733
+ scaleY = 1
734
+ } = _ref2;
735
+ const {
736
+ file,
737
+ image,
738
+ options
739
+ } = this;
740
+ const canvas = document.createElement('canvas');
741
+ const context = canvas.getContext('2d');
742
+ const is90DegreesRotated = Math.abs(rotate) % 180 === 90;
743
+ const resizable = (options.resize === 'contain' || options.resize === 'cover') && isPositiveNumber(options.width) && isPositiveNumber(options.height);
744
+ let maxWidth = Math.max(options.maxWidth, 0) || Infinity;
745
+ let maxHeight = Math.max(options.maxHeight, 0) || Infinity;
746
+ let minWidth = Math.max(options.minWidth, 0) || 0;
747
+ let minHeight = Math.max(options.minHeight, 0) || 0;
748
+ let aspectRatio = naturalWidth / naturalHeight;
749
+ let {
750
+ width,
751
+ height
752
+ } = options;
753
+ if (is90DegreesRotated) {
754
+ [maxWidth, maxHeight] = [maxHeight, maxWidth];
755
+ [minWidth, minHeight] = [minHeight, minWidth];
756
+ [width, height] = [height, width];
757
+ }
758
+ if (resizable) {
759
+ aspectRatio = width / height;
760
+ }
761
+ ({
762
+ width: maxWidth,
763
+ height: maxHeight
764
+ } = getAdjustedSizes({
765
+ aspectRatio,
766
+ width: maxWidth,
767
+ height: maxHeight
768
+ }, 'contain'));
769
+ ({
770
+ width: minWidth,
771
+ height: minHeight
772
+ } = getAdjustedSizes({
773
+ aspectRatio,
774
+ width: minWidth,
775
+ height: minHeight
776
+ }, 'cover'));
777
+ if (resizable) {
778
+ ({
779
+ width,
780
+ height
781
+ } = getAdjustedSizes({
782
+ aspectRatio,
783
+ width,
784
+ height
785
+ }, options.resize));
786
+ } else {
787
+ ({
788
+ width = naturalWidth,
789
+ height = naturalHeight
790
+ } = getAdjustedSizes({
791
+ aspectRatio,
792
+ width,
793
+ height
794
+ }));
795
+ }
796
+ width = Math.floor(normalizeDecimalNumber(Math.min(Math.max(width, minWidth), maxWidth)));
797
+ height = Math.floor(normalizeDecimalNumber(Math.min(Math.max(height, minHeight), maxHeight)));
798
+ const destX = -width / 2;
799
+ const destY = -height / 2;
800
+ const destWidth = width;
801
+ const destHeight = height;
802
+ const params = [];
803
+ if (resizable) {
804
+ let srcX = 0;
805
+ let srcY = 0;
806
+ let srcWidth = naturalWidth;
807
+ let srcHeight = naturalHeight;
808
+ ({
809
+ width: srcWidth,
810
+ height: srcHeight
811
+ } = getAdjustedSizes({
812
+ aspectRatio,
813
+ width: naturalWidth,
814
+ height: naturalHeight
815
+ }, {
816
+ contain: 'cover',
817
+ cover: 'contain'
818
+ }[options.resize]));
819
+ srcX = (naturalWidth - srcWidth) / 2;
820
+ srcY = (naturalHeight - srcHeight) / 2;
821
+ params.push(srcX, srcY, srcWidth, srcHeight);
822
+ }
823
+ params.push(destX, destY, destWidth, destHeight);
824
+ if (is90DegreesRotated) {
825
+ [width, height] = [height, width];
826
+ }
827
+ canvas.width = width;
828
+ canvas.height = height;
829
+ if (!isImageType(options.mimeType)) {
830
+ options.mimeType = file.type;
831
+ }
832
+ let fillStyle = 'transparent';
994
833
 
995
- if (result) {
996
- // Returns original file if the result is greater than it and without size related options
997
- 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)) {
998
- result = file;
999
- } else {
1000
- var date = new Date();
1001
- result.lastModified = date.getTime();
1002
- result.lastModifiedDate = date;
1003
- result.name = file.name; // Convert the extension to match its type
834
+ // Converts PNG files over the `convertSize` to JPEGs.
835
+ if (file.size > options.convertSize && options.convertTypes.indexOf(options.mimeType) >= 0) {
836
+ options.mimeType = 'image/jpeg';
837
+ }
838
+ const isJPEGImage = options.mimeType === 'image/jpeg';
839
+ if (isJPEGImage) {
840
+ fillStyle = '#fff';
841
+ }
1004
842
 
1005
- if (result.name && result.type !== file.type) {
1006
- result.name = result.name.replace(REGEXP_EXTENSION, imageTypeToExtension(result.type));
843
+ // Override the default fill color (#000, black)
844
+ context.fillStyle = fillStyle;
845
+ context.fillRect(0, 0, width, height);
846
+ if (options.beforeDraw) {
847
+ options.beforeDraw.call(this, context, canvas);
848
+ }
849
+ if (this.aborted) {
850
+ return;
851
+ }
852
+ context.save();
853
+ context.translate(width / 2, height / 2);
854
+ context.rotate(rotate * Math.PI / 180);
855
+ context.scale(scaleX, scaleY);
856
+ context.drawImage(image, ...params);
857
+ context.restore();
858
+ if (options.drew) {
859
+ options.drew.call(this, context, canvas);
860
+ }
861
+ if (this.aborted) {
862
+ return;
863
+ }
864
+ const callback = blob => {
865
+ if (!this.aborted) {
866
+ const done = result => this.done({
867
+ naturalWidth,
868
+ naturalHeight,
869
+ result
870
+ });
871
+ if (blob && isJPEGImage && options.retainExif && this.exif && this.exif.length > 0) {
872
+ const next = arrayBuffer => done(toBlob(arrayBufferToDataURL(insertExif(arrayBuffer, this.exif), options.mimeType)));
873
+ if (blob.arrayBuffer) {
874
+ blob.arrayBuffer().then(next).catch(() => {
875
+ this.fail(new Error('Failed to read the compressed image with Blob.arrayBuffer().'));
876
+ });
877
+ } else {
878
+ const reader = new FileReader();
879
+ this.reader = reader;
880
+ reader.onload = _ref3 => {
881
+ let {
882
+ target
883
+ } = _ref3;
884
+ next(target.result);
885
+ };
886
+ reader.onabort = () => {
887
+ this.fail(new Error('Aborted to read the compressed image with FileReader.'));
888
+ };
889
+ reader.onerror = () => {
890
+ this.fail(new Error('Failed to read the compressed image with FileReader.'));
891
+ };
892
+ reader.onloadend = () => {
893
+ this.reader = null;
894
+ };
895
+ reader.readAsArrayBuffer(blob);
1007
896
  }
897
+ } else {
898
+ done(blob);
1008
899
  }
1009
- } else {
1010
- // Returns original file if the result is null in some cases.
1011
- result = file;
1012
- }
1013
-
1014
- this.result = result;
1015
-
1016
- if (options.success) {
1017
- options.success.call(this, result);
1018
900
  }
901
+ };
902
+ if (canvas.toBlob) {
903
+ canvas.toBlob(callback, options.mimeType, options.quality);
904
+ } else {
905
+ callback(toBlob(canvas.toDataURL(options.mimeType, options.quality)));
1019
906
  }
1020
- }, {
1021
- key: "fail",
1022
- value: function fail(err) {
1023
- var options = this.options;
1024
-
1025
- if (options.error) {
1026
- options.error.call(this, err);
1027
- } else {
1028
- throw err;
1029
- }
907
+ }
908
+ done(_ref4) {
909
+ let {
910
+ naturalWidth,
911
+ naturalHeight,
912
+ result
913
+ } = _ref4;
914
+ const {
915
+ file,
916
+ image,
917
+ options
918
+ } = this;
919
+ if (URL && image.src.indexOf('blob:') === 0) {
920
+ URL.revokeObjectURL(image.src);
1030
921
  }
1031
- }, {
1032
- key: "abort",
1033
- value: function abort() {
1034
- if (!this.aborted) {
1035
- this.aborted = true;
1036
-
1037
- if (this.reader) {
1038
- this.reader.abort();
1039
- } else if (!this.image.complete) {
1040
- this.image.onload = null;
1041
- this.image.onabort();
1042
- } else {
1043
- this.fail(new Error('The compression process has been aborted.'));
922
+ if (result) {
923
+ // Returns original file if the result is greater than it and without size related options
924
+ 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)) {
925
+ result = file;
926
+ } else {
927
+ const date = new Date();
928
+ result.lastModified = date.getTime();
929
+ result.lastModifiedDate = date;
930
+ result.name = file.name;
931
+
932
+ // Convert the extension to match its type
933
+ if (result.name && result.type !== file.type) {
934
+ result.name = result.name.replace(REGEXP_EXTENSION, imageTypeToExtension(result.type));
1044
935
  }
1045
936
  }
937
+ } else {
938
+ // Returns original file if the result is null in some cases.
939
+ result = file;
1046
940
  }
1047
- /**
1048
- * Get the no conflict compressor class.
1049
- * @returns {Compressor} The compressor class.
1050
- */
1051
-
1052
- }], [{
1053
- key: "noConflict",
1054
- value: function noConflict() {
1055
- window.Compressor = AnotherCompressor;
1056
- return Compressor;
941
+ this.result = result;
942
+ if (options.success) {
943
+ options.success.call(this, result);
1057
944
  }
1058
- /**
1059
- * Change the default options.
1060
- * @param {Object} options - The new default options.
1061
- */
1062
-
1063
- }, {
1064
- key: "setDefaults",
1065
- value: function setDefaults(options) {
1066
- _extends(DEFAULTS, options);
945
+ }
946
+ fail(err) {
947
+ const {
948
+ options
949
+ } = this;
950
+ if (options.error) {
951
+ options.error.call(this, err);
952
+ } else {
953
+ throw err;
954
+ }
955
+ }
956
+ abort() {
957
+ if (!this.aborted) {
958
+ this.aborted = true;
959
+ if (this.reader) {
960
+ this.reader.abort();
961
+ } else if (!this.image.complete) {
962
+ this.image.onload = null;
963
+ this.image.onabort();
964
+ } else {
965
+ this.fail(new Error('The compression process has been aborted.'));
966
+ }
1067
967
  }
1068
- }]);
968
+ }
969
+
970
+ /**
971
+ * Get the no conflict compressor class.
972
+ * @returns {Compressor} The compressor class.
973
+ */
974
+ static noConflict() {
975
+ window.Compressor = AnotherCompressor;
976
+ return Compressor;
977
+ }
1069
978
 
1070
- return Compressor;
1071
- }();
979
+ /**
980
+ * Change the default options.
981
+ * @param {Object} options - The new default options.
982
+ */
983
+ static setDefaults(options) {
984
+ _extends(DEFAULTS, options);
985
+ }
986
+ }
1072
987
 
1073
988
  module.exports = Compressor;