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