@e-mc/image 0.1.0 → 0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e-mc/image",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Image constructor for E-mc.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -20,9 +20,7 @@
20
20
  "license": "BSD 3-Clause",
21
21
  "homepage": "https://github.com/anpham6/e-mc#readme",
22
22
  "dependencies": {
23
- "@e-mc/core": "0.1.0",
24
- "@e-mc/types": "0.1.0",
25
- "bmp-js": "^0.1.0",
26
- "jimp": "^0.22.7"
23
+ "@e-mc/core": "0.2.0",
24
+ "@e-mc/types": "0.2.0"
27
25
  }
28
26
  }
package/types/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ /// <reference path="../../types/index.d.ts" />
2
+
1
3
  export interface ImageHandler<T, U, V> {
2
4
  readonly handler: T;
3
5
  host: U | null;
package/jimp/image.d.ts DELETED
@@ -1,19 +0,0 @@
1
- import type { IHost, IImage, ImageConstructor } from '../../types/lib';
2
-
3
- import type { ImageHandler } from '../types';
4
-
5
- // @ts-ignore
6
- import type * as jimp from 'jimp';
7
-
8
- export interface IJimpHandler<T extends IHost = IHost> extends ImageHandler<jimp, T, IImage<T>> {
9
- method(): Promise<void>;
10
- rotate(localFile?: string, callback?: ResultCallback<string>): Promise<this>;
11
- background(value: number | [number, number, number, number]): void;
12
- writeAsync(output: string, callback?: ResultCallback): Promise<void>;
13
- }
14
-
15
- export interface JimpImageConstructor extends ImageConstructor {
16
- new(handler: jimp, instance: IImage, host?: Null<IHost>): IJimpHandler;
17
- }
18
-
19
- export type ResultCallback<T = unknown, U = void, V = unknown> = (err: V, result: T) => U;
package/jimp/index.d.ts DELETED
@@ -1,5 +0,0 @@
1
- import type { JimpImageConstructor } from './image';
2
-
3
- declare const Jimp: JimpImageConstructor;
4
-
5
- export = Jimp;
package/jimp/index.js DELETED
@@ -1,998 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const path = require("path");
4
- const fs = require("fs");
5
- const child_process = require("child_process");
6
- const jimp = require("jimp");
7
- const bmp = require("bmp-js");
8
- const types_1 = require("../../types");
9
- const index_1 = require("../index");
10
- const util_1 = require("./util");
11
- const CACHE_TRANSFORM = {};
12
- let CACHE_INIT = false;
13
- let TEMP_DIR = '';
14
- const METHOD_ALIAS = {
15
- contain: 'ct',
16
- cover: 'cv',
17
- resize: 're',
18
- scale: 'sc',
19
- scaleToFit: 'sf',
20
- autocrop: 'au',
21
- crop: 'cr',
22
- blit: 'bt',
23
- composite: 'cp',
24
- mask: 'ma',
25
- convolute: 'cl',
26
- flip: 'fl',
27
- mirror: 'mi',
28
- rotate: 'ro',
29
- brightness: 'br',
30
- contrast: 'cn',
31
- dither565: 'dt',
32
- greyscale: 'gr',
33
- invert: 'in',
34
- normalize: 'no',
35
- fade: 'fa',
36
- opacity: 'op',
37
- opaque: 'oq',
38
- background: 'bg',
39
- gaussian: 'ga',
40
- blur: 'bl',
41
- posterize: 'po',
42
- sepia: 'se',
43
- pixelate: 'px',
44
- displace: 'dp',
45
- color: 'co'
46
- };
47
- function getMethodName(value) {
48
- const name = value.toLowerCase();
49
- if (METHOD_ALIAS[name]) {
50
- return name;
51
- }
52
- if (name.length === 2) {
53
- for (const alias in METHOD_ALIAS) {
54
- if (METHOD_ALIAS[alias] === name) {
55
- return alias;
56
- }
57
- }
58
- }
59
- }
60
- function performCommand(host, instance, localUri, command, outputType, finalAs, buffer, parent) {
61
- return jimp.read((buffer || localUri))
62
- .then(img => {
63
- return transformCommand(localUri, new JimpHandler(img, instance, host), command, outputType, finalAs, parent);
64
- });
65
- }
66
- async function transformCommand(localFile, handler, command, outputType, outputAs, parent) {
67
- if (command) {
68
- handler.instance.setCommand(command, outputAs);
69
- }
70
- await handler.method();
71
- handler.resize();
72
- handler.crop();
73
- if (outputType === jimp.MIME_JPEG) {
74
- if (!outputAs) {
75
- handler.quality();
76
- }
77
- }
78
- else {
79
- handler.opacity();
80
- }
81
- switch (handler.rotateCount) {
82
- case 0:
83
- return handler;
84
- case 1:
85
- return handler.rotate();
86
- default:
87
- return handler.rotate(localFile, (err, result) => {
88
- if (!err && handler.host) {
89
- try {
90
- handler.host.add(result, parent);
91
- }
92
- catch {
93
- }
94
- }
95
- });
96
- }
97
- }
98
- function setImageCache(tempKey, tempFile, output, localFile) {
99
- try {
100
- if (typeof output === 'string') {
101
- fs.copyFileSync(output, tempFile);
102
- }
103
- else {
104
- fs.writeFileSync(tempFile, output);
105
- }
106
- const stored = getCacheData.call(this);
107
- const lastAccessed = Date.now();
108
- if (localFile) {
109
- const { mtimeMs, size } = fs.statSync(localFile);
110
- stored[tempKey] = { tempKey, tempFile, lastAccessed, localFile, mtimeMs, size };
111
- }
112
- else {
113
- stored[tempKey] = { tempKey, tempFile, lastAccessed };
114
- }
115
- writeImageData.call(this, tempFile, stored[tempKey]);
116
- }
117
- catch {
118
- TEMP_DIR = '';
119
- }
120
- }
121
- function getImageCache(tempKey) {
122
- const stored = getCacheData.call(this);
123
- const data = stored[tempKey];
124
- if (data) {
125
- const { tempFile, localFile, mtimeMs, size } = data;
126
- try {
127
- data.lastAccessed = Date.now();
128
- writeImageData.call(this, tempFile, data);
129
- if (!localFile) {
130
- return [fs.readFileSync(tempFile)];
131
- }
132
- const stat = fs.statSync(localFile);
133
- if (stat.mtimeMs === mtimeMs && stat.size === size) {
134
- return [fs.readFileSync(tempFile)];
135
- }
136
- }
137
- catch {
138
- TEMP_DIR = '';
139
- }
140
- removeFile(tempFile);
141
- delete stored[tempKey];
142
- }
143
- TEMP_DIR || (TEMP_DIR = this.getTempDir({ moduleDir: true, increment: 5 }));
144
- return [null, TEMP_DIR ? path.join(TEMP_DIR, (0, types_1.generateUUID)()) : ''];
145
- }
146
- function writeImageData(tempFile, data) {
147
- if (this.settings.jimp.cache_expires) {
148
- queueMicrotask(() => {
149
- fs.writeFile(tempFile + '.json', JSON.stringify(data), 'utf-8', () => { });
150
- });
151
- }
152
- }
153
- function getCacheData() {
154
- var _a;
155
- if (!CACHE_INIT) {
156
- TEMP_DIR = this.getTempDir({ moduleDir: true, increment: 5 });
157
- const settings = (_a = this.settings).jimp || (_a.jimp = {});
158
- const expires = (0, types_1.parseExpires)(settings.cache_expires || 0);
159
- if (expires === 0) {
160
- settings.cache_expires = 0;
161
- }
162
- if (TEMP_DIR) {
163
- if (expires === 0) {
164
- index_1.default.removeDir(TEMP_DIR, true);
165
- }
166
- else {
167
- const current = Date.now();
168
- try {
169
- fs.readdirSync(TEMP_DIR, { withFileTypes: true }).forEach(item => {
170
- if (item.isFile() && item.name.endsWith('.json')) {
171
- const pathname = path.join(TEMP_DIR, item.name);
172
- try {
173
- const data = JSON.parse(fs.readFileSync(pathname, 'utf-8'));
174
- if ((0, types_1.isPlainObject)(data) && fs.existsSync(data.tempFile)) {
175
- if (data.lastAccessed + expires > current) {
176
- CACHE_TRANSFORM[data.tempKey] = data;
177
- return;
178
- }
179
- removeFile(data.tempFile);
180
- }
181
- }
182
- catch {
183
- }
184
- removeFile(pathname);
185
- }
186
- });
187
- }
188
- catch {
189
- }
190
- }
191
- }
192
- CACHE_INIT = true;
193
- }
194
- return CACHE_TRANSFORM;
195
- }
196
- function formatMessage(value, cacheFile, startTime, failed) {
197
- if (cacheFile) {
198
- this.formatMessage(2048 /* LOG_TYPE.IMAGE */, "jimp" /* STRINGS.MODULE_NAME */, [value, 'cache'], cacheFile, { ...index_1.default.LOG_STYLE_NOTICE, hintBold: true });
199
- }
200
- else {
201
- this.writeTimeProcess("jimp" /* STRINGS.MODULE_NAME */, value, startTime, { type: 2048 /* LOG_TYPE.IMAGE */, failed });
202
- }
203
- }
204
- function getTempPath(ext) {
205
- const tempDir = TEMP_DIR || this.getTempDir({ moduleDir: true, createDir: true }) || this.getTempDir();
206
- return path.join(tempDir, (0, types_1.generateUUID)() + '.' + ext);
207
- }
208
- const removeFile = (pathname) => fs.unlink(pathname, () => { });
209
- class JimpHandler {
210
- constructor(handler, instance, host) {
211
- this.handler = handler;
212
- this.instance = instance;
213
- this._host = null;
214
- if (host) {
215
- this._host = host;
216
- }
217
- }
218
- async rotate(localFile, callback) {
219
- if (this.aborted) {
220
- return this;
221
- }
222
- const data = this.instance.rotateData;
223
- if (data) {
224
- const { values, color } = data;
225
- const handler = this.handler;
226
- if (!isNaN(color)) {
227
- handler.background(color);
228
- }
229
- const tasks = [];
230
- const length = values.length;
231
- const deg = values[0];
232
- if (length > 1 && localFile) {
233
- const leading = localFile.substring(0, localFile.lastIndexOf('.') + 1);
234
- const ext = path.extname(localFile);
235
- for (let i = 1; i < length; ++i) {
236
- const value = values[i];
237
- const img = handler.clone().rotate(value);
238
- const output = leading + value + ext;
239
- tasks.push(img.writeAsync(output)
240
- .then(() => this.finalize(output, callback))
241
- .catch(err => this.instance.writeFail(["Unable to rotate image" /* ERR_IMAGE.ROTATE */, "jimp" /* STRINGS.MODULE_NAME */], err, 2048 /* LOG_TYPE.IMAGE */)));
242
- }
243
- }
244
- if (deg) {
245
- handler.rotate(deg);
246
- }
247
- if (tasks.length) {
248
- return Promise.all(tasks).then(() => this);
249
- }
250
- }
251
- return this;
252
- }
253
- async method() {
254
- if (this.aborted) {
255
- return;
256
- }
257
- const data = this.instance.methodData;
258
- if (data) {
259
- const handler = this.handler;
260
- for (const [name, args = []] of data) {
261
- try {
262
- const alias = getMethodName(name);
263
- if (!alias) {
264
- throw (0, types_1.errorValue)("Invalid method name" /* ERR_IMAGE.METHOD_NAME */, name);
265
- }
266
- if (alias === 'composite') {
267
- const [src, x, y, opts] = args;
268
- if ((0, types_1.isString)(src) && typeof x === 'number' && typeof y === 'number') {
269
- handler.composite(await jimp.read(src), x, y, opts);
270
- }
271
- else {
272
- throw (0, types_1.errorValue)("Invalid parameters" /* ERR_MESSAGE.PARAMETERS */, alias);
273
- }
274
- }
275
- else {
276
- handler[alias](...args);
277
- }
278
- }
279
- catch (err) {
280
- this.instance.writeFail(["Unknown" /* ERR_MESSAGE.UNKNOWN */, "jimp" /* STRINGS.MODULE_NAME */ + ': ' + name], err, 2048 /* LOG_TYPE.IMAGE */);
281
- }
282
- }
283
- }
284
- }
285
- resize() {
286
- if (this.aborted) {
287
- return;
288
- }
289
- const data = this.instance.resizeData;
290
- if (data) {
291
- const { width, height, color, algorithm, align, mode } = data;
292
- const handler = this.handler;
293
- if (!isNaN(color)) {
294
- handler.background(color);
295
- }
296
- let resizeMode = jimp.RESIZE_NEAREST_NEIGHBOR, flags = 0;
297
- switch (algorithm) {
298
- case 'bilinear':
299
- resizeMode = jimp.RESIZE_BILINEAR;
300
- break;
301
- case 'bicubic':
302
- resizeMode = jimp.RESIZE_BICUBIC;
303
- break;
304
- case 'hermite':
305
- resizeMode = jimp.RESIZE_HERMITE;
306
- break;
307
- case 'bezier':
308
- resizeMode = jimp.RESIZE_BEZIER;
309
- break;
310
- }
311
- switch (align[0]) {
312
- case 'left':
313
- flags |= jimp.HORIZONTAL_ALIGN_LEFT;
314
- break;
315
- case 'center':
316
- flags |= jimp.HORIZONTAL_ALIGN_CENTER;
317
- break;
318
- case 'right':
319
- flags |= jimp.HORIZONTAL_ALIGN_RIGHT;
320
- break;
321
- }
322
- switch (align[1]) {
323
- case 'top':
324
- flags |= jimp.VERTICAL_ALIGN_TOP;
325
- break;
326
- case 'middle':
327
- flags |= jimp.VERTICAL_ALIGN_MIDDLE;
328
- break;
329
- case 'bottom':
330
- flags |= jimp.VERTICAL_ALIGN_BOTTOM;
331
- break;
332
- }
333
- switch (mode) {
334
- case 'contain':
335
- handler.contain(width, height, flags);
336
- break;
337
- case 'cover':
338
- handler.cover(width, height, flags);
339
- break;
340
- case 'scale':
341
- handler.scaleToFit(width, height);
342
- break;
343
- default:
344
- handler.resize(width === Infinity ? jimp.AUTO : width, height === Infinity ? jimp.AUTO : height, resizeMode);
345
- break;
346
- }
347
- }
348
- }
349
- background(value) {
350
- if (Array.isArray(value)) {
351
- value = parseInt('0x' + value.map(item => item.toString(16)).join(''), 16);
352
- }
353
- this.handler.background(value);
354
- }
355
- finalize(output, callback) {
356
- var _a;
357
- if (this.aborted) {
358
- return;
359
- }
360
- const instance = this.instance;
361
- if (instance.outputAs === 'webp' && path.extname(output).toLowerCase() !== '.webp') {
362
- const webp = (_a = instance.settings).webp || (_a.webp = {});
363
- const data = instance.qualityData;
364
- const replace = instance.getCommand().indexOf('@') !== -1;
365
- const filename = (0, util_1.renameExt)(output, 'webp', replace);
366
- const args = [(0, util_1.normalizePath)(output)];
367
- if (data) {
368
- const { value, preset, nearLossless } = data;
369
- if (preset) {
370
- args.push('-preset', preset);
371
- }
372
- if (value > 100) {
373
- args.push('-lossless');
374
- }
375
- else if (value >= 0) {
376
- args.push('-q', value.toString());
377
- }
378
- if (nearLossless >= 0) {
379
- args.push('-near_lossless', Math.min(nearLossless, 100).toString());
380
- }
381
- }
382
- if (Array.isArray(webp.cwebp)) {
383
- for (let i = 0; i < webp.cwebp.length; ++i) {
384
- const arg = webp.cwebp[i];
385
- switch (arg) {
386
- case '-h':
387
- case '-H':
388
- case '-version':
389
- continue;
390
- case '-o':
391
- case '--':
392
- ++i;
393
- break;
394
- case '-preset':
395
- case '-q':
396
- case '-near_lossless':
397
- if (args.includes(arg) || arg !== '-preset' && args.includes('-lossless')) {
398
- ++i;
399
- break;
400
- }
401
- default:
402
- args.push(arg);
403
- break;
404
- }
405
- }
406
- }
407
- args.push('-o', (0, util_1.normalizePath)(filename));
408
- try {
409
- child_process.execFile((0, util_1.getWebP_bin)('cwebp', webp.path), args, { shell: true, signal: this.instance.signal }, err => {
410
- if (err) {
411
- this.instance.writeFail(["Unable to convert file" /* ERR_MESSAGE.CONVERT_FILE */, path.basename(filename)], err, 2048 /* LOG_TYPE.IMAGE */);
412
- }
413
- else if (webp !== output) {
414
- const tempFile = output;
415
- queueMicrotask(() => {
416
- fs.unlink(tempFile, error => !error && fs.rmdir(path.dirname(tempFile), () => { }));
417
- });
418
- output = filename;
419
- }
420
- if (callback) {
421
- callback(err, output);
422
- }
423
- });
424
- }
425
- catch (err) {
426
- this.instance.checkPackage(err, 'cwebp-bin@6.1.2', "Unknown" /* ERR_MESSAGE.UNKNOWN */, { type: 2048 /* LOG_TYPE.IMAGE */, passThrough: !!callback });
427
- if (callback) {
428
- callback(err, '');
429
- }
430
- }
431
- }
432
- else if (callback) {
433
- callback(null, output);
434
- }
435
- }
436
- getBuffer(tempFile, saveAs) {
437
- const empty = () => tempFile ? '' : null;
438
- const output = getTempPath.call(this.instance, this.instance.outputAs || (saveAs && util_1.MIME_OUTPUT.has('image/' + (saveAs === 'jpg' ? 'jpeg' : saveAs)) ? saveAs : this.handler.getMIME().split('/').pop()));
439
- return !output ? Promise.resolve(empty()) : new Promise(resolve => {
440
- this.handler.write(output, error => {
441
- if (error) {
442
- resolve(empty());
443
- return;
444
- }
445
- this.finalize(output, (error, result) => {
446
- if (error) {
447
- resolve(empty());
448
- }
449
- else if (tempFile) {
450
- resolve(output);
451
- }
452
- else {
453
- try {
454
- resolve(fs.readFileSync(result));
455
- }
456
- catch (err) {
457
- this.instance.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(result)], err, 32 /* LOG_TYPE.FILE */);
458
- resolve(null);
459
- }
460
- queueMicrotask(() => fs.unlink(result, err => !err && this.instance.emit('file:delete', result)));
461
- }
462
- });
463
- });
464
- });
465
- }
466
- crop() {
467
- if (this.aborted) {
468
- return;
469
- }
470
- const data = this.instance.cropData;
471
- if (data) {
472
- this.handler = this.handler.crop(data.x, data.y, data.width, data.height);
473
- }
474
- }
475
- opacity() {
476
- if (this.aborted) {
477
- return;
478
- }
479
- const value = this.instance.opacityValue ?? NaN;
480
- if (value >= 0) {
481
- this.handler = this.handler.opacity(value);
482
- }
483
- }
484
- quality() {
485
- if (this.aborted) {
486
- return;
487
- }
488
- const data = this.instance.qualityData;
489
- if (data && !isNaN(data.value)) {
490
- this.handler = this.handler.quality(data.value);
491
- }
492
- }
493
- write(output, callback) {
494
- if (this.aborted) {
495
- if (callback) {
496
- callback((0, types_1.createAbortError)(), '');
497
- }
498
- return;
499
- }
500
- this.handler.write(output, err => {
501
- if (!err) {
502
- this.finalize(output, callback);
503
- }
504
- else if (callback) {
505
- callback(err, '');
506
- }
507
- });
508
- }
509
- writeAsync(output, callback) {
510
- if (this.aborted) {
511
- if (callback) {
512
- callback((0, types_1.createAbortError)(), '');
513
- }
514
- return Promise.resolve();
515
- }
516
- return this.handler.writeAsync(output)
517
- .then(() => this.finalize(output, callback))
518
- .catch(err => {
519
- if (callback) {
520
- callback(err, '');
521
- }
522
- else {
523
- this.instance.writeFail(["Unable to write file" /* ERR_MESSAGE.WRITE_FILE */, path.basename(output)], err, 2048 /* LOG_TYPE.IMAGE */);
524
- }
525
- });
526
- }
527
- get host() {
528
- return this._host || this.instance.host;
529
- }
530
- get aborted() {
531
- return this.instance.aborted;
532
- }
533
- get rotateCount() {
534
- return this.instance.rotateData?.values.length || 0;
535
- }
536
- }
537
- class Jimp extends index_1.default {
538
- constructor() {
539
- super(...arguments);
540
- this._moduleName = "jimp" /* STRINGS.MODULE_NAME */;
541
- this._threadable = true;
542
- }
543
- static async transform(file, command, options = {}) {
544
- const [outputType, saveAs, finalAs] = (0, util_1.parseFormat)(command = command.trim(), options.mimeType);
545
- const empty = () => options.tempFile ? '' : null;
546
- if (outputType) {
547
- const instance = new Jimp(options.module);
548
- let buffer = null;
549
- if (Buffer.isBuffer(file)) {
550
- const tempDir = TEMP_DIR || instance.getTempDir();
551
- if (!this.createDir(tempDir)) {
552
- return empty();
553
- }
554
- try {
555
- const { ext } = await this.resolveMime(file) || { ext: 'unknown' };
556
- buffer = file;
557
- fs.writeFileSync(file = path.join(tempDir, (0, types_1.generateUUID)() + '.' + ext), buffer);
558
- }
559
- catch {
560
- return empty();
561
- }
562
- options.cache = false;
563
- }
564
- const filename = path.basename(file);
565
- const broadcastId = options.broadcastId;
566
- if (broadcastId) {
567
- if ((0, types_1.isPlainObject)(broadcastId)) {
568
- instance.broadcastId = broadcastId.value;
569
- if (broadcastId.stripAnsi === false) {
570
- instance.supports('stripAnsi', false);
571
- }
572
- }
573
- else {
574
- instance.broadcastId = broadcastId;
575
- }
576
- }
577
- const writeMessage = (cache, failed) => {
578
- if (options.startTime) {
579
- formatMessage.call(instance, filename + (0, util_1.showOutputType)(options.mimeType, outputType, finalAs), cache ? file : '', options.startTime, failed);
580
- }
581
- };
582
- let tempKey, tempFile;
583
- if (options.cache) {
584
- [buffer, tempFile] = getImageCache.call(instance, tempKey = file + command + (options.mimeType || ''));
585
- if (buffer) {
586
- writeMessage(true, false);
587
- return Promise.resolve(buffer);
588
- }
589
- }
590
- instance.formatMessage(index_1.default.LOG_TYPE.IMAGE, "jimp" /* STRINGS.MODULE_NAME */, ["Transforming image..." /* STRINGS.TRANSFORM */, filename], command);
591
- index_1.default.initCpuUsage(instance);
592
- return performCommand(null, instance, file, command, outputType, finalAs)
593
- .then(async (handler) => {
594
- const result = await handler.getBuffer(options.tempFile, saveAs);
595
- instance.flushLog();
596
- writeMessage(false, !result || instance.errors.length > 0);
597
- if (result && tempKey && tempFile) {
598
- setImageCache.call(instance, tempKey, tempFile, result, file);
599
- }
600
- return result;
601
- })
602
- .catch(() => empty())
603
- .finally(() => buffer && !options.cache && removeFile(file));
604
- }
605
- return empty();
606
- }
607
- parseRotate(value) {
608
- const data = super.parseRotate(value);
609
- if (data && this.settings.jimp?.rotate_clockwise) {
610
- const values = data.values;
611
- for (let i = 0; i < values.length; ++i) {
612
- values[i] *= -1;
613
- }
614
- }
615
- return data;
616
- }
617
- async using(data, command) {
618
- if (this.aborted) {
619
- return Promise.reject((0, types_1.createAbortError)());
620
- }
621
- return new Promise(async (resolve, reject) => {
622
- var _a;
623
- const { host, file } = data;
624
- const localUri = host.getLocalUri(data);
625
- const mimeType = host.getMimeType(data);
626
- if (!localUri || !util_1.MIME_INPUT.has(mimeType)) {
627
- reject((0, types_1.errorValue)("Unknown" /* ERR_MESSAGE.UNKNOWN */, !localUri ? 'URI' : 'MIME'));
628
- return;
629
- }
630
- if (!this.canRead(localUri, { ownPermissionOnly: true })) {
631
- reject((0, types_1.errorValue)("Not permitted to read file" /* ERR_MESSAGE.UNSUPPORTED_READ */, localUri));
632
- return;
633
- }
634
- const [outputType, saveAs, finalAs] = (0, util_1.parseFormat)(command = command.trim(), mimeType, true);
635
- if (!outputType) {
636
- reject((0, types_1.errorValue)("Invalid format" /* ERR_MESSAGE.FORMAT */, /^\w+/.exec(command)?.[0] || "Unknown" /* ERR_MESSAGE.UNKNOWN */));
637
- return;
638
- }
639
- const replace = command.indexOf('@') !== -1;
640
- const output = host.addCopy(data.getObject({ command, outputType }), saveAs, replace);
641
- if (!output) {
642
- reject((0, types_1.errorValue)("Not able to copy file" /* ERR_MESSAGE.NOT_COPYABLE */, outputType));
643
- return;
644
- }
645
- if (!this.canWrite(output, { ownPermissionOnly: true })) {
646
- reject((0, types_1.errorValue)("Not permitted to write file" /* ERR_MESSAGE.UNSUPPORTED_WRITE */, output));
647
- return;
648
- }
649
- const startTime = process.hrtime();
650
- const success = (result, cache) => {
651
- const filename = path.basename(result);
652
- if (file.document) {
653
- host.writeImage(file.document, data.getObject({ command, output: result }));
654
- }
655
- if (host.getLocalUri(data) !== result) {
656
- if (command.indexOf('%') !== -1) {
657
- const files = host.filesToCompare.get(file);
658
- if (files) {
659
- files.push(result);
660
- }
661
- else {
662
- host.filesToCompare.set(file, [result]);
663
- }
664
- }
665
- else if (replace) {
666
- host.replace(file, result);
667
- }
668
- else {
669
- host.add(result, file);
670
- }
671
- }
672
- if (replace && file.localUri !== output && !host.assets.find(item => item.localUri === output && !item.invalid)) {
673
- host.filesToRemove.add(output);
674
- }
675
- formatMessage.call(this, (0, util_1.showInputType)(mimeType, outputType, finalAs) + filename, cache ? result : '', startTime, false);
676
- resolve();
677
- };
678
- let tempKey, tempFile;
679
- if (this.settings.cache && (file.etag || file.buffer)) {
680
- let buffer;
681
- [buffer, tempFile] = getImageCache.call(this, tempKey = (file.etag || index_1.default.asHash(file.buffer)) + command + mimeType);
682
- if (buffer) {
683
- const result = finalAs === 'webp' ? (0, util_1.renameExt)(output, 'webp', replace) : output;
684
- fs.writeFileSync(result, file.buffer = buffer);
685
- success(result, true);
686
- return;
687
- }
688
- }
689
- const finalize = (value) => {
690
- if (tempFile && tempKey) {
691
- setImageCache.call(this, tempKey, tempFile, value);
692
- }
693
- if (replace) {
694
- delete file.buffer;
695
- }
696
- success(value, false);
697
- };
698
- const transformBuffer = (bmpFile) => {
699
- startMessage();
700
- performCommand(host, this, localUri, command, outputType, finalAs, bmpFile || file.buffer, file)
701
- .then((img) => {
702
- if (typeof bmpFile === 'string') {
703
- removeFile(bmpFile);
704
- }
705
- const errorResponse = (err) => {
706
- this.writeFail(["Unable to finalize image" /* ERR_IMAGE.FINALIZE */, "jimp" /* STRINGS.MODULE_NAME */], err, { type: 2048 /* LOG_TYPE.IMAGE */, startTime });
707
- resolve();
708
- };
709
- if (outputType === jimp.MIME_GIF) {
710
- try {
711
- const { GifUtil, GifFrame } = require('gifwrap');
712
- const frame = new GifFrame(img.handler.bitmap);
713
- GifUtil.quantizeSorokin(frame, 256);
714
- GifUtil.write(output, [frame])
715
- .then(() => finalize(output))
716
- .catch(err => errorResponse(err));
717
- }
718
- catch (err) {
719
- if (this.checkPackage(err, 'gifwrap', 2048 /* LOG_TYPE.IMAGE */)) {
720
- resolve();
721
- }
722
- else {
723
- errorResponse(err);
724
- }
725
- }
726
- }
727
- else {
728
- img.write(output, (err, result) => {
729
- if (!err && result) {
730
- finalize(result);
731
- }
732
- else {
733
- errorResponse(err || new Error("Unknown" /* ERR_MESSAGE.UNKNOWN */));
734
- }
735
- });
736
- }
737
- })
738
- .catch(err => {
739
- this.writeFail(["Unable to read buffer" /* ERR_MESSAGE.READ_BUFFER */, path.basename(localUri)], err, { type: 2048 /* LOG_TYPE.IMAGE */, startTime });
740
- resolve();
741
- });
742
- };
743
- const errorResponse = (err) => {
744
- this.writeFail(["Unable to convert file" /* ERR_MESSAGE.CONVERT_FILE */, path.basename(localUri)], err, { type: 2048 /* LOG_TYPE.IMAGE */, startTime });
745
- resolve();
746
- };
747
- const rotateAnim = (cmd) => {
748
- const rotate = cmd.rotate;
749
- if (rotate) {
750
- rotate.values = [rotate.values.pop()];
751
- }
752
- };
753
- const hasTransform = (cmd) => !!(cmd.rotate || cmd.opacity >= 0 && cmd.opacity < 1 || cmd.resize || cmd.crop || cmd.method);
754
- const startMessage = () => host.formatMessage(2048 /* LOG_TYPE.IMAGE */, "jimp" /* STRINGS.MODULE_NAME */, ["Transforming image..." /* STRINGS.TRANSFORM */, path.basename(localUri)], command);
755
- if (mimeType === jimp.MIME_GIF) {
756
- if (outputType === jimp.MIME_GIF || outputType === "image/webp" /* STRINGS.MIME_WEBP */) {
757
- const cmd = this.parseCommand(command);
758
- const transformWebP = (target, modified) => {
759
- var _a;
760
- if (finalAs === 'webp') {
761
- if (!modified) {
762
- startMessage();
763
- }
764
- const { path: webp_path, gif2webp } = (_a = this.settings).webp || (_a.webp = {});
765
- const webp = (0, util_1.renameExt)(output, 'webp', replace);
766
- const args = [(0, util_1.normalizePath)(target)];
767
- const quality = cmd.quality;
768
- if (quality) {
769
- if (!isNaN(quality.value)) {
770
- args.push('-q', quality.value.toString());
771
- }
772
- if (!isNaN(quality.method)) {
773
- args.push('-m', quality.method.toString());
774
- }
775
- }
776
- if (Array.isArray(gif2webp)) {
777
- for (let i = 0, length = gif2webp.length; i < length; ++i) {
778
- const arg = gif2webp[i];
779
- switch (arg) {
780
- case '-h':
781
- case '-version':
782
- continue;
783
- case '-o':
784
- ++i;
785
- continue;
786
- case '-q':
787
- case '-m':
788
- if (args.includes(arg)) {
789
- ++i;
790
- continue;
791
- }
792
- break;
793
- case '--':
794
- i = length;
795
- continue;
796
- }
797
- args.push(arg);
798
- }
799
- }
800
- args.push('-o', (0, util_1.normalizePath)(webp));
801
- try {
802
- child_process.execFile((0, util_1.getWebP_bin)('gif2webp', webp_path), args, { shell: true, signal: this.signal }, (err, stdout) => {
803
- if (!err) {
804
- this.addLog(types_1.STATUS_TYPE.INFO, stdout);
805
- finalize(webp);
806
- }
807
- else {
808
- errorResponse(err);
809
- }
810
- });
811
- }
812
- catch (err) {
813
- if (this.checkPackage(err, 'gif2webp-bin@3', 2048 /* LOG_TYPE.IMAGE */)) {
814
- resolve();
815
- }
816
- else {
817
- errorResponse(err);
818
- }
819
- }
820
- }
821
- else if (modified) {
822
- finalize(output);
823
- }
824
- else {
825
- resolve();
826
- }
827
- };
828
- if (hasTransform(cmd)) {
829
- try {
830
- startMessage();
831
- const { GifUtil, BitmapImage } = require('gifwrap');
832
- GifUtil.read(file.buffer || localUri)
833
- .then(gif => {
834
- rotateAnim(cmd);
835
- Promise.all(gif.frames.map(frame => {
836
- const handler = new JimpHandler(GifUtil.shareAsJimp(jimp, frame), this);
837
- return transformCommand(localUri, handler, cmd, jimp.MIME_GIF);
838
- }))
839
- .then(items => {
840
- const frames = gif.frames;
841
- for (let i = 0, length = items.length; i < length; ++i) {
842
- const img = new BitmapImage(items[i].handler.bitmap);
843
- GifUtil.quantizeSorokin(img, 256);
844
- frames[i].bitmap = img.bitmap;
845
- }
846
- GifUtil.write(output, frames, gif)
847
- .then(() => transformWebP(output, true))
848
- .catch(err => errorResponse(err));
849
- })
850
- .catch(err => errorResponse(err));
851
- })
852
- .catch(err => errorResponse(err));
853
- }
854
- catch (err) {
855
- if (this.checkPackage(err, 'gifwrap', 2048 /* LOG_TYPE.IMAGE */)) {
856
- resolve();
857
- }
858
- else {
859
- errorResponse(err);
860
- }
861
- }
862
- }
863
- else {
864
- transformWebP(localUri, false);
865
- }
866
- }
867
- else {
868
- transformBuffer();
869
- }
870
- }
871
- else if (mimeType === "image/webp" /* STRINGS.MIME_WEBP */) {
872
- const tryWebpMux = async () => {
873
- let loaded;
874
- try {
875
- const webp = new (require('node-webpmux').Image)();
876
- loaded = true;
877
- if (index_1.default.supported(18, 1)) {
878
- this.formatMessage(2048 /* LOG_TYPE.IMAGE */, 'WARN', 'node-webpmux is not compatible with global fetch', 'NodeJS: --no-experimental-fetch', { ...index_1.default.LOG_STYLE_WARN });
879
- }
880
- await webp.initLib();
881
- await webp.load(host.getBuffer(file));
882
- if (!(webp.hasAnim && (outputType === "image/webp" /* STRINGS.MIME_WEBP */ || outputType === jimp.MIME_GIF))) {
883
- transformBuffer(bmp.encode({ width: webp.width, height: webp.height, data: index_1.default.toABGR(await (!webp.hasAnim ? webp.getImageData() : webp.getFrameData(0))) }).data);
884
- return true;
885
- }
886
- const cmd = this.parseCommand(command);
887
- if (hasTransform(cmd)) {
888
- startMessage();
889
- Promise.all(webp.frames.map(async (frame, index) => {
890
- const handler = new JimpHandler(await jimp.read(bmp.encode({ width: frame.width, height: frame.height, data: index_1.default.toABGR(await webp.getFrameData(index)) }).data), this);
891
- handler.background(webp.anim.bgColor);
892
- return transformCommand(localUri, handler, cmd, jimp.MIME_BMP);
893
- }))
894
- .then(items => {
895
- const length = items.length;
896
- if (outputType === jimp.MIME_GIF) {
897
- try {
898
- const { GifFrame, GifUtil, BitmapImage } = require('gifwrap');
899
- const frames = new Array(length);
900
- for (let i = 0; i < length; ++i) {
901
- const { x, y, delay } = webp.frames[i];
902
- const img = new BitmapImage(items[i].handler.bitmap);
903
- GifUtil.quantizeSorokin(img, 256);
904
- frames[i] = new GifFrame(new BitmapImage(img), { xOffset: x, yOffset: y, delayCentisecs: delay / 10 });
905
- }
906
- GifUtil.write(output, frames, { loops: webp.anim.loops })
907
- .then(() => finalize(output))
908
- .catch(err => errorResponse(err));
909
- }
910
- catch (err) {
911
- if (this.checkPackage(err, 'gifwrap', 2048 /* LOG_TYPE.IMAGE */)) {
912
- resolve();
913
- }
914
- else {
915
- errorResponse(err);
916
- }
917
- }
918
- }
919
- else {
920
- const { value: q = NaN, method: m = NaN, preset } = cmd.quality || {};
921
- const quality = !isNaN(q) ? q : undefined;
922
- const method = !isNaN(m) ? m : undefined;
923
- rotateAnim(cmd);
924
- const frames = new Array(length);
925
- let w = 0, h = 0;
926
- for (let i = 0; i < length; ++i) {
927
- const { width, height, data: buffer } = items[i].handler.bitmap;
928
- frames[i] = webp.setFrameData(i, buffer, { width, height, quality, method, preset });
929
- w = Math.max(w, width);
930
- h = Math.max(h, height);
931
- }
932
- Promise.all(frames)
933
- .then(() => {
934
- webp.save(output, { width: w, height: h, bgColor: cmd.rotate ? [0, 0, 0, 0] : undefined })
935
- .then(() => finalize(output))
936
- .catch(err => errorResponse(err));
937
- })
938
- .catch(err => errorResponse(err));
939
- }
940
- })
941
- .catch(err => errorResponse(err));
942
- }
943
- else {
944
- resolve();
945
- }
946
- return true;
947
- }
948
- catch (err) {
949
- if (loaded) {
950
- this.writeFail(["Unknown" /* ERR_MESSAGE.UNKNOWN */, 'node-webpmux'], err, { type: 2048 /* LOG_TYPE.IMAGE */, startTime });
951
- }
952
- else if (this.checkPackage(err, 'node-webpmux@3', 2048 /* LOG_TYPE.IMAGE */)) {
953
- resolve();
954
- return true;
955
- }
956
- }
957
- return false;
958
- };
959
- const { path: webp_path } = (_a = this.settings).webp || (_a.webp = {});
960
- const bmpFile = getTempPath.call(this, 'bmp');
961
- try {
962
- child_process.execFile((0, util_1.getWebP_bin)('dwebp', webp_path), [(0, util_1.normalizePath)(localUri), '-bmp', '-o', (0, util_1.normalizePath)(bmpFile)], { shell: true, signal: this.signal }, err => {
963
- if (!err) {
964
- transformBuffer(bmpFile);
965
- }
966
- else {
967
- removeFile(bmpFile);
968
- tryWebpMux().then(valid => !valid && errorResponse(err));
969
- }
970
- });
971
- }
972
- catch (err) {
973
- if (!await tryWebpMux()) {
974
- if (this.checkPackage(err, 'dwebp-bin@1', 2048 /* LOG_TYPE.IMAGE */)) {
975
- resolve();
976
- }
977
- else {
978
- errorResponse(err);
979
- }
980
- }
981
- }
982
- }
983
- else {
984
- transformBuffer();
985
- }
986
- });
987
- }
988
- get settings() {
989
- var _a;
990
- return (_a = this.module).settings || (_a.settings = {});
991
- }
992
- }
993
- exports.default = Jimp;
994
-
995
- if (exports.default) {
996
- module.exports = exports.default;
997
- module.exports.default = exports.default;
998
- }
package/jimp/util.d.ts DELETED
@@ -1,10 +0,0 @@
1
- declare namespace util {
2
- function parseFormat(command: string, mimeType?: string, gif?: boolean): [string, string, string];
3
- function renameExt(output: string, ext: string, replace?: boolean): string;
4
- function normalizePath(value: string): string;
5
- function getWebP_bin(name: string, pathname: string | undefined): string;
6
- function showInputType(value: string | undefined, outputType: string, finalAs: string): string;
7
- function showOutputType(value: string | undefined, outputType: string, finalAs: string): string;
8
- }
9
-
10
- export = util;
package/jimp/util.js DELETED
@@ -1,95 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.showOutputType = exports.showInputType = exports.getWebP_bin = exports.normalizePath = exports.renameExt = exports.parseFormat = exports.MIME_OUTPUT = exports.MIME_INPUT = void 0;
4
- const path = require("path");
5
- const fs = require("fs");
6
- const jimp = require("jimp");
7
- const types_1 = require("../../types");
8
- const index_1 = require("../index");
9
- exports.MIME_INPUT = new Set([jimp.MIME_PNG, jimp.MIME_JPEG, jimp.MIME_BMP, jimp.MIME_GIF, jimp.MIME_TIFF, "image/webp" /* STRINGS.MIME_WEBP */]);
10
- exports.MIME_OUTPUT = new Set([jimp.MIME_PNG, jimp.MIME_JPEG, jimp.MIME_BMP, jimp.MIME_GIF, "image/webp" /* STRINGS.MIME_WEBP */]);
11
- function parseFormat(command, mimeType, gif) {
12
- command = command.toLowerCase();
13
- for (let mime of exports.MIME_OUTPUT) {
14
- let saveAs = mime.split('/')[1];
15
- if (command.startsWith(saveAs)) {
16
- let finalAs = '';
17
- if (saveAs !== 'gif') {
18
- switch (saveAs) {
19
- case 'jpeg':
20
- saveAs = 'jpg';
21
- break;
22
- case 'webp':
23
- if (mimeType === "image/webp" /* STRINGS.MIME_WEBP */) {
24
- try {
25
- require('node-webpmux');
26
- mime = "image/webp" /* STRINGS.MIME_WEBP */;
27
- break;
28
- }
29
- catch {
30
- }
31
- }
32
- if (mimeType === jimp.MIME_JPEG) {
33
- mime = jimp.MIME_JPEG;
34
- saveAs = 'jpg';
35
- }
36
- else if (gif && mimeType === jimp.MIME_GIF) {
37
- mime = jimp.MIME_GIF;
38
- saveAs = 'gif';
39
- }
40
- else {
41
- mime = jimp.MIME_PNG;
42
- saveAs = 'png';
43
- }
44
- finalAs = 'webp';
45
- break;
46
- }
47
- }
48
- else if (!gif) {
49
- break;
50
- }
51
- return [mime, saveAs, finalAs];
52
- }
53
- }
54
- return ['', '', ''];
55
- }
56
- exports.parseFormat = parseFormat;
57
- function renameExt(output, ext, replace) {
58
- let result = (0, types_1.renameExt)(output.replace('.__copy__.', '.'), ext);
59
- if (!replace) {
60
- const pathname = result;
61
- let i = 0;
62
- while (index_1.default.isPath(result)) {
63
- result = pathname.substring(0, pathname.lastIndexOf('.') + 1) + `(${++i}).` + ext;
64
- }
65
- }
66
- return result;
67
- }
68
- exports.renameExt = renameExt;
69
- function normalizePath(value) {
70
- return '"' + value.replace(/"/g, '\\"') + '"';
71
- }
72
- exports.normalizePath = normalizePath;
73
- function getWebP_bin(name, pathname) {
74
- if (pathname && fs.existsSync(pathname)) {
75
- name += process.platform === 'win32' ? '.exe' : '';
76
- const bin = path.join(pathname, name);
77
- return index_1.default.sanitizeCmd(fs.existsSync(bin) ? bin : path.join(pathname, 'bin', name));
78
- }
79
- return require(name + '-bin');
80
- }
81
- exports.getWebP_bin = getWebP_bin;
82
- function showInputType(value, outputType, finalAs) {
83
- if (finalAs) {
84
- outputType = 'image/' + finalAs;
85
- }
86
- return value && outputType !== value ? value.split('/').pop() + ' -> ' : '';
87
- }
88
- exports.showInputType = showInputType;
89
- function showOutputType(value, outputType, finalAs) {
90
- if (finalAs) {
91
- outputType = 'image/' + finalAs;
92
- }
93
- return value !== outputType ? ' -> ' + outputType.split('/').pop() : '';
94
- }
95
- exports.showOutputType = showOutputType;