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