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