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