compressorjs 1.1.1 → 1.2.1

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