pica 7.0.0 → 9.0.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 +15 -16
- package/dist/pica.js +475 -230
- package/dist/pica.min.js +2 -2
- package/index.js +86 -40
- package/lib/mathlib.js +2 -2
- package/lib/mm_resize/convolve.c +193 -17
- package/lib/mm_resize/convolve.js +160 -33
- package/lib/mm_resize/convolve.wasm +0 -0
- package/lib/mm_resize/convolve_wasm_base64.js +1 -1
- package/lib/mm_resize/resize.js +25 -21
- package/lib/mm_resize/resize_filter_gen.js +3 -3
- package/lib/mm_resize/resize_filter_info.js +44 -17
- package/lib/mm_resize/resize_wasm.js +24 -14
- package/lib/utils.js +79 -1
- package/lib/worker.js +5 -3
- package/package.json +7 -8
- package/CHANGELOG.md +0 -334
package/dist/pica.js
CHANGED
|
@@ -13,8 +13,6 @@ https://github.com/nodeca/pica
|
|
|
13
13
|
//
|
|
14
14
|
'use strict';
|
|
15
15
|
|
|
16
|
-
var inherits = _dereq_('inherits');
|
|
17
|
-
|
|
18
16
|
var Multimath = _dereq_('multimath');
|
|
19
17
|
|
|
20
18
|
var mm_unsharp_mask = _dereq_('./mm_unsharp_mask');
|
|
@@ -37,7 +35,8 @@ function MathLib(requested_features) {
|
|
|
37
35
|
this.use(mm_resize);
|
|
38
36
|
}
|
|
39
37
|
|
|
40
|
-
|
|
38
|
+
MathLib.prototype = Object.create(Multimath.prototype);
|
|
39
|
+
MathLib.prototype.constructor = MathLib;
|
|
41
40
|
|
|
42
41
|
MathLib.prototype.resizeAndUnsharp = function resizeAndUnsharp(options, cache) {
|
|
43
42
|
var result = this.resize(options, cache);
|
|
@@ -51,7 +50,7 @@ MathLib.prototype.resizeAndUnsharp = function resizeAndUnsharp(options, cache) {
|
|
|
51
50
|
|
|
52
51
|
module.exports = MathLib;
|
|
53
52
|
|
|
54
|
-
},{"./mm_resize":4,"./mm_unsharp_mask":9,"
|
|
53
|
+
},{"./mm_resize":4,"./mm_unsharp_mask":9,"multimath":19}],2:[function(_dereq_,module,exports){
|
|
55
54
|
// Resize convolvers, pure JS implementation
|
|
56
55
|
//
|
|
57
56
|
'use strict'; // Precision of fixed FP values
|
|
@@ -59,18 +58,23 @@ module.exports = MathLib;
|
|
|
59
58
|
|
|
60
59
|
function clampTo8(i) {
|
|
61
60
|
return i < 0 ? 0 : i > 255 ? 255 : i;
|
|
62
|
-
}
|
|
63
|
-
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function clampNegative(i) {
|
|
64
|
+
return i >= 0 ? i : 0;
|
|
65
|
+
} // Convolve image data in horizontal direction. Can be used for:
|
|
66
|
+
//
|
|
67
|
+
// 1. bitmap with premultiplied alpha
|
|
68
|
+
// 2. bitmap without alpha (all values 255)
|
|
64
69
|
//
|
|
65
|
-
//
|
|
66
|
-
// types of input array and temporary buffer)
|
|
67
|
-
// - making vertical pass by horisonltal lines inprove CPU cache use.
|
|
70
|
+
// Notes:
|
|
68
71
|
//
|
|
69
|
-
//
|
|
72
|
+
// - output is transposed
|
|
73
|
+
// - output resolution is ~15 bits per channel(for better precision).
|
|
70
74
|
//
|
|
71
75
|
|
|
72
76
|
|
|
73
|
-
function
|
|
77
|
+
function convolveHor(src, dest, srcW, srcH, destW, filters) {
|
|
74
78
|
var r, g, b, a;
|
|
75
79
|
var filterPtr, filterShift, filterSize;
|
|
76
80
|
var srcPtr, srcY, destX, filterVal;
|
|
@@ -96,39 +100,26 @@ function convolveHorizontally(src, dest, srcW, srcH, destW, filters) {
|
|
|
96
100
|
g = g + filterVal * src[srcPtr + 1] | 0;
|
|
97
101
|
r = r + filterVal * src[srcPtr] | 0;
|
|
98
102
|
srcPtr = srcPtr + 4 | 0;
|
|
99
|
-
} //
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
// (!) Add 1/2 of value before clamping to get proper rounding. In other
|
|
103
|
-
// case brightness loss will be noticeable if you resize image with white
|
|
104
|
-
// border and place it on white background.
|
|
103
|
+
} // Store 15 bits between passes for better precision
|
|
104
|
+
// Instead of shift to 14 (FIXED_FRAC_BITS), shift to 7 only
|
|
105
105
|
//
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
dest[destOffset + 3] =
|
|
109
|
-
|
|
110
|
-
);
|
|
111
|
-
dest[destOffset
|
|
112
|
-
/*FIXED_FRAC_BITS*/
|
|
113
|
-
);
|
|
114
|
-
dest[destOffset + 1] = clampTo8(g + (1 << 13) >> 14
|
|
115
|
-
/*FIXED_FRAC_BITS*/
|
|
116
|
-
);
|
|
117
|
-
dest[destOffset] = clampTo8(r + (1 << 13) >> 14
|
|
118
|
-
/*FIXED_FRAC_BITS*/
|
|
119
|
-
);
|
|
108
|
+
dest[destOffset + 3] = clampNegative(a >> 7);
|
|
109
|
+
dest[destOffset + 2] = clampNegative(b >> 7);
|
|
110
|
+
dest[destOffset + 1] = clampNegative(g >> 7);
|
|
111
|
+
dest[destOffset] = clampNegative(r >> 7);
|
|
120
112
|
destOffset = destOffset + srcH * 4 | 0;
|
|
121
113
|
}
|
|
122
114
|
|
|
123
115
|
destOffset = (srcY + 1) * 4 | 0;
|
|
124
116
|
srcOffset = (srcY + 1) * srcW * 4 | 0;
|
|
125
117
|
}
|
|
126
|
-
} //
|
|
127
|
-
//
|
|
128
|
-
// keep code in separate functions to avoid deoptimizations & speed loss.
|
|
118
|
+
} // Supplementary method for `convolveHor()`
|
|
119
|
+
//
|
|
129
120
|
|
|
130
121
|
|
|
131
|
-
function
|
|
122
|
+
function convolveVert(src, dest, srcW, srcH, destW, filters) {
|
|
132
123
|
var r, g, b, a;
|
|
133
124
|
var filterPtr, filterShift, filterSize;
|
|
134
125
|
var srcPtr, srcY, destX, filterVal;
|
|
@@ -154,27 +145,134 @@ function convolveVertically(src, dest, srcW, srcH, destW, filters) {
|
|
|
154
145
|
g = g + filterVal * src[srcPtr + 1] | 0;
|
|
155
146
|
r = r + filterVal * src[srcPtr] | 0;
|
|
156
147
|
srcPtr = srcPtr + 4 | 0;
|
|
157
|
-
} //
|
|
158
|
-
|
|
148
|
+
} // Sync with premultiplied version for exact result match
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
r >>= 7;
|
|
152
|
+
g >>= 7;
|
|
153
|
+
b >>= 7;
|
|
154
|
+
a >>= 7; // Bring this value back in range + round result.
|
|
155
|
+
//
|
|
156
|
+
|
|
157
|
+
dest[destOffset + 3] = clampTo8(a + (1 << 13) >> 14);
|
|
158
|
+
dest[destOffset + 2] = clampTo8(b + (1 << 13) >> 14);
|
|
159
|
+
dest[destOffset + 1] = clampTo8(g + (1 << 13) >> 14);
|
|
160
|
+
dest[destOffset] = clampTo8(r + (1 << 13) >> 14);
|
|
161
|
+
destOffset = destOffset + srcH * 4 | 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
destOffset = (srcY + 1) * 4 | 0;
|
|
165
|
+
srcOffset = (srcY + 1) * srcW * 4 | 0;
|
|
166
|
+
}
|
|
167
|
+
} // Premultiply & convolve image data in horizontal direction. Can be used for:
|
|
168
|
+
//
|
|
169
|
+
// - Any bitmap data, extracted with `.getImageData()` method (with
|
|
170
|
+
// non-premultiplied alpha)
|
|
171
|
+
//
|
|
172
|
+
// For images without alpha channel this method is slower than `convolveHor()`
|
|
173
|
+
//
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
function convolveHorWithPre(src, dest, srcW, srcH, destW, filters) {
|
|
177
|
+
var r, g, b, a, alpha;
|
|
178
|
+
var filterPtr, filterShift, filterSize;
|
|
179
|
+
var srcPtr, srcY, destX, filterVal;
|
|
180
|
+
var srcOffset = 0,
|
|
181
|
+
destOffset = 0; // For each row
|
|
182
|
+
|
|
183
|
+
for (srcY = 0; srcY < srcH; srcY++) {
|
|
184
|
+
filterPtr = 0; // Apply precomputed filters to each destination row point
|
|
185
|
+
|
|
186
|
+
for (destX = 0; destX < destW; destX++) {
|
|
187
|
+
// Get the filter that determines the current output pixel.
|
|
188
|
+
filterShift = filters[filterPtr++];
|
|
189
|
+
filterSize = filters[filterPtr++];
|
|
190
|
+
srcPtr = srcOffset + filterShift * 4 | 0;
|
|
191
|
+
r = g = b = a = 0; // Apply the filter to the row to get the destination pixel r, g, b, a
|
|
192
|
+
|
|
193
|
+
for (; filterSize > 0; filterSize--) {
|
|
194
|
+
filterVal = filters[filterPtr++]; // Use reverse order to workaround deopts in old v8 (node v.10)
|
|
195
|
+
// Big thanks to @mraleph (Vyacheslav Egorov) for the tip.
|
|
196
|
+
|
|
197
|
+
alpha = src[srcPtr + 3];
|
|
198
|
+
a = a + filterVal * alpha | 0;
|
|
199
|
+
b = b + filterVal * src[srcPtr + 2] * alpha | 0;
|
|
200
|
+
g = g + filterVal * src[srcPtr + 1] * alpha | 0;
|
|
201
|
+
r = r + filterVal * src[srcPtr] * alpha | 0;
|
|
202
|
+
srcPtr = srcPtr + 4 | 0;
|
|
203
|
+
} // Premultiply is (* alpha / 255).
|
|
204
|
+
// Postpone division for better performance
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
b = b / 255 | 0;
|
|
208
|
+
g = g / 255 | 0;
|
|
209
|
+
r = r / 255 | 0; // Store 15 bits between passes for better precision
|
|
210
|
+
// Instead of shift to 14 (FIXED_FRAC_BITS), shift to 7 only
|
|
159
211
|
//
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
212
|
+
|
|
213
|
+
dest[destOffset + 3] = clampNegative(a >> 7);
|
|
214
|
+
dest[destOffset + 2] = clampNegative(b >> 7);
|
|
215
|
+
dest[destOffset + 1] = clampNegative(g >> 7);
|
|
216
|
+
dest[destOffset] = clampNegative(r >> 7);
|
|
217
|
+
destOffset = destOffset + srcH * 4 | 0;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
destOffset = (srcY + 1) * 4 | 0;
|
|
221
|
+
srcOffset = (srcY + 1) * srcW * 4 | 0;
|
|
222
|
+
}
|
|
223
|
+
} // Supplementary method for `convolveHorWithPre()`
|
|
224
|
+
//
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
function convolveVertWithPre(src, dest, srcW, srcH, destW, filters) {
|
|
228
|
+
var r, g, b, a;
|
|
229
|
+
var filterPtr, filterShift, filterSize;
|
|
230
|
+
var srcPtr, srcY, destX, filterVal;
|
|
231
|
+
var srcOffset = 0,
|
|
232
|
+
destOffset = 0; // For each row
|
|
233
|
+
|
|
234
|
+
for (srcY = 0; srcY < srcH; srcY++) {
|
|
235
|
+
filterPtr = 0; // Apply precomputed filters to each destination row point
|
|
236
|
+
|
|
237
|
+
for (destX = 0; destX < destW; destX++) {
|
|
238
|
+
// Get the filter that determines the current output pixel.
|
|
239
|
+
filterShift = filters[filterPtr++];
|
|
240
|
+
filterSize = filters[filterPtr++];
|
|
241
|
+
srcPtr = srcOffset + filterShift * 4 | 0;
|
|
242
|
+
r = g = b = a = 0; // Apply the filter to the row to get the destination pixel r, g, b, a
|
|
243
|
+
|
|
244
|
+
for (; filterSize > 0; filterSize--) {
|
|
245
|
+
filterVal = filters[filterPtr++]; // Use reverse order to workaround deopts in old v8 (node v.10)
|
|
246
|
+
// Big thanks to @mraleph (Vyacheslav Egorov) for the tip.
|
|
247
|
+
|
|
248
|
+
a = a + filterVal * src[srcPtr + 3] | 0;
|
|
249
|
+
b = b + filterVal * src[srcPtr + 2] | 0;
|
|
250
|
+
g = g + filterVal * src[srcPtr + 1] | 0;
|
|
251
|
+
r = r + filterVal * src[srcPtr] | 0;
|
|
252
|
+
srcPtr = srcPtr + 4 | 0;
|
|
253
|
+
} // Downscale to leave room for un-premultiply
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
r >>= 7;
|
|
257
|
+
g >>= 7;
|
|
258
|
+
b >>= 7;
|
|
259
|
+
a >>= 7; // Un-premultiply
|
|
260
|
+
|
|
261
|
+
a = clampTo8(a + (1 << 13) >> 14);
|
|
262
|
+
|
|
263
|
+
if (a > 0) {
|
|
264
|
+
r = r * 255 / a | 0;
|
|
265
|
+
g = g * 255 / a | 0;
|
|
266
|
+
b = b * 255 / a | 0;
|
|
267
|
+
} // Bring this value back in range + round result.
|
|
268
|
+
// Shift value = FIXED_FRAC_BITS + 7
|
|
163
269
|
//
|
|
164
270
|
|
|
165
271
|
|
|
166
|
-
dest[destOffset + 3] =
|
|
167
|
-
|
|
168
|
-
);
|
|
169
|
-
dest[destOffset
|
|
170
|
-
/*FIXED_FRAC_BITS*/
|
|
171
|
-
);
|
|
172
|
-
dest[destOffset + 1] = clampTo8(g + (1 << 13) >> 14
|
|
173
|
-
/*FIXED_FRAC_BITS*/
|
|
174
|
-
);
|
|
175
|
-
dest[destOffset] = clampTo8(r + (1 << 13) >> 14
|
|
176
|
-
/*FIXED_FRAC_BITS*/
|
|
177
|
-
);
|
|
272
|
+
dest[destOffset + 3] = a;
|
|
273
|
+
dest[destOffset + 2] = clampTo8(b + (1 << 13) >> 14);
|
|
274
|
+
dest[destOffset + 1] = clampTo8(g + (1 << 13) >> 14);
|
|
275
|
+
dest[destOffset] = clampTo8(r + (1 << 13) >> 14);
|
|
178
276
|
destOffset = destOffset + srcH * 4 | 0;
|
|
179
277
|
}
|
|
180
278
|
|
|
@@ -184,8 +282,10 @@ function convolveVertically(src, dest, srcW, srcH, destW, filters) {
|
|
|
184
282
|
}
|
|
185
283
|
|
|
186
284
|
module.exports = {
|
|
187
|
-
|
|
188
|
-
|
|
285
|
+
convolveHor: convolveHor,
|
|
286
|
+
convolveVert: convolveVert,
|
|
287
|
+
convolveHorWithPre: convolveHorWithPre,
|
|
288
|
+
convolveVertWithPre: convolveVertWithPre
|
|
189
289
|
};
|
|
190
290
|
|
|
191
291
|
},{}],3:[function(_dereq_,module,exports){
|
|
@@ -194,7 +294,7 @@ module.exports = {
|
|
|
194
294
|
'use strict';
|
|
195
295
|
/* eslint-disable max-len */
|
|
196
296
|
|
|
197
|
-
module.exports = '
|
|
297
|
+
module.exports = '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';
|
|
198
298
|
|
|
199
299
|
},{}],4:[function(_dereq_,module,exports){
|
|
200
300
|
'use strict';
|
|
@@ -211,9 +311,23 @@ module.exports = {
|
|
|
211
311
|
|
|
212
312
|
var createFilters = _dereq_('./resize_filter_gen');
|
|
213
313
|
|
|
214
|
-
var
|
|
314
|
+
var _require = _dereq_('./convolve'),
|
|
315
|
+
convolveHor = _require.convolveHor,
|
|
316
|
+
convolveVert = _require.convolveVert,
|
|
317
|
+
convolveHorWithPre = _require.convolveHorWithPre,
|
|
318
|
+
convolveVertWithPre = _require.convolveVertWithPre;
|
|
215
319
|
|
|
216
|
-
|
|
320
|
+
function hasAlpha(src, width, height) {
|
|
321
|
+
var ptr = 3,
|
|
322
|
+
len = width * height * 4 | 0;
|
|
323
|
+
|
|
324
|
+
while (ptr < len) {
|
|
325
|
+
if (src[ptr] !== 255) return true;
|
|
326
|
+
ptr = ptr + 4 | 0;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
217
331
|
|
|
218
332
|
function resetAlpha(dst, width, height) {
|
|
219
333
|
var ptr = 3,
|
|
@@ -236,20 +350,20 @@ module.exports = function resize(options) {
|
|
|
236
350
|
var offsetX = options.offsetX || 0;
|
|
237
351
|
var offsetY = options.offsetY || 0;
|
|
238
352
|
var dest = options.dest || new Uint8Array(destW * destH * 4);
|
|
239
|
-
var
|
|
240
|
-
var
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
353
|
+
var filter = typeof options.filter === 'undefined' ? 'mks2013' : options.filter;
|
|
354
|
+
var filtersX = createFilters(filter, srcW, destW, scaleX, offsetX),
|
|
355
|
+
filtersY = createFilters(filter, srcH, destH, scaleY, offsetY);
|
|
356
|
+
var tmp = new Uint16Array(destW * srcH * 4); // Autodetect if alpha channel exists, and use appropriate method
|
|
357
|
+
|
|
358
|
+
if (hasAlpha(src, srcW, srcH)) {
|
|
359
|
+
convolveHorWithPre(src, tmp, srcW, srcH, destW, filtersX);
|
|
360
|
+
convolveVertWithPre(tmp, dest, srcH, destW, destH, filtersY);
|
|
361
|
+
} else {
|
|
362
|
+
convolveHor(src, tmp, srcW, srcH, destW, filtersX);
|
|
363
|
+
convolveVert(tmp, dest, srcH, destW, destH, filtersY);
|
|
364
|
+
resetAlpha(dest, destW, destH);
|
|
365
|
+
}
|
|
366
|
+
|
|
253
367
|
return dest;
|
|
254
368
|
};
|
|
255
369
|
|
|
@@ -274,13 +388,13 @@ function toFixedPoint(num) {
|
|
|
274
388
|
return Math.round(num * ((1 << FIXED_FRAC_BITS) - 1));
|
|
275
389
|
}
|
|
276
390
|
|
|
277
|
-
module.exports = function resizeFilterGen(
|
|
278
|
-
var filterFunction = FILTER_INFO[
|
|
391
|
+
module.exports = function resizeFilterGen(filter, srcSize, destSize, scale, offset) {
|
|
392
|
+
var filterFunction = FILTER_INFO.filter[filter].fn;
|
|
279
393
|
var scaleInverted = 1.0 / scale;
|
|
280
394
|
var scaleClamped = Math.min(1.0, scale); // For upscale
|
|
281
395
|
// Filter window (averaging interval), scaled to src image
|
|
282
396
|
|
|
283
|
-
var srcWindow = FILTER_INFO[
|
|
397
|
+
var srcWindow = FILTER_INFO.filter[filter].win / scaleClamped;
|
|
284
398
|
var destPixel, srcPixel, srcFirst, srcLast, filterElementSize, floatFilter, fxpFilter, total, pxl, idx, floatVal, filterTotal, filterVal;
|
|
285
399
|
var leftNotEmpty, rightNotEmpty, filterShift, filterSize;
|
|
286
400
|
var maxFilterElementSize = Math.floor((srcWindow + 1) * 2);
|
|
@@ -370,64 +484,121 @@ module.exports = function resizeFilterGen(quality, srcSize, destSize, scale, off
|
|
|
370
484
|
//
|
|
371
485
|
'use strict';
|
|
372
486
|
|
|
373
|
-
|
|
374
|
-
// Nearest neibor
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
// Hamming
|
|
381
|
-
win: 1.0,
|
|
382
|
-
filter: function filter(x) {
|
|
383
|
-
if (x <= -1.0 || x >= 1.0) {
|
|
384
|
-
return 0.0;
|
|
487
|
+
var filter = {
|
|
488
|
+
// Nearest neibor
|
|
489
|
+
box: {
|
|
490
|
+
win: 0.5,
|
|
491
|
+
fn: function fn(x) {
|
|
492
|
+
if (x < 0) x = -x;
|
|
493
|
+
return x < 0.5 ? 1.0 : 0.0;
|
|
385
494
|
}
|
|
495
|
+
},
|
|
496
|
+
// // Hamming
|
|
497
|
+
hamming: {
|
|
498
|
+
win: 1.0,
|
|
499
|
+
fn: function fn(x) {
|
|
500
|
+
if (x < 0) x = -x;
|
|
501
|
+
|
|
502
|
+
if (x >= 1.0) {
|
|
503
|
+
return 0.0;
|
|
504
|
+
}
|
|
386
505
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
506
|
+
if (x < 1.19209290E-07) {
|
|
507
|
+
return 1.0;
|
|
508
|
+
}
|
|
390
509
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
}
|
|
394
|
-
}, {
|
|
395
|
-
// Lanczos, win = 2
|
|
396
|
-
win: 2.0,
|
|
397
|
-
filter: function filter(x) {
|
|
398
|
-
if (x <= -2.0 || x >= 2.0) {
|
|
399
|
-
return 0.0;
|
|
510
|
+
var xpi = x * Math.PI;
|
|
511
|
+
return Math.sin(xpi) / xpi * (0.54 + 0.46 * Math.cos(xpi / 1.0));
|
|
400
512
|
}
|
|
513
|
+
},
|
|
514
|
+
// Lanczos, win = 2
|
|
515
|
+
lanczos2: {
|
|
516
|
+
win: 2.0,
|
|
517
|
+
fn: function fn(x) {
|
|
518
|
+
if (x < 0) x = -x;
|
|
401
519
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
520
|
+
if (x >= 2.0) {
|
|
521
|
+
return 0.0;
|
|
522
|
+
}
|
|
405
523
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
filter: function filter(x) {
|
|
413
|
-
if (x <= -3.0 || x >= 3.0) {
|
|
414
|
-
return 0.0;
|
|
524
|
+
if (x < 1.19209290E-07) {
|
|
525
|
+
return 1.0;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
var xpi = x * Math.PI;
|
|
529
|
+
return Math.sin(xpi) / xpi * Math.sin(xpi / 2.0) / (xpi / 2.0);
|
|
415
530
|
}
|
|
531
|
+
},
|
|
532
|
+
// Lanczos, win = 3
|
|
533
|
+
lanczos3: {
|
|
534
|
+
win: 3.0,
|
|
535
|
+
fn: function fn(x) {
|
|
536
|
+
if (x < 0) x = -x;
|
|
537
|
+
|
|
538
|
+
if (x >= 3.0) {
|
|
539
|
+
return 0.0;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (x < 1.19209290E-07) {
|
|
543
|
+
return 1.0;
|
|
544
|
+
}
|
|
416
545
|
|
|
417
|
-
|
|
418
|
-
return
|
|
546
|
+
var xpi = x * Math.PI;
|
|
547
|
+
return Math.sin(xpi) / xpi * Math.sin(xpi / 3.0) / (xpi / 3.0);
|
|
419
548
|
}
|
|
549
|
+
},
|
|
550
|
+
// Magic Kernel Sharp 2013, win = 2.5
|
|
551
|
+
// http://johncostella.com/magic/
|
|
552
|
+
mks2013: {
|
|
553
|
+
win: 2.5,
|
|
554
|
+
fn: function fn(x) {
|
|
555
|
+
if (x < 0) x = -x;
|
|
556
|
+
|
|
557
|
+
if (x >= 2.5) {
|
|
558
|
+
return 0.0;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (x >= 1.5) {
|
|
562
|
+
return -0.125 * (x - 2.5) * (x - 2.5);
|
|
563
|
+
}
|
|
420
564
|
|
|
421
|
-
|
|
422
|
-
|
|
565
|
+
if (x >= 0.5) {
|
|
566
|
+
return 0.25 * (4 * x * x - 11 * x + 7);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return 1.0625 - 1.75 * x * x;
|
|
570
|
+
}
|
|
423
571
|
}
|
|
424
|
-
}
|
|
572
|
+
};
|
|
573
|
+
module.exports = {
|
|
574
|
+
filter: filter,
|
|
575
|
+
// Legacy mapping
|
|
576
|
+
f2q: {
|
|
577
|
+
box: 0,
|
|
578
|
+
hamming: 1,
|
|
579
|
+
lanczos2: 2,
|
|
580
|
+
lanczos3: 3
|
|
581
|
+
},
|
|
582
|
+
q2f: ['box', 'hamming', 'lanczos2', 'lanczos3']
|
|
583
|
+
};
|
|
425
584
|
|
|
426
585
|
},{}],8:[function(_dereq_,module,exports){
|
|
427
586
|
'use strict';
|
|
428
587
|
|
|
429
588
|
var createFilters = _dereq_('./resize_filter_gen');
|
|
430
589
|
|
|
590
|
+
function hasAlpha(src, width, height) {
|
|
591
|
+
var ptr = 3,
|
|
592
|
+
len = width * height * 4 | 0;
|
|
593
|
+
|
|
594
|
+
while (ptr < len) {
|
|
595
|
+
if (src[ptr] !== 255) return true;
|
|
596
|
+
ptr = ptr + 4 | 0;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
|
|
431
602
|
function resetAlpha(dst, width, height) {
|
|
432
603
|
var ptr = 3,
|
|
433
604
|
len = width * height * 4 | 0;
|
|
@@ -472,16 +643,18 @@ module.exports = function resize_wasm(options) {
|
|
|
472
643
|
var offsetX = options.offsetX || 0.0;
|
|
473
644
|
var offsetY = options.offsetY || 0.0;
|
|
474
645
|
var dest = options.dest || new Uint8Array(destW * destH * 4);
|
|
475
|
-
var
|
|
476
|
-
var
|
|
477
|
-
|
|
478
|
-
|
|
646
|
+
var filter = typeof options.filter === 'undefined' ? 'mks2013' : options.filter;
|
|
647
|
+
var filtersX = createFilters(filter, srcW, destW, scaleX, offsetX),
|
|
648
|
+
filtersY = createFilters(filter, srcH, destH, scaleY, offsetY); // destination is 0 too.
|
|
649
|
+
|
|
650
|
+
var src_offset = 0;
|
|
651
|
+
var src_size = Math.max(src.byteLength, dest.byteLength); // buffer between convolve passes
|
|
479
652
|
|
|
480
|
-
var
|
|
653
|
+
var tmp_offset = this.__align(src_offset + src_size);
|
|
481
654
|
|
|
482
|
-
var
|
|
655
|
+
var tmp_size = srcH * destW * 4 * 2; // 2 bytes per channel
|
|
483
656
|
|
|
484
|
-
var filtersX_offset = this.__align(tmp_offset +
|
|
657
|
+
var filtersX_offset = this.__align(tmp_offset + tmp_size);
|
|
485
658
|
|
|
486
659
|
var filtersY_offset = this.__align(filtersX_offset + filtersX.byteLength);
|
|
487
660
|
|
|
@@ -500,22 +673,24 @@ module.exports = function resize_wasm(options) {
|
|
|
500
673
|
// speed difference is not significant vs direct .set()
|
|
501
674
|
|
|
502
675
|
copyInt16asLE(filtersX, mem, filtersX_offset);
|
|
503
|
-
copyInt16asLE(filtersY, mem, filtersY_offset); //
|
|
504
|
-
// Now call webassembly method
|
|
676
|
+
copyInt16asLE(filtersY, mem, filtersY_offset); // Now call webassembly method
|
|
505
677
|
// emsdk does method names with '_'
|
|
506
678
|
|
|
507
679
|
var fn = instance.exports.convolveHV || instance.exports._convolveHV;
|
|
508
|
-
|
|
680
|
+
|
|
681
|
+
if (hasAlpha(src, srcW, srcH)) {
|
|
682
|
+
fn(filtersX_offset, filtersY_offset, tmp_offset, srcW, srcH, destW, destH, 1);
|
|
683
|
+
} else {
|
|
684
|
+
fn(filtersX_offset, filtersY_offset, tmp_offset, srcW, srcH, destW, destH, 0);
|
|
685
|
+
resetAlpha(dest, destW, destH);
|
|
686
|
+
} //
|
|
509
687
|
// Copy data back to typed array
|
|
510
688
|
//
|
|
511
689
|
// 32-bit copy is much faster in chrome
|
|
512
690
|
|
|
513
|
-
var dest32 = new Uint32Array(dest.buffer);
|
|
514
|
-
dest32.set(new Uint32Array(this.__memory.buffer, 0, destH * destW)); // That's faster than doing checks in convolver.
|
|
515
|
-
// !!! Note, canvas data is not premultipled. We don't need other
|
|
516
|
-
// alpha corrections.
|
|
517
691
|
|
|
518
|
-
|
|
692
|
+
var dest32 = new Uint32Array(dest.buffer);
|
|
693
|
+
dest32.set(new Uint32Array(this.__memory.buffer, 0, destH * destW));
|
|
519
694
|
return dest;
|
|
520
695
|
};
|
|
521
696
|
|
|
@@ -986,7 +1161,18 @@ module.exports.cib_support = function cib_support(createCanvas) {
|
|
|
986
1161
|
|
|
987
1162
|
module.exports.worker_offscreen_canvas_support = function worker_offscreen_canvas_support() {
|
|
988
1163
|
return new Promise(function (resolve, reject) {
|
|
1164
|
+
if (typeof OffscreenCanvas === 'undefined') {
|
|
1165
|
+
// if OffscreenCanvas is present, we assume browser supports Worker and built-in Promise as well
|
|
1166
|
+
resolve(false);
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
989
1170
|
function workerPayload(self) {
|
|
1171
|
+
if (typeof createImageBitmap === 'undefined') {
|
|
1172
|
+
self.postMessage(false);
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
990
1176
|
Promise.resolve().then(function () {
|
|
991
1177
|
var canvas = new OffscreenCanvas(10, 10); // test that 2d context can be used in worker
|
|
992
1178
|
|
|
@@ -1005,10 +1191,75 @@ module.exports.worker_offscreen_canvas_support = function worker_offscreen_canva
|
|
|
1005
1191
|
var w = new Worker("data:text/javascript;base64,".concat(code));
|
|
1006
1192
|
|
|
1007
1193
|
w.onmessage = function (ev) {
|
|
1008
|
-
return ev.data
|
|
1194
|
+
return resolve(ev.data);
|
|
1009
1195
|
};
|
|
1010
1196
|
|
|
1011
1197
|
w.onerror = reject;
|
|
1198
|
+
}).then(function (result) {
|
|
1199
|
+
return result;
|
|
1200
|
+
}, function () {
|
|
1201
|
+
return false;
|
|
1202
|
+
});
|
|
1203
|
+
}; // Check if canvas.getContext('2d').getImageData can be used,
|
|
1204
|
+
// FireFox randomizes the output of that function in `privacy.resistFingerprinting` mode
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
module.exports.can_use_canvas = function can_use_canvas(createCanvas) {
|
|
1208
|
+
var usable = false;
|
|
1209
|
+
|
|
1210
|
+
try {
|
|
1211
|
+
var canvas = createCanvas(2, 1);
|
|
1212
|
+
var ctx = canvas.getContext('2d');
|
|
1213
|
+
var d = ctx.createImageData(2, 1);
|
|
1214
|
+
d.data[0] = 12;
|
|
1215
|
+
d.data[1] = 23;
|
|
1216
|
+
d.data[2] = 34;
|
|
1217
|
+
d.data[3] = 255;
|
|
1218
|
+
d.data[4] = 45;
|
|
1219
|
+
d.data[5] = 56;
|
|
1220
|
+
d.data[6] = 67;
|
|
1221
|
+
d.data[7] = 255;
|
|
1222
|
+
ctx.putImageData(d, 0, 0);
|
|
1223
|
+
d = null;
|
|
1224
|
+
d = ctx.getImageData(0, 0, 2, 1);
|
|
1225
|
+
|
|
1226
|
+
if (d.data[0] === 12 && d.data[1] === 23 && d.data[2] === 34 && d.data[3] === 255 && d.data[4] === 45 && d.data[5] === 56 && d.data[6] === 67 && d.data[7] === 255) {
|
|
1227
|
+
usable = true;
|
|
1228
|
+
}
|
|
1229
|
+
} catch (err) {}
|
|
1230
|
+
|
|
1231
|
+
return usable;
|
|
1232
|
+
}; // Check if createImageBitmap(img, sx, sy, sw, sh) signature works correctly
|
|
1233
|
+
// with JPEG images oriented with Exif;
|
|
1234
|
+
// https://bugs.chromium.org/p/chromium/issues/detail?id=1220671
|
|
1235
|
+
// TODO: remove after it's fixed in chrome for at least 2 releases
|
|
1236
|
+
|
|
1237
|
+
|
|
1238
|
+
module.exports.cib_can_use_region = function cib_can_use_region() {
|
|
1239
|
+
return new Promise(function (resolve) {
|
|
1240
|
+
if (typeof createImageBitmap === 'undefined') {
|
|
1241
|
+
resolve(false);
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
var image = new Image();
|
|
1246
|
+
image.src = 'data:image/jpeg;base64,' + '/9j/4QBiRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAYAAAEaAAUAAAABAAAASgEbAAUAA' + 'AABAAAAUgEoAAMAAAABAAIAAAITAAMAAAABAAEAAAAAAAAAAABIAAAAAQAAAEgAAAAB/9' + 'sAQwAEAwMEAwMEBAMEBQQEBQYKBwYGBgYNCQoICg8NEBAPDQ8OERMYFBESFxIODxUcFRc' + 'ZGRsbGxAUHR8dGh8YGhsa/9sAQwEEBQUGBQYMBwcMGhEPERoaGhoaGhoaGhoaGhoaGhoa' + 'GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa/8IAEQgAAQACAwERAAIRAQMRA' + 'f/EABQAAQAAAAAAAAAAAAAAAAAAAAf/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAA' + 'IQAxAAAAF/P//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAQUCf//EABQRAQAAAAA' + 'AAAAAAAAAAAAAAAD/2gAIAQMBAT8Bf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIB' + 'AT8Bf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEABj8Cf//EABQQAQAAAAAAAAAAA' + 'AAAAAAAAAD/2gAIAQEAAT8hf//aAAwDAQACAAMAAAAQH//EABQRAQAAAAAAAAAAAAAAAA' + 'AAAAD/2gAIAQMBAT8Qf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Qf//EABQ' + 'QAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8Qf//Z';
|
|
1247
|
+
|
|
1248
|
+
image.onload = function () {
|
|
1249
|
+
createImageBitmap(image, 0, 0, image.width, image.height).then(function (bitmap) {
|
|
1250
|
+
if (bitmap.width === image.width && bitmap.height === image.height) {
|
|
1251
|
+
resolve(true);
|
|
1252
|
+
} else {
|
|
1253
|
+
resolve(false);
|
|
1254
|
+
}
|
|
1255
|
+
}, function () {
|
|
1256
|
+
return resolve(false);
|
|
1257
|
+
});
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1260
|
+
image.onerror = function () {
|
|
1261
|
+
return resolve(false);
|
|
1262
|
+
};
|
|
1012
1263
|
});
|
|
1013
1264
|
};
|
|
1014
1265
|
|
|
@@ -1028,16 +1279,15 @@ module.exports = function () {
|
|
|
1028
1279
|
|
|
1029
1280
|
if (!tileOpts.src && tileOpts.srcBitmap) {
|
|
1030
1281
|
var canvas = new OffscreenCanvas(tileOpts.width, tileOpts.height);
|
|
1031
|
-
var ctx = canvas.getContext('2d'
|
|
1032
|
-
alpha: Boolean(tileOpts.alpha)
|
|
1033
|
-
});
|
|
1282
|
+
var ctx = canvas.getContext('2d');
|
|
1034
1283
|
ctx.drawImage(tileOpts.srcBitmap, 0, 0);
|
|
1035
1284
|
tileOpts.src = ctx.getImageData(0, 0, tileOpts.width, tileOpts.height).data;
|
|
1036
1285
|
canvas.width = canvas.height = 0;
|
|
1037
1286
|
canvas = null;
|
|
1038
1287
|
tileOpts.srcBitmap.close();
|
|
1039
|
-
tileOpts.srcBitmap = null;
|
|
1040
|
-
|
|
1288
|
+
tileOpts.srcBitmap = null; // Temporary force out data to typed array, because Chrome have artefacts
|
|
1289
|
+
// https://github.com/nodeca/pica/issues/223
|
|
1290
|
+
// returnBitmap = true;
|
|
1041
1291
|
}
|
|
1042
1292
|
|
|
1043
1293
|
if (!mathLib) mathLib = new MathLib(ev.data.features); // Use multimath's sync auto-init. Avoid Promise use in old browsers,
|
|
@@ -1050,9 +1300,7 @@ module.exports = function () {
|
|
|
1050
1300
|
|
|
1051
1301
|
var _canvas = new OffscreenCanvas(tileOpts.toWidth, tileOpts.toHeight);
|
|
1052
1302
|
|
|
1053
|
-
var _ctx = _canvas.getContext('2d'
|
|
1054
|
-
alpha: Boolean(tileOpts.alpha)
|
|
1055
|
-
});
|
|
1303
|
+
var _ctx = _canvas.getContext('2d');
|
|
1056
1304
|
|
|
1057
1305
|
_ctx.putImageData(toImageData, 0, 0);
|
|
1058
1306
|
|
|
@@ -1191,35 +1439,6 @@ function blurMono16(src, width, height, radius) {
|
|
|
1191
1439
|
module.exports = blurMono16;
|
|
1192
1440
|
|
|
1193
1441
|
},{}],19:[function(_dereq_,module,exports){
|
|
1194
|
-
if (typeof Object.create === 'function') {
|
|
1195
|
-
// implementation from standard node.js 'util' module
|
|
1196
|
-
module.exports = function inherits(ctor, superCtor) {
|
|
1197
|
-
if (superCtor) {
|
|
1198
|
-
ctor.super_ = superCtor
|
|
1199
|
-
ctor.prototype = Object.create(superCtor.prototype, {
|
|
1200
|
-
constructor: {
|
|
1201
|
-
value: ctor,
|
|
1202
|
-
enumerable: false,
|
|
1203
|
-
writable: true,
|
|
1204
|
-
configurable: true
|
|
1205
|
-
}
|
|
1206
|
-
})
|
|
1207
|
-
}
|
|
1208
|
-
};
|
|
1209
|
-
} else {
|
|
1210
|
-
// old school shim for old browsers
|
|
1211
|
-
module.exports = function inherits(ctor, superCtor) {
|
|
1212
|
-
if (superCtor) {
|
|
1213
|
-
ctor.super_ = superCtor
|
|
1214
|
-
var TempCtor = function () {}
|
|
1215
|
-
TempCtor.prototype = superCtor.prototype
|
|
1216
|
-
ctor.prototype = new TempCtor()
|
|
1217
|
-
ctor.prototype.constructor = ctor
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
|
|
1222
|
-
},{}],20:[function(_dereq_,module,exports){
|
|
1223
1442
|
'use strict';
|
|
1224
1443
|
|
|
1225
1444
|
|
|
@@ -1378,7 +1597,7 @@ MultiMath.prototype.__align = function align(number, base) {
|
|
|
1378
1597
|
|
|
1379
1598
|
module.exports = MultiMath;
|
|
1380
1599
|
|
|
1381
|
-
},{"./lib/base64decode":
|
|
1600
|
+
},{"./lib/base64decode":20,"./lib/wa_detect":21,"object-assign":22}],20:[function(_dereq_,module,exports){
|
|
1382
1601
|
// base64 decode str -> Uint8Array, to load WA modules
|
|
1383
1602
|
//
|
|
1384
1603
|
'use strict';
|
|
@@ -1426,7 +1645,7 @@ module.exports = function base64decode(str) {
|
|
|
1426
1645
|
return out;
|
|
1427
1646
|
};
|
|
1428
1647
|
|
|
1429
|
-
},{}],
|
|
1648
|
+
},{}],21:[function(_dereq_,module,exports){
|
|
1430
1649
|
// Detect WebAssembly support.
|
|
1431
1650
|
// - Check global WebAssembly object
|
|
1432
1651
|
// - Try to load simple module (can be disabled via CSP)
|
|
@@ -1465,7 +1684,7 @@ module.exports = function hasWebAssembly() {
|
|
|
1465
1684
|
return wa;
|
|
1466
1685
|
};
|
|
1467
1686
|
|
|
1468
|
-
},{}],
|
|
1687
|
+
},{}],22:[function(_dereq_,module,exports){
|
|
1469
1688
|
/*
|
|
1470
1689
|
object-assign
|
|
1471
1690
|
(c) Sindre Sorhus
|
|
@@ -1557,7 +1776,7 @@ module.exports = shouldUseNative() ? Object.assign : function (target, source) {
|
|
|
1557
1776
|
return to;
|
|
1558
1777
|
};
|
|
1559
1778
|
|
|
1560
|
-
},{}],
|
|
1779
|
+
},{}],23:[function(_dereq_,module,exports){
|
|
1561
1780
|
var bundleFn = arguments[3];
|
|
1562
1781
|
var sources = arguments[4];
|
|
1563
1782
|
var cache = arguments[5];
|
|
@@ -1650,7 +1869,7 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
|
|
|
1650
1869
|
|
|
1651
1870
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
1652
1871
|
|
|
1653
|
-
function _iterableToArrayLimit(arr, i) { var _i = arr
|
|
1872
|
+
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
1654
1873
|
|
|
1655
1874
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
1656
1875
|
|
|
@@ -1668,7 +1887,9 @@ var worker = _dereq_('./lib/worker');
|
|
|
1668
1887
|
|
|
1669
1888
|
var createStages = _dereq_('./lib/stepper');
|
|
1670
1889
|
|
|
1671
|
-
var createRegions = _dereq_('./lib/tiler');
|
|
1890
|
+
var createRegions = _dereq_('./lib/tiler');
|
|
1891
|
+
|
|
1892
|
+
var filter_info = _dereq_('./lib/mm_resize/resize_filter_info'); // Deduplicate pools & limiters with the same configs
|
|
1672
1893
|
// when user creates multiple pica instances.
|
|
1673
1894
|
|
|
1674
1895
|
|
|
@@ -1700,15 +1921,16 @@ var DEFAULT_PICA_OPTS = {
|
|
|
1700
1921
|
}
|
|
1701
1922
|
};
|
|
1702
1923
|
var DEFAULT_RESIZE_OPTS = {
|
|
1703
|
-
|
|
1704
|
-
alpha: false,
|
|
1924
|
+
filter: 'mks2013',
|
|
1705
1925
|
unsharpAmount: 0,
|
|
1706
1926
|
unsharpRadius: 0.0,
|
|
1707
1927
|
unsharpThreshold: 0
|
|
1708
1928
|
};
|
|
1709
|
-
var CAN_NEW_IMAGE_DATA;
|
|
1710
|
-
var CAN_CREATE_IMAGE_BITMAP;
|
|
1711
|
-
var
|
|
1929
|
+
var CAN_NEW_IMAGE_DATA = false;
|
|
1930
|
+
var CAN_CREATE_IMAGE_BITMAP = false;
|
|
1931
|
+
var CAN_USE_CANVAS_GET_IMAGE_DATA = false;
|
|
1932
|
+
var CAN_USE_OFFSCREEN_CANVAS = false;
|
|
1933
|
+
var CAN_USE_CIB_REGION_FOR_IMAGE = false;
|
|
1712
1934
|
|
|
1713
1935
|
function workerFabric() {
|
|
1714
1936
|
return {
|
|
@@ -1759,16 +1981,12 @@ Pica.prototype.init = function () {
|
|
|
1759
1981
|
|
|
1760
1982
|
if (this.__initPromise) return this.__initPromise; // Test if we can create ImageData without canvas and memory copy
|
|
1761
1983
|
|
|
1762
|
-
if (
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
new ImageData(new Uint8ClampedArray(400), 10, 10);
|
|
1769
|
-
CAN_NEW_IMAGE_DATA = true;
|
|
1770
|
-
} catch (__) {}
|
|
1771
|
-
}
|
|
1984
|
+
if (typeof ImageData !== 'undefined' && typeof Uint8ClampedArray !== 'undefined') {
|
|
1985
|
+
try {
|
|
1986
|
+
/* eslint-disable no-new */
|
|
1987
|
+
new ImageData(new Uint8ClampedArray(400), 10, 10);
|
|
1988
|
+
CAN_NEW_IMAGE_DATA = true;
|
|
1989
|
+
} catch (__) {}
|
|
1772
1990
|
} // ImageBitmap can be effective in 2 places:
|
|
1773
1991
|
//
|
|
1774
1992
|
// 1. Threaded jpeg unpack (basic)
|
|
@@ -1778,15 +1996,11 @@ Pica.prototype.init = function () {
|
|
|
1778
1996
|
// see https://developer.mozilla.org/ru/docs/Web/API/ImageBitmap
|
|
1779
1997
|
|
|
1780
1998
|
|
|
1781
|
-
if (
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
CAN_CREATE_IMAGE_BITMAP = true;
|
|
1787
|
-
} else {
|
|
1788
|
-
this.debug('ImageBitmap does not support .close(), disabled');
|
|
1789
|
-
}
|
|
1999
|
+
if (typeof ImageBitmap !== 'undefined') {
|
|
2000
|
+
if (ImageBitmap.prototype && ImageBitmap.prototype.close) {
|
|
2001
|
+
CAN_CREATE_IMAGE_BITMAP = true;
|
|
2002
|
+
} else {
|
|
2003
|
+
this.debug('ImageBitmap does not support .close(), disabled');
|
|
1790
2004
|
}
|
|
1791
2005
|
}
|
|
1792
2006
|
|
|
@@ -1842,21 +2056,26 @@ Pica.prototype.init = function () {
|
|
|
1842
2056
|
});
|
|
1843
2057
|
}
|
|
1844
2058
|
|
|
2059
|
+
CAN_USE_CANVAS_GET_IMAGE_DATA = utils.can_use_canvas(this.options.createCanvas);
|
|
1845
2060
|
var checkOffscreenCanvas;
|
|
1846
2061
|
|
|
1847
2062
|
if (CAN_CREATE_IMAGE_BITMAP && CAN_NEW_IMAGE_DATA && features.indexOf('ww') !== -1) {
|
|
1848
2063
|
checkOffscreenCanvas = utils.worker_offscreen_canvas_support();
|
|
1849
2064
|
} else {
|
|
1850
|
-
checkOffscreenCanvas = Promise.
|
|
2065
|
+
checkOffscreenCanvas = Promise.resolve(false);
|
|
1851
2066
|
}
|
|
1852
2067
|
|
|
1853
|
-
checkOffscreenCanvas = checkOffscreenCanvas.then(function () {
|
|
1854
|
-
CAN_USE_OFFSCREEN_CANVAS =
|
|
1855
|
-
}
|
|
1856
|
-
|
|
2068
|
+
checkOffscreenCanvas = checkOffscreenCanvas.then(function (result) {
|
|
2069
|
+
CAN_USE_OFFSCREEN_CANVAS = result;
|
|
2070
|
+
}); // we use createImageBitmap to crop image data and pass it to workers,
|
|
2071
|
+
// so need to check whether function works correctly;
|
|
2072
|
+
// https://bugs.chromium.org/p/chromium/issues/detail?id=1220671
|
|
2073
|
+
|
|
2074
|
+
var checkCibRegion = utils.cib_can_use_region().then(function (result) {
|
|
2075
|
+
CAN_USE_CIB_REGION_FOR_IMAGE = result;
|
|
1857
2076
|
}); // Init math lib. That's async because can load some
|
|
1858
2077
|
|
|
1859
|
-
this.__initPromise = Promise.all([initMath, checkCibResize, checkOffscreenCanvas]).then(function () {
|
|
2078
|
+
this.__initPromise = Promise.all([initMath, checkCibResize, checkOffscreenCanvas, checkCibRegion]).then(function () {
|
|
1860
2079
|
return _this;
|
|
1861
2080
|
});
|
|
1862
2081
|
return this.__initPromise;
|
|
@@ -1908,7 +2127,10 @@ Pica.prototype.__invokeResize = function (tileOpts, opts) {
|
|
|
1908
2127
|
|
|
1909
2128
|
|
|
1910
2129
|
Pica.prototype.__extractTileData = function (tile, from, opts, stageEnv, extractTo) {
|
|
1911
|
-
if (this.features.ww && CAN_USE_OFFSCREEN_CANVAS)
|
|
2130
|
+
if (this.features.ww && CAN_USE_OFFSCREEN_CANVAS && ( // createImageBitmap doesn't work for images (Image, ImageBitmap) with Exif orientation in Chrome,
|
|
2131
|
+
// can use canvas because canvas doesn't have orientation;
|
|
2132
|
+
// see https://bugs.chromium.org/p/chromium/issues/detail?id=1220671
|
|
2133
|
+
utils.isCanvas(from) || CAN_USE_CIB_REGION_FOR_IMAGE)) {
|
|
1912
2134
|
this.debug('Create tile for OffscreenCanvas');
|
|
1913
2135
|
return createImageBitmap(stageEnv.srcImageBitmap || from, tile.x, tile.y, tile.width, tile.height).then(function (bitmap) {
|
|
1914
2136
|
extractTo.srcBitmap = bitmap;
|
|
@@ -1918,9 +2140,7 @@ Pica.prototype.__extractTileData = function (tile, from, opts, stageEnv, extract
|
|
|
1918
2140
|
|
|
1919
2141
|
|
|
1920
2142
|
if (utils.isCanvas(from)) {
|
|
1921
|
-
if (!stageEnv.srcCtx) stageEnv.srcCtx = from.getContext('2d'
|
|
1922
|
-
alpha: Boolean(opts.alpha)
|
|
1923
|
-
}); // If input is Canvas - extract region data directly
|
|
2143
|
+
if (!stageEnv.srcCtx) stageEnv.srcCtx = from.getContext('2d'); // If input is Canvas - extract region data directly
|
|
1924
2144
|
|
|
1925
2145
|
this.debug('Get tile pixel data');
|
|
1926
2146
|
extractTo.src = stageEnv.srcCtx.getImageData(tile.x, tile.y, tile.width, tile.height).data;
|
|
@@ -1934,9 +2154,7 @@ Pica.prototype.__extractTileData = function (tile, from, opts, stageEnv, extract
|
|
|
1934
2154
|
|
|
1935
2155
|
this.debug('Draw tile imageBitmap/image to temporary canvas');
|
|
1936
2156
|
var tmpCanvas = this.options.createCanvas(tile.width, tile.height);
|
|
1937
|
-
var tmpCtx = tmpCanvas.getContext('2d'
|
|
1938
|
-
alpha: Boolean(opts.alpha)
|
|
1939
|
-
});
|
|
2157
|
+
var tmpCtx = tmpCanvas.getContext('2d');
|
|
1940
2158
|
tmpCtx.globalCompositeOperation = 'copy';
|
|
1941
2159
|
tmpCtx.drawImage(stageEnv.srcImageBitmap || from, tile.x, tile.y, tile.width, tile.height, 0, 0, tile.width, tile.height);
|
|
1942
2160
|
this.debug('Get tile pixel data');
|
|
@@ -2009,8 +2227,7 @@ Pica.prototype.__tileAndResize = function (from, to, opts) {
|
|
|
2009
2227
|
scaleY: tile.scaleY,
|
|
2010
2228
|
offsetX: tile.offsetX,
|
|
2011
2229
|
offsetY: tile.offsetY,
|
|
2012
|
-
|
|
2013
|
-
alpha: opts.alpha,
|
|
2230
|
+
filter: opts.filter,
|
|
2014
2231
|
unsharpAmount: opts.unsharpAmount,
|
|
2015
2232
|
unsharpRadius: opts.unsharpRadius,
|
|
2016
2233
|
unsharpThreshold: opts.unsharpThreshold
|
|
@@ -2035,9 +2252,7 @@ Pica.prototype.__tileAndResize = function (from, to, opts) {
|
|
|
2035
2252
|
|
|
2036
2253
|
|
|
2037
2254
|
return Promise.resolve().then(function () {
|
|
2038
|
-
stageEnv.toCtx = to.getContext('2d'
|
|
2039
|
-
alpha: Boolean(opts.alpha)
|
|
2040
|
-
});
|
|
2255
|
+
stageEnv.toCtx = to.getContext('2d');
|
|
2041
2256
|
if (utils.isCanvas(from)) return null;
|
|
2042
2257
|
|
|
2043
2258
|
if (utils.isImageBitmap(from)) {
|
|
@@ -2117,14 +2332,20 @@ Pica.prototype.__processStages = function (stages, from, to, opts) {
|
|
|
2117
2332
|
toWidth = _stages$shift2[0],
|
|
2118
2333
|
toHeight = _stages$shift2[1];
|
|
2119
2334
|
|
|
2120
|
-
var isLastStage = stages.length === 0;
|
|
2335
|
+
var isLastStage = stages.length === 0; // Optimization for legacy filters -
|
|
2336
|
+
// only use user-defined quality for the last stage,
|
|
2337
|
+
// use simpler (Hamming) filter for the first stages where
|
|
2338
|
+
// scale factor is large enough (more than 2-3)
|
|
2339
|
+
//
|
|
2340
|
+
// For advanced filters (mks2013 and custom) - skip optimization,
|
|
2341
|
+
// because need to apply sharpening every time
|
|
2342
|
+
|
|
2343
|
+
var filter;
|
|
2344
|
+
if (isLastStage || filter_info.q2f.indexOf(opts.filter) < 0) filter = opts.filter;else if (opts.filter === 'box') filter = 'box';else filter = 'hamming';
|
|
2121
2345
|
opts = assign({}, opts, {
|
|
2122
2346
|
toWidth: toWidth,
|
|
2123
2347
|
toHeight: toHeight,
|
|
2124
|
-
|
|
2125
|
-
// use simpler (Hamming) filter for the first stages where
|
|
2126
|
-
// scale factor is large enough (more than 2-3)
|
|
2127
|
-
quality: isLastStage ? opts.quality : Math.min(1, opts.quality)
|
|
2348
|
+
filter: filter
|
|
2128
2349
|
});
|
|
2129
2350
|
var tmpCanvas;
|
|
2130
2351
|
|
|
@@ -2152,14 +2373,12 @@ Pica.prototype.__processStages = function (stages, from, to, opts) {
|
|
|
2152
2373
|
Pica.prototype.__resizeViaCreateImageBitmap = function (from, to, opts) {
|
|
2153
2374
|
var _this5 = this;
|
|
2154
2375
|
|
|
2155
|
-
var toCtx = to.getContext('2d'
|
|
2156
|
-
alpha: Boolean(opts.alpha)
|
|
2157
|
-
});
|
|
2376
|
+
var toCtx = to.getContext('2d');
|
|
2158
2377
|
this.debug('Resize via createImageBitmap()');
|
|
2159
2378
|
return createImageBitmap(from, {
|
|
2160
2379
|
resizeWidth: opts.toWidth,
|
|
2161
2380
|
resizeHeight: opts.toHeight,
|
|
2162
|
-
resizeQuality: utils.cib_quality_name(opts.
|
|
2381
|
+
resizeQuality: utils.cib_quality_name(filter_info.f2q[opts.filter])
|
|
2163
2382
|
}).then(function (imageBitmap) {
|
|
2164
2383
|
if (opts.canceled) return opts.cancelToken; // if no unsharp - draw directly to output canvas
|
|
2165
2384
|
|
|
@@ -2177,9 +2396,7 @@ Pica.prototype.__resizeViaCreateImageBitmap = function (from, to, opts) {
|
|
|
2177
2396
|
|
|
2178
2397
|
var tmpCanvas = _this5.options.createCanvas(opts.toWidth, opts.toHeight);
|
|
2179
2398
|
|
|
2180
|
-
var tmpCtx = tmpCanvas.getContext('2d'
|
|
2181
|
-
alpha: Boolean(opts.alpha)
|
|
2182
|
-
});
|
|
2399
|
+
var tmpCtx = tmpCanvas.getContext('2d');
|
|
2183
2400
|
tmpCtx.drawImage(imageBitmap, 0, 0);
|
|
2184
2401
|
imageBitmap.close();
|
|
2185
2402
|
var iData = tmpCtx.getImageData(0, 0, opts.toWidth, opts.toHeight);
|
|
@@ -2215,7 +2432,16 @@ Pica.prototype.resize = function (from, to, options) {
|
|
|
2215
2432
|
opts.toWidth = to.width;
|
|
2216
2433
|
opts.toHeight = to.height;
|
|
2217
2434
|
opts.width = from.naturalWidth || from.width;
|
|
2218
|
-
opts.height = from.naturalHeight || from.height; //
|
|
2435
|
+
opts.height = from.naturalHeight || from.height; // Legacy `.quality` option
|
|
2436
|
+
|
|
2437
|
+
if (Object.prototype.hasOwnProperty.call(opts, 'quality')) {
|
|
2438
|
+
if (opts.quality < 0 || opts.quality > 3) {
|
|
2439
|
+
throw new Error("Pica: .quality should be [0..3], got ".concat(opts.quality));
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
opts.filter = filter_info.q2f[opts.quality];
|
|
2443
|
+
} // Prevent stepper from infinite loop
|
|
2444
|
+
|
|
2219
2445
|
|
|
2220
2446
|
if (to.width === 0 || to.height === 0) {
|
|
2221
2447
|
return Promise.reject(new Error("Invalid output size: ".concat(to.width, "x").concat(to.height)));
|
|
@@ -2242,7 +2468,17 @@ Pica.prototype.resize = function (from, to, options) {
|
|
|
2242
2468
|
if (opts.canceled) return opts.cancelToken; // if createImageBitmap supports resize, just do it and return
|
|
2243
2469
|
|
|
2244
2470
|
if (_this6.features.cib) {
|
|
2245
|
-
|
|
2471
|
+
if (filter_info.q2f.indexOf(opts.filter) >= 0) {
|
|
2472
|
+
return _this6.__resizeViaCreateImageBitmap(from, to, opts);
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
_this6.debug('cib is enabled, but not supports provided filter, fallback to manual math');
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2478
|
+
if (!CAN_USE_CANVAS_GET_IMAGE_DATA) {
|
|
2479
|
+
var err = new Error('Pica: cannot use getImageData on canvas, ' + "make sure fingerprinting protection isn't enabled");
|
|
2480
|
+
err.code = 'ERR_GET_IMAGE_DATA';
|
|
2481
|
+
throw err;
|
|
2246
2482
|
} //
|
|
2247
2483
|
// No easy way, let's resize manually via arrays
|
|
2248
2484
|
//
|
|
@@ -2258,7 +2494,16 @@ Pica.prototype.resize = function (from, to, options) {
|
|
|
2258
2494
|
Pica.prototype.resizeBuffer = function (options) {
|
|
2259
2495
|
var _this7 = this;
|
|
2260
2496
|
|
|
2261
|
-
var opts = assign({}, DEFAULT_RESIZE_OPTS, options);
|
|
2497
|
+
var opts = assign({}, DEFAULT_RESIZE_OPTS, options); // Legacy `.quality` option
|
|
2498
|
+
|
|
2499
|
+
if (Object.prototype.hasOwnProperty.call(opts, 'quality')) {
|
|
2500
|
+
if (opts.quality < 0 || opts.quality > 3) {
|
|
2501
|
+
throw new Error("Pica: .quality should be [0..3], got ".concat(opts.quality));
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
opts.filter = filter_info.q2f[opts.quality];
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2262
2507
|
return this.init().then(function () {
|
|
2263
2508
|
return _this7.__mathlib.resizeAndUnsharp(opts);
|
|
2264
2509
|
});
|
|
@@ -2301,5 +2546,5 @@ Pica.prototype.debug = function () {};
|
|
|
2301
2546
|
|
|
2302
2547
|
module.exports = Pica;
|
|
2303
2548
|
|
|
2304
|
-
},{"./lib/mathlib":1,"./lib/pool":13,"./lib/stepper":14,"./lib/tiler":15,"./lib/utils":16,"./lib/worker":17,"object-assign":
|
|
2549
|
+
},{"./lib/mathlib":1,"./lib/mm_resize/resize_filter_info":7,"./lib/pool":13,"./lib/stepper":14,"./lib/tiler":15,"./lib/utils":16,"./lib/worker":17,"object-assign":22,"webworkify":23}]},{},[])("/index.js")
|
|
2305
2550
|
});
|