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