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