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