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