@depup/sharp-cli 5.2.0-depup.0 → 6.0.0-depup.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.
Files changed (50) hide show
  1. package/.github/workflows/ci.yml +30 -0
  2. package/.prettierignore +2 -0
  3. package/.prettierrc +1 -0
  4. package/CHANGELOG.md +40 -8
  5. package/README.md +6 -9
  6. package/bin/cli.js +5 -5
  7. package/changes.json +5 -17
  8. package/cmd/channel-manipulation/bandbool.js +24 -19
  9. package/cmd/channel-manipulation/ensure-alpha.js +27 -22
  10. package/cmd/channel-manipulation/extract-channel.js +23 -19
  11. package/cmd/channel-manipulation/join-channel.js +19 -20
  12. package/cmd/channel-manipulation/remove-alpha.js +12 -15
  13. package/cmd/colour-manipulation/greyscale.js +16 -16
  14. package/cmd/colour-manipulation/pipeline-colourspace.js +26 -22
  15. package/cmd/colour-manipulation/tint.js +17 -19
  16. package/cmd/colour-manipulation/tocolourspace.js +22 -21
  17. package/cmd/compositing/composite.js +133 -102
  18. package/cmd/operations/affine.js +57 -51
  19. package/cmd/operations/blur.js +44 -41
  20. package/cmd/operations/boolean.js +22 -21
  21. package/cmd/operations/clahe.js +37 -37
  22. package/cmd/operations/convolve.js +52 -48
  23. package/cmd/operations/dilate.js +58 -0
  24. package/cmd/operations/erode.js +58 -0
  25. package/cmd/operations/flatten.js +23 -24
  26. package/cmd/operations/flip.js +12 -15
  27. package/cmd/operations/flop.js +12 -15
  28. package/cmd/operations/gamma.js +26 -25
  29. package/cmd/operations/linear.js +30 -29
  30. package/cmd/operations/median.js +18 -22
  31. package/cmd/operations/modulate.js +42 -31
  32. package/cmd/operations/negate.js +17 -20
  33. package/cmd/operations/normalise.js +28 -25
  34. package/cmd/operations/recomb.js +34 -32
  35. package/cmd/operations/rotate.js +31 -29
  36. package/cmd/operations/sharpen.js +49 -45
  37. package/cmd/operations/threshold.js +29 -29
  38. package/cmd/operations/unflatten.js +14 -16
  39. package/cmd/output.js +61 -56
  40. package/cmd/resizing/extend.js +55 -49
  41. package/cmd/resizing/extract.js +32 -33
  42. package/cmd/resizing/resize.js +79 -56
  43. package/cmd/resizing/trim.js +59 -36
  44. package/{lib/queue.js → eslint.config.mjs} +21 -17
  45. package/lib/cli.js +637 -383
  46. package/lib/constants.js +24 -18
  47. package/lib/convert.js +106 -73
  48. package/lib/index.js +56 -23
  49. package/lib/utils.js +50 -0
  50. package/package.json +27 -37
package/lib/cli.js CHANGED
@@ -21,192 +21,297 @@
21
21
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
23
 
24
- // Strict mode.
25
- 'use strict'
26
-
27
24
  // Package modules.
28
- const pick = require('lodash.pick')
29
- const sharp = require('sharp')
30
- const yargs = require('yargs')
25
+ import sharp from "sharp";
26
+ import yargs from "yargs";
31
27
 
32
28
  // Local modules.
33
- const constants = require('./constants')
34
- const pkg = require('../package.json')
35
- const queue = require('./queue')
29
+ import affine from "../cmd/operations/affine.js";
30
+ import bandbool from "../cmd/channel-manipulation/bandbool.js";
31
+ import blur from "../cmd/operations/blur.js";
32
+ import boolean from "../cmd/operations/boolean.js";
33
+ import clahe from "../cmd/operations/clahe.js";
34
+ import composite from "../cmd/compositing/composite.js";
35
+ import convolve from "../cmd/operations/convolve.js";
36
+ import dilate from "../cmd/operations/dilate.js";
37
+ import ensureAlpha from "../cmd/channel-manipulation/ensure-alpha.js";
38
+ import erode from "../cmd/operations/erode.js";
39
+ import extend from "../cmd/resizing/extend.js";
40
+ import extract from "../cmd/resizing/extract.js";
41
+ import extractChannel from "../cmd/channel-manipulation/extract-channel.js";
42
+ import flatten from "../cmd/operations/flatten.js";
43
+ import flip from "../cmd/operations/flip.js";
44
+ import flop from "../cmd/operations/flop.js";
45
+ import gamma from "../cmd/operations/gamma.js";
46
+ import greyscale from "../cmd/colour-manipulation/greyscale.js";
47
+ import joinChannel from "../cmd/channel-manipulation/join-channel.js";
48
+ import linear from "../cmd/operations/linear.js";
49
+ import median from "../cmd/operations/median.js";
50
+ import modulate from "../cmd/operations/modulate.js";
51
+ import negate from "../cmd/operations/negate.js";
52
+ import normalise from "../cmd/operations/normalise.js";
53
+ import pipelineColourspace from "../cmd/colour-manipulation/pipeline-colourspace.js";
54
+ import recomb from "../cmd/operations/recomb.js";
55
+ import removeAlpha from "../cmd/channel-manipulation/remove-alpha.js";
56
+ import resize from "../cmd/resizing/resize.js";
57
+ import rotate from "../cmd/operations/rotate.js";
58
+ import sharpen from "../cmd/operations/sharpen.js";
59
+ import threshold from "../cmd/operations/threshold.js";
60
+ import tint from "../cmd/colour-manipulation/tint.js";
61
+ import tile from "../cmd/output.js";
62
+ import toColourspace from "../cmd/colour-manipulation/tocolourspace.js";
63
+ import trim from "../cmd/resizing/trim.js";
64
+ import unflatten from "../cmd/operations/unflatten.js";
65
+ import constants from "./constants.js";
66
+ import { pick } from "./utils.js";
67
+
68
+ // Assets.
69
+ import pkg from "../package.json" with { type: "json" };
36
70
 
37
71
  // Configure.
38
- const IS_TEXT_TERMINAL = process.stdin.isTTY
72
+ const IS_TEXT_TERMINAL = process.stdin.isTTY;
39
73
 
40
74
  // Options.
41
- const global = 'Global Options'
42
- const input = 'Input Options'
43
- const optimize = 'Optimization Options'
44
- const output = 'Output Options'
75
+ const global = "Global Options";
76
+ const input = "Input Options";
77
+ const optimize = "Optimization Options";
78
+ const output = "Output Options";
45
79
 
46
80
  const globalOptions = {
81
+ dry: {
82
+ alias: "n",
83
+ desc: "Process images without writing output files",
84
+ group: global,
85
+ type: "boolean",
86
+ },
87
+
88
+ print: {
89
+ desc: "Print input and output metadata as JSON",
90
+ group: global,
91
+ implies: IS_TEXT_TERMINAL ? undefined : "dry",
92
+ type: "boolean",
93
+ },
94
+
47
95
  // @see https://sharp.pixelplumbing.com/api-constructor/
48
96
  input: {
49
- alias: 'i',
50
- defaultDescription: 'stdin',
97
+ alias: "i",
98
+ defaultDescription: "stdin",
51
99
  demand: IS_TEXT_TERMINAL,
52
- desc: 'Path to (an) image file(s)',
100
+ desc: "Path to (an) image file(s)",
53
101
  group: global,
54
- implies: 'output',
55
- type: 'array'
102
+ implies: "output",
103
+ requiresArg: true,
104
+ type: "array",
56
105
  },
57
106
 
58
107
  // @see https://sharp.pixelplumbing.com/api-output/
59
108
  output: {
60
- alias: 'o',
61
- defaultDescription: 'stdout',
109
+ alias: "o",
110
+ defaultDescription: "stdout",
62
111
  demand: IS_TEXT_TERMINAL,
63
- desc: 'Directory or URI template to write the image files to',
112
+ desc: "Directory or URI template to write the image files to",
64
113
  group: global,
65
- type: 'string'
114
+ nargs: 1,
115
+ type: "string",
66
116
  },
67
117
 
68
118
  // @see https://sharp.pixelplumbing.com/api-output#timeout
69
119
  timeout: {
70
- desc: 'Number of seconds after which processing will be stopped',
120
+ desc: "Number of seconds after which processing will be stopped",
71
121
  group: global,
72
- type: 'number'
73
- }
74
- }
122
+ nargs: 1,
123
+ type: "number",
124
+ },
125
+ };
75
126
 
76
127
  // @see https://sharp.pixelplumbing.com/api-constructor
77
- const inputOptions = {
128
+ export const inputOptions = {
78
129
  animated: {
79
- desc: 'Read all frames/pages of an animated image',
130
+ desc: "Read all frames/pages of an animated image",
80
131
  group: input,
81
- type: 'boolean'
132
+ type: "boolean",
82
133
  },
83
134
  autoOrient: {
84
- desc: 'Rotate/flip the image to match EXIF Orientation, if any',
135
+ desc: "Rotate/flip the image to match EXIF Orientation, if any",
85
136
  group: input,
86
- type: 'boolean'
87
- },
88
- failOn: {
89
- choices: constants.FAIL_ON,
90
- defaultDescription: 'warning',
91
- desc: 'Level of sensitivity to invalid images',
92
- group: input
137
+ type: "boolean",
93
138
  },
94
139
  density: {
95
- desc: 'DPI for vector images',
140
+ desc: "DPI for vector images",
96
141
  defaultDescription: 72,
97
142
  group: input,
98
- type: 'number'
143
+ nargs: 1,
144
+ type: "number",
145
+ },
146
+ failOn: {
147
+ choices: constants.FAIL_ON,
148
+ defaultDescription: "warning",
149
+ desc: "Level of sensitivity to invalid images",
150
+ group: input,
99
151
  },
100
152
  ignoreIcc: {
101
153
  default: false,
102
- desc: 'Should the embedded ICC profile, if any, be ignored',
154
+ desc: "Should the embedded ICC profile, if any, be ignored",
103
155
  group: input,
104
- type: 'boolean'
156
+ type: "boolean",
105
157
  },
106
158
  level: {
107
- desc: 'Level to extract from a multi-level input (OpenSlide), zero based',
159
+ desc: "Level to extract from a multi-level input (OpenSlide), zero based",
108
160
  defaultDescription: 0,
109
161
  group: input,
110
- type: 'number'
162
+ nargs: 1,
163
+ type: "number",
111
164
  },
112
165
  limitInputPixels: {
113
- defaultDescription: 0x3FFF * 0x3FFF,
114
- desc: 'Do not process input images where the number of pixels (width x height) exceeds this limit',
166
+ defaultDescription: 0x3fff * 0x3fff,
167
+ desc: "Do not process input images where the number of pixels (width x height) exceeds this limit",
115
168
  group: input,
116
- type: 'number'
169
+ nargs: 1,
170
+ type: "number",
171
+ },
172
+ limitInputChannels: {
173
+ defaultDescription: 5,
174
+ desc: "Do not process input images where the number of channels exceeds this limit",
175
+ group: input,
176
+ nargs: 1,
177
+ type: "number",
117
178
  },
118
179
  page: {
119
180
  defaultDescription: 0,
120
- desc: 'Page number to start extracting from for multi-page input',
181
+ desc: "Page number to start extracting from for multi-page input",
121
182
  group: input,
122
- type: 'number'
183
+ nargs: 1,
184
+ type: "number",
123
185
  },
124
186
  pages: {
125
187
  defaultDescription: 1,
126
- desc: 'Number of pages to extract for multi-page input',
188
+ desc: "Number of pages to extract for multi-page input",
127
189
  group: input,
128
- type: 'number'
190
+ nargs: 1,
191
+ type: "number",
129
192
  },
130
193
  pdfBackground: {
131
- desc: 'Background colour to use when PDF is partially transparent',
194
+ desc: "Background colour to use when PDF is partially transparent",
132
195
  group: input,
133
- type: 'string'
196
+ type: "string",
134
197
  },
135
198
  sequentialRead: {
136
199
  default: false,
137
- desc: 'Use sequential rather than random access where possible',
200
+ desc: "Use sequential rather than random access where possible",
138
201
  group: input,
139
- type: 'boolean'
202
+ type: "boolean",
140
203
  },
141
204
  subifd: {
142
205
  defaultDescription: -1,
143
- desc: 'subIFD to extract for OME-TIFF',
206
+ desc: "subIFD to extract for OME-TIFF",
144
207
  group: input,
145
- type: 'number'
208
+ nargs: 1,
209
+ type: "number",
146
210
  },
147
211
  unlimited: {
148
- desc: 'Remove safety features that help prevent memory exhaustion',
212
+ desc: "Remove safety features that help prevent memory exhaustion",
149
213
  group: input,
150
- type: 'boolean'
151
- }
152
- }
214
+ type: "boolean",
215
+ },
216
+ };
153
217
 
154
218
  const outputOptions = {
219
+ // @see https://sharp.pixelplumbing.com/api-output#tiff
220
+ bigtiff: {
221
+ desc: "Use BigTIFF variant",
222
+ group: output,
223
+ type: "boolean",
224
+ },
225
+
155
226
  // @see https://sharp.pixelplumbing.com/api-output#png
156
227
  compressionLevel: {
157
- alias: 'c',
158
- desc: 'zlib compression level',
228
+ alias: "c",
229
+ desc: "zlib compression level",
159
230
  defaultDescription: 6,
160
231
  group: output,
161
- type: 'number'
232
+ nargs: 1,
233
+ type: "number",
162
234
  },
163
235
 
164
236
  // @see https://sharp.pixelplumbing.com/api-output#toformat
165
237
  format: {
166
- alias: 'f',
238
+ alias: "f",
167
239
  choices: constants.FORMAT,
168
- defaultDescription: 'input',
169
- desc: 'Force output to a given format',
170
- group: output
240
+ defaultDescription: "input",
241
+ desc: "Force output to a given format",
242
+ group: output,
243
+ },
244
+
245
+ // @see https://sharp.pixelplumbing.com/api-output#gif
246
+ keepDuplicateFrames: {
247
+ desc: "Keep duplicate frames in the output instead of combining them",
248
+ group: output,
249
+ type: "boolean",
250
+ },
251
+
252
+ // @see https://sharp.pixelplumbing.com/api-output#keepgainmap
253
+ keepGainMap: {
254
+ conflicts: "withGainMap",
255
+ desc: "Attempt to process the image and gain map separately, recombining them into a single output image",
256
+ group: output,
257
+ type: "boolean",
171
258
  },
172
259
 
173
260
  // @see https://sharp.pixelplumbing.com/api-output#withmetadata
174
261
  metadata: {
175
- alias: ['m', 'withMetadata'],
176
- desc: 'Include all metadata (EXIF, XMP, IPTC) from the input image in the output image',
262
+ alias: ["m", "withMetadata"],
263
+ desc: "Include all metadata (EXIF, XMP, IPTC) from the input image in the output image",
264
+ group: output,
265
+ type: "boolean",
266
+ },
267
+ "metadata.density": {
268
+ desc: "Number of pixels per inch (DPI)",
177
269
  group: output,
178
- type: 'boolean'
270
+ nargs: 1,
271
+ type: "number",
179
272
  },
180
- 'metadata.density': {
181
- desc: 'Number of pixels per inch (DPI)',
273
+ "metadata.exif": {
274
+ defaultDescription: "{}",
275
+ desc: "Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data",
182
276
  group: output,
183
- type: 'number'
277
+ type: "object",
184
278
  },
185
- 'metadata.exif': {
186
- defaultDescription: '{}',
187
- desc: 'Object keyed by IFD0, IFD1 etc. of key/value string pairs to write as EXIF data',
279
+ "metadata.icc": {
280
+ defaultDescription: "sRGB",
281
+ desc: "Filesystem path to output ICC profile",
188
282
  group: output,
189
- type: 'object'
283
+ type: "string",
190
284
  },
191
- 'metadata.icc': {
192
- defaultDescription: 'sRGB',
193
- desc: 'Filesystem path to output ICC profile',
285
+ "metadata.orientation": {
286
+ desc: "Used to update the EXIF Orientation tag",
194
287
  group: output,
195
- type: 'string'
288
+ nargs: 1,
289
+ type: "number",
196
290
  },
197
- 'metadata.orientation': {
198
- desc: 'Used to update the EXIF Orientation tag',
291
+
292
+ // @see https://sharp.pixelplumbing.com/api-output#withdensity
293
+ withDensity: {
294
+ desc: "Set output density (DPI) in EXIF metadata",
199
295
  group: output,
200
- type: 'number'
296
+ nargs: 1,
297
+ type: "number",
298
+ },
299
+
300
+ // @see https://sharp.pixelplumbing.com/api-output#withgainmap
301
+ withGainMap: {
302
+ conflicts: "keepGainMap",
303
+ desc: "Convert the main image to HDR (High Dynamic Range) before further processing",
304
+ group: output,
305
+ type: "boolean",
201
306
  },
202
307
 
203
308
  // @see https://sharp.pixelplumbing.com/api-output#jpeg
204
309
  // @see https://sharp.pixelplumbing.com/api-output#png
205
310
  progressive: {
206
- alias: 'p',
207
- desc: 'Use progressive (interlace) scan',
311
+ alias: "p",
312
+ desc: "Use progressive (interlace) scan",
208
313
  group: output,
209
- type: 'boolean'
314
+ type: "boolean",
210
315
  },
211
316
 
212
317
  // @see https://sharp.pixelplumbing.com/api-output#avif
@@ -214,79 +319,85 @@ const outputOptions = {
214
319
  // @see https://sharp.pixelplumbing.com/api-output#tiff
215
320
  // @see https://sharp.pixelplumbing.com/api-output#webp
216
321
  quality: {
217
- alias: 'q',
218
- desc: 'Quality',
219
- defaultDescription: '80',
322
+ alias: "q",
323
+ desc: "Quality",
324
+ defaultDescription: "80",
220
325
  group: output,
221
- type: 'number'
222
- }
223
- }
326
+ nargs: 1,
327
+ type: "number",
328
+ },
329
+ };
224
330
 
225
331
  const optimizationOptions = {
226
332
  // @see https://sharp.pixelplumbing.com/api-output#png
227
333
  adaptiveFiltering: {
228
- desc: 'Use adaptive row filtering',
334
+ desc: "Use adaptive row filtering",
229
335
  group: optimize,
230
- type: 'boolean'
336
+ type: "boolean",
231
337
  },
232
338
 
233
339
  // @see https://sharp.pixelplumbing.com/api-output#webp
234
340
  alphaQuality: {
235
- desc: 'Quality of alpha layer',
236
- defaultDescription: '80',
341
+ desc: "Quality of alpha layer",
342
+ defaultDescription: "80",
237
343
  group: optimize,
238
- type: 'number'
344
+ nargs: 1,
345
+ type: "number",
239
346
  },
240
347
 
241
348
  // @see https://sharp.pixelplumbing.com/api-output#tiff
242
349
  bitdepth: {
243
350
  choices: [1, 2, 4, 8],
244
351
  defaultDescription: 8,
245
- desc: 'Reduce bitdepth to 1, 2, or 4 bit',
246
- group: optimize
352
+ desc: "Reduce bitdepth to 1, 2, or 4 bit",
353
+ group: optimize,
354
+ nargs: 1,
247
355
  },
248
356
 
249
357
  // @see https://sharp.pixelplumbing.com/api-output#avif
250
358
  // @see https://sharp.pixelplumbing.com/api-output#jpeg
251
359
  chromaSubsampling: {
252
360
  desc: 'Set to "4:4:4" to prevent chroma subsampling when quality <= 90',
253
- defaultDescription: '4:4:4 (AVIF) / 4:2:0',
361
+ defaultDescription: "4:4:4 (AVIF) / 4:2:0",
254
362
  group: optimize,
255
- type: 'string'
363
+ type: "string",
256
364
  },
257
365
 
258
366
  // @see https://sharp.pixelplumbing.com/api-output#gif
259
- // @see https://sharp.dimens.io/api-output#png
367
+ // @see https://sharp.pixelplumbing.com/api-output#png
260
368
  colors: {
261
- alias: 'colours',
369
+ alias: "colours",
262
370
  defaultDescription: 256,
263
- desc: 'Maximum number of palette entries',
371
+ desc: "Maximum number of palette entries",
264
372
  group: optimize,
265
- type: 'number'
373
+ nargs: 1,
374
+ type: "number",
266
375
  },
267
376
 
268
377
  // @see https://sharp.pixelplumbing.com/api-output#tiff
269
378
  compression: {
270
379
  choices: constants.TIFF_COMPRESSION,
271
- default: 'jpeg',
272
- desc: 'Compression options',
273
- group: optimize
380
+ default: "jpeg",
381
+ desc: "Compression options",
382
+ group: optimize,
274
383
  },
275
384
 
276
385
  // @see https://sharp.pixelplumbing.com/api-output#gif
277
386
  delay: {
278
- desc: 'Delay(s) between animation frames',
387
+ desc: "Delay(s) between animation frames",
279
388
  group: optimize,
280
- type: 'number'
389
+ nargs: 1,
390
+ type: "number",
281
391
  },
282
392
 
283
393
  // @see https://sharp.pixelplumbing.com/api-output#gif
284
- // @see https://sharp.dimens.io/api-output#png
394
+ // @see https://sharp.pixelplumbing.com/api-output#png
285
395
  dither: {
286
- desc: 'Level of Floyd-Steinberg error diffusion',
287
- defaultDescription: '1.0',
396
+ desc: "Level of Floyd-Steinberg error diffusion",
397
+ defaultDescription: "1.0",
288
398
  group: optimize,
289
- type: 'number'
399
+ nargs: 1,
400
+ type: "number",
290
401
  },
291
402
 
292
403
  // @see https://sharp.pixelplumbing.com/api-output#avif
@@ -295,389 +406,493 @@ const optimizationOptions = {
295
406
  // @see https://sharp.pixelplumbing.com/api-output#png
296
407
  // @see https://sharp.pixelplumbing.com/api-output#webp
297
408
  effort: {
298
- defaultDescription: '7 (GIF, PNG) / 4',
299
- desc: 'Level of CPU effort to reduce file size',
409
+ defaultDescription: "7 (GIF, PNG) / 4",
410
+ desc: "Level of CPU effort to reduce file size",
411
+ group: optimize,
412
+ nargs: 1,
413
+ type: "number",
414
+ },
415
+
416
+ // @see https://sharp.pixelplumbing.com/api-output#webp
417
+ exact: {
418
+ desc: "Preserve the colour data in transparent pixels",
300
419
  group: optimize,
301
- type: 'number'
420
+ type: "boolean",
302
421
  },
303
422
 
304
423
  // @see https://sharp.pixelplumbing.com/api-output#heif
305
424
  hbitdepth: {
306
425
  choices: [8, 10, 12],
307
426
  defaultDescription: 8,
308
- desc: 'Set bitdepth to 8, 10, or 12 bit',
309
- group: optimize
427
+ desc: "Set bitdepth to 8, 10, or 12 bit",
428
+ group: optimize,
429
+ nargs: 1,
310
430
  },
311
431
 
312
432
  // @see https://sharp.pixelplumbing.com/api-output#heif
313
433
  hcompression: {
314
434
  choices: constants.HEIF_COMPRESSION,
315
- default: 'av1',
316
- desc: 'Compression format',
317
- group: optimize
435
+ default: "av1",
436
+ desc: "Compression format",
437
+ group: optimize,
318
438
  },
319
439
 
320
440
  // @see https://sharp.pixelplumbing.com/api-output#gif
321
441
  interFrameMaxError: {
322
- desc: 'Maximum inter-frame error for transparency',
442
+ desc: "Maximum inter-frame error for transparency",
323
443
  group: optimize,
324
- type: 'number'
444
+ nargs: 1,
445
+ type: "number",
325
446
  },
326
447
 
327
448
  // @see https://sharp.pixelplumbing.com/api-output#gif
328
449
  interPaletteMaxError: {
329
- desc: 'Maximum inter-palette error for palette reuse',
450
+ desc: "Maximum inter-palette error for palette reuse",
330
451
  group: optimize,
331
- type: 'number'
452
+ nargs: 1,
453
+ type: "number",
332
454
  },
333
455
 
334
456
  // @see https://sharp.pixelplumbing.com/api-output#gif
335
457
  loop: {
336
458
  default: 0,
337
- desc: 'Number of animation iterations',
459
+ desc: "Number of animation iterations",
338
460
  group: optimize,
339
- type: 'number'
461
+ nargs: 1,
462
+ type: "number",
340
463
  },
341
464
 
342
465
  // @see https://sharp.pixelplumbing.com/api-output#avif
343
466
  // @see https://sharp.pixelplumbing.com/api-output#webp
344
467
  lossless: {
345
- desc: 'Use lossless compression mode',
468
+ desc: "Use lossless compression mode",
346
469
  group: optimize,
347
- type: 'boolean'
470
+ type: "boolean",
348
471
  },
349
472
 
350
473
  // @see https://sharp.pixelplumbing.com/api-output#tiff
351
474
  miniswhite: {
352
- desc: 'Write 1-bit images as miniswhite',
475
+ desc: "Write 1-bit images as miniswhite",
353
476
  group: optimize,
354
- type: 'boolean'
477
+ type: "boolean",
355
478
  },
356
479
 
357
480
  // @see https://sharp.pixelplumbing.com/api-output#webp
358
481
  minSize: {
359
- desc: 'Prevent use of animation key frames to minimize file size',
482
+ desc: "Prevent use of animation key frames to minimize file size",
360
483
  group: optimize,
361
- type: 'boolean'
484
+ type: "boolean",
362
485
  },
363
486
 
364
487
  // @see https://sharp.pixelplumbing.com/api-output#webp
365
488
  mixed: {
366
- desc: 'Allow mixture of lossy and lossless animation frames',
489
+ desc: "Allow mixture of lossy and lossless animation frames",
367
490
  group: optimize,
368
- type: 'boolean'
491
+ type: "boolean",
369
492
  },
370
493
 
371
494
  // @see https://sharp.pixelplumbing.com/api-output#jpeg
372
495
  mozjpeg: {
373
- desc: 'Use mozjpeg defaults',
496
+ desc: "Use mozjpeg defaults",
374
497
  group: optimize,
375
- type: 'boolean'
498
+ type: "boolean",
376
499
  },
377
500
 
378
501
  // @see https://sharp.pixelplumbing.com/api-output#webp
379
502
  nearLossless: {
380
- desc: 'Use near_lossless compression mode',
503
+ desc: "Use near_lossless compression mode",
381
504
  group: optimize,
382
- type: 'boolean'
505
+ type: "boolean",
383
506
  },
384
507
 
385
508
  // @see https://sharp.pixelplumbing.com/api-output#jpeg
386
509
  optimise: {
387
- alias: 'optimize',
388
- desc: 'Apply optimiseScans, overshootDeringing, and trellisQuantisation',
510
+ alias: "optimize",
511
+ desc: "Apply optimiseScans, overshootDeringing, and trellisQuantisation",
389
512
  group: optimize,
390
- type: 'boolean'
513
+ type: "boolean",
391
514
  },
392
515
 
393
516
  // @see https://sharp.pixelplumbing.com/api-output#jpeg
394
517
  optimiseCoding: {
395
- alias: 'optimizeCoding',
518
+ alias: "optimizeCoding",
396
519
  default: true,
397
- desc: 'Optimise Huffman coding tables',
520
+ desc: "Optimise Huffman coding tables",
398
521
  group: optimize,
399
- type: 'boolean'
522
+ type: "boolean",
400
523
  },
401
524
 
402
525
  // @see https://sharp.pixelplumbing.com/api-output#jpeg
403
526
  optimiseScans: {
404
- alias: 'optimizeScans',
405
- desc: 'Optimise progressive scans',
527
+ alias: "optimizeScans",
528
+ desc: "Optimise progressive scans",
406
529
  group: optimize,
407
- implies: 'progressive',
408
- type: 'boolean'
530
+ implies: "progressive",
531
+ type: "boolean",
409
532
  },
410
533
 
411
534
  // @see https://sharp.pixelplumbing.com/api-output#jpeg
412
535
  overshootDeringing: {
413
- desc: 'Apply overshoot deringing',
536
+ desc: "Apply overshoot deringing",
414
537
  group: optimize,
415
- type: 'boolean'
538
+ type: "boolean",
416
539
  },
417
540
 
418
- // @see https://sharp.dimens.io/api-output#png
541
+ // @see https://sharp.pixelplumbing.com/api-output#png
419
542
  palette: {
420
- desc: 'Quantise to a palette-based image with alpha transparency support',
543
+ desc: "Quantise to a palette-based image with alpha transparency support",
421
544
  group: optimize,
422
- type: 'boolean'
545
+ type: "boolean",
423
546
  },
424
547
 
425
548
  // @see https://sharp.pixelplumbing.com/api-output#tiff
426
549
  predictor: {
427
550
  choices: constants.TIFF_PREDICTOR,
428
- default: 'horizontal',
429
- desc: 'Compression predictor',
430
- group: optimize
551
+ default: "horizontal",
552
+ desc: "Compression predictor",
553
+ group: optimize,
431
554
  },
432
555
 
433
556
  // @see https://sharp.pixelplumbing.com/api-output#webp
434
557
  preset: {
435
558
  choices: constants.PRESETS,
436
- default: 'default',
437
- desc: 'Named preset for preprocessing/filtering',
438
- group: optimize
559
+ default: "default",
560
+ desc: "Named preset for preprocessing/filtering",
561
+ group: optimize,
439
562
  },
440
563
 
441
564
  // @see https://sharp.pixelplumbing.com/api-output#tiff
442
565
  pyramid: {
443
- desc: 'Write an image pyramid',
566
+ desc: "Write an image pyramid",
444
567
  group: optimize,
445
- type: 'boolean'
568
+ type: "boolean",
446
569
  },
447
570
 
448
571
  // @see https://sharp.pixelplumbing.com/api-output#jpeg
449
572
  quantisationTable: {
450
- alias: 'quantizationTable',
451
- defaultDescription: '0',
452
- desc: 'Quantization table to use',
573
+ alias: "quantizationTable",
574
+ defaultDescription: "0",
575
+ desc: "Quantization table to use",
453
576
  group: optimize,
454
- type: 'number'
577
+ nargs: 1,
578
+ type: "number",
455
579
  },
456
580
 
457
581
  // @see https://sharp.pixelplumbing.com/api-output#gif
458
582
  reuse: {
459
- alias: ['reoptimise', 'reoptimize'],
460
- desc: 'Always generate new palettes (slow)',
583
+ alias: ["reoptimise", "reoptimize"],
584
+ desc: "Always generate new palettes (slow)",
461
585
  group: optimize,
462
- type: 'boolean'
586
+ type: "boolean",
463
587
  },
464
588
 
465
589
  // @see https://sharp.pixelplumbing.com/api-output
466
590
  resolutionUnit: {
467
591
  choices: constants.RESOLUTION_UNIT,
468
- defaultDescription: 'inch',
469
- desc: 'Resolution unit',
470
- group: optimize
592
+ defaultDescription: "inch",
593
+ desc: "Resolution unit",
594
+ group: optimize,
471
595
  },
472
596
 
473
597
  // @see https://sharp.pixelplumbing.com/api-output#webp
474
598
  smartDeblock: {
475
- desc: 'Auto-adjust the deblocking filter, can improve low contrast edges',
599
+ desc: "Auto-adjust the deblocking filter, can improve low contrast edges",
476
600
  group: optimize,
477
- type: 'boolean'
601
+ type: "boolean",
478
602
  },
479
603
 
480
604
  // @see https://sharp.pixelplumbing.com/api-output#webp
481
605
  smartSubsample: {
482
- desc: 'High quality chroma subsampling',
606
+ desc: "High quality chroma subsampling",
483
607
  group: optimize,
484
- type: 'boolean'
608
+ type: "boolean",
485
609
  },
486
610
 
487
611
  // @see https://sharp.pixelplumbing.com/api-output#tile
488
612
  tileBackground: {
489
- defaultDescription: 'rgba(255, 255, 255, 1)',
490
- desc: 'Background colour, parsed by the color module',
613
+ defaultDescription: "rgba(255, 255, 255, 1)",
614
+ desc: "Background colour, parsed by the color module",
491
615
  group: optimize,
492
- type: 'string'
616
+ type: "string",
493
617
  },
494
618
 
495
619
  // @see https://sharp.pixelplumbing.com/api-output#tiff
496
620
  tileHeight: {
497
- desc: 'Vertical tile size',
621
+ desc: "Vertical tile size",
498
622
  group: optimize,
499
- type: 'number'
623
+ nargs: 1,
624
+ type: "number",
500
625
  },
501
626
 
502
627
  // @see https://sharp.pixelplumbing.com/api-output#tiff
503
628
  tileWidth: {
504
- desc: 'Horizontal tile size',
629
+ desc: "Horizontal tile size",
505
630
  group: optimize,
506
- type: 'number'
631
+ nargs: 1,
632
+ type: "number",
507
633
  },
508
634
 
509
635
  // @see https://sharp.pixelplumbing.com/api-output#jpeg
510
636
  trellisQuantisation: {
511
- desc: 'Apply trellis quantisation',
637
+ desc: "Apply trellis quantisation",
638
+ group: optimize,
639
+ type: "boolean",
640
+ },
641
+
642
+ // @see https://sharp.pixelplumbing.com/api-output#avif
643
+ // @see https://sharp.pixelplumbing.com/api-output#heif
644
+ tune: {
645
+ choices: constants.TUNE,
646
+ defaultDescription: "auto",
647
+ desc: "Tune output for a quality metric",
512
648
  group: optimize,
513
- type: 'boolean'
514
649
  },
515
650
 
516
651
  // @see https://sharp.pixelplumbing.com/api-output#tiff
517
652
  xres: {
518
- defaultDescription: '1.0',
519
- desc: 'Horizontal resolution',
653
+ defaultDescription: "1.0",
654
+ desc: "Horizontal resolution",
520
655
  group: optimize,
521
- type: 'number'
656
+ nargs: 1,
657
+ type: "number",
522
658
  },
523
659
 
524
660
  // @see https://sharp.pixelplumbing.com/api-output#tiff
525
661
  yres: {
526
- defaultDescription: '1.0',
527
- desc: 'Vertical resolution',
662
+ defaultDescription: "1.0",
663
+ desc: "Vertical resolution",
528
664
  group: optimize,
529
- type: 'number'
530
- }
531
- }
665
+ nargs: 1,
666
+ type: "number",
667
+ },
668
+ };
532
669
 
533
670
  const options = {
534
671
  ...globalOptions,
535
672
  ...inputOptions,
536
673
  ...outputOptions,
537
- ...optimizationOptions
674
+ ...optimizationOptions,
675
+ };
676
+
677
+ // Helpers.
678
+ function createContext() {
679
+ return { "#queue": [] };
538
680
  }
539
681
 
540
682
  // Configure.
541
- const cli = yargs
542
- .parserConfiguration({ 'populate--': true })
683
+ const cli = yargs()
684
+ .parserConfiguration({ "populate--": true })
543
685
  .strict()
544
- .usage('$0 <options> [command..]')
686
+ .usage("$0 <options> [command..]")
545
687
  .options(options)
546
- .example('$0 -i ./input.jpg -o ./out resize 300 200', 'out/input.jpg will be a 300 pixels wide and 200 pixels high image containing a scaled and cropped version of input.jpg')
547
- .example('$0 -i ./input.jpg -o ./out -mq90 rotate 180 -- resize 300 -- flatten "#ff6600" -- composite ./overlay.png --gravity southeast -- sharpen', 'out/input.jpg will be an upside down, 300px wide, alpha channel flattened onto orange background, composited with overlay.png with SE gravity, sharpened, with metadata, 90% quality version of input.jpg')
548
- .example('$0 -i ./input.jpg -o ./out --metadata', 'Include all metadata in the output image')
549
- .example('$0 -i ./input.jpg -o ./out --metadata.exif.IFD0.Copyright "Wernham Hogg"', 'Set "IFD0-Copyright" in output EXIF metadata')
550
- .example('$0 -i ./input.jpg -o ./out --metadata.density 96', 'Set output metadata to 96 DPI')
551
- .epilog('For more information on available options, please visit https://sharp.pixelplumbing.com/')
688
+ .example(
689
+ "$0 -i ./input.jpg -o ./out resize 300 200",
690
+ "out/input.jpg will be a 300 pixels wide and 200 pixels high image containing a scaled and cropped version of input.jpg",
691
+ )
692
+ .example(
693
+ '$0 -i ./input.jpg -o ./out -mq90 rotate 180 -- resize 300 -- flatten "#ff6600" -- composite ./overlay.png --gravity southeast -- sharpen',
694
+ "out/input.jpg will be an upside down, 300px wide, alpha channel flattened onto orange background, composited with overlay.png with SE gravity, sharpened, with metadata, 90% quality version of input.jpg",
695
+ )
696
+ .example(
697
+ "$0 -i ./input.jpg -o ./out --metadata",
698
+ "Include all metadata in the output image",
699
+ )
700
+ .example(
701
+ '$0 -i ./input.jpg -o ./out --metadata.exif.IFD0.Copyright "Wernham Hogg"',
702
+ 'Set "IFD0-Copyright" in output EXIF metadata',
703
+ )
704
+ .example(
705
+ "$0 -i ./input.jpg -o ./out --metadata.density 96",
706
+ "Set output metadata to 96 DPI",
707
+ )
708
+ .epilog(
709
+ "For more information on available options, please visit https://sharp.pixelplumbing.com/",
710
+ )
552
711
  .showHelpOnFail(false)
553
712
  .wrap(100)
554
713
 
555
714
  // Built-in options.
556
- .help().alias('help', 'h')
557
- .version(pkg.version).alias('version', 'v')
558
- .group(['help', 'version'], 'Misc. Options')
715
+ .help()
716
+ .alias("help", "h")
717
+ .version(pkg.version)
718
+ .alias("version", "v")
719
+ .group(["help", "version"], "Misc. Options")
559
720
 
560
721
  // Commands.
561
- // Avoid `yargs.commandDir()` as it uses insertion order, not alphabetical.
562
- .command(require('../cmd/operations/affine'))
563
- .command(require('../cmd/channel-manipulation/bandbool'))
564
- .command(require('../cmd/operations/blur'))
565
- .command(require('../cmd/operations/boolean'))
566
- .command(require('../cmd/operations/clahe'))
567
- .command(require('../cmd/compositing/composite'))
568
- .command(require('../cmd/operations/convolve'))
569
- .command(require('../cmd/channel-manipulation/ensure-alpha'))
570
- .command(require('../cmd/resizing/extend'))
571
- .command(require('../cmd/resizing/extract'))
572
- .command(require('../cmd/channel-manipulation/extract-channel'))
573
- .command(require('../cmd/operations/flatten'))
574
- .command(require('../cmd/operations/flip'))
575
- .command(require('../cmd/operations/flop'))
576
- .command(require('../cmd/operations/gamma'))
577
- .command(require('../cmd/colour-manipulation/greyscale'))
578
- .command(require('../cmd/channel-manipulation/join-channel'))
579
- .command(require('../cmd/operations/linear'))
580
- .command(require('../cmd/operations/median'))
581
- .command(require('../cmd/operations/modulate'))
582
- .command(require('../cmd/operations/negate'))
583
- .command(require('../cmd/operations/normalise'))
584
- .command(require('../cmd/colour-manipulation/pipeline-colourspace'))
585
- .command(require('../cmd/operations/recomb'))
586
- .command(require('../cmd/channel-manipulation/remove-alpha'))
587
- .command(require('../cmd/resizing/resize'))
588
- .command(require('../cmd/operations/rotate'))
589
- .command(require('../cmd/operations/sharpen'))
590
- .command(require('../cmd/operations/threshold'))
591
- .command(require('../cmd/colour-manipulation/tint'))
592
- .command(require('../cmd/output'))
593
- .command(require('../cmd/colour-manipulation/tocolourspace'))
594
- .command(require('../cmd/resizing/trim'))
595
- .command(require('../cmd/operations/unflatten'))
722
+ .command(affine)
723
+ .command(bandbool)
724
+ .command(blur)
725
+ .command(boolean)
726
+ .command(clahe)
727
+ .command(composite)
728
+ .command(convolve)
729
+ .command(dilate)
730
+ .command(ensureAlpha)
731
+ .command(erode)
732
+ .command(extend)
733
+ .command(extract)
734
+ .command(extractChannel)
735
+ .command(flatten)
736
+ .command(flip)
737
+ .command(flop)
738
+ .command(gamma)
739
+ .command(greyscale)
740
+ .command(joinChannel)
741
+ .command(linear)
742
+ .command(median)
743
+ .command(modulate)
744
+ .command(negate)
745
+ .command(normalise)
746
+ .command(pipelineColourspace)
747
+ .command(recomb)
748
+ .command(removeAlpha)
749
+ .command(resize)
750
+ .command(rotate)
751
+ .command(sharpen)
752
+ .command(threshold)
753
+ .command(tint)
754
+ .command(tile)
755
+ .command(toColourspace)
756
+ .command(trim)
757
+ .command(unflatten);
758
+
759
+ // Intercept parsing as to orchestrate commands.
760
+ cli.parseAsync = async function (args, context = createContext()) {
761
+ // Capture parsing result as a promise.
762
+ const argv = await new Promise((resolve, reject) => {
763
+ return cli.parse(args, context, (err, argv, output) => {
764
+ if (err) reject(err);
765
+ if (argv.help || argv.v) reject(output);
766
+ resolve(argv);
767
+ });
768
+ });
769
+
770
+ // Invoke with remaining arguments (if any). Carry over global options.
771
+ const remainingArgv = argv["--"] ?? [];
772
+ if (remainingArgv.length > 0) {
773
+ const globalArgv = pick(argv, Object.keys(options));
774
+ return cli.default(globalArgv).parseAsync(remainingArgv, context);
775
+ }
596
776
 
597
- // Helpers.
598
- const originalParse = cli.parse.bind(cli)
599
- const promisifiedParse = (...args) => {
600
- return new Promise((resolve, reject) => {
601
- originalParse(...args, (err, argv, output) => {
602
- if (err) {
603
- reject(err)
604
- }
605
- if (argv.v || argv.help) {
606
- reject(output)
607
- }
608
- resolve(argv)
609
- })
610
- })
611
- }
777
+ // Apply global options (once).
778
+ const queue = context["#queue"];
779
+
780
+ // @see https://sharp.pixelplumbing.com/api-output#timeout
781
+ if (argv.timeout) {
782
+ queue.unshift([
783
+ "timeout",
784
+ (sharp) => sharp.timeout({ seconds: argv.timeout }),
785
+ ]);
786
+ }
787
+
788
+ // Output options.
789
+
790
+ // @see https://sharp.pixelplumbing.com/api-output#toformat
791
+ if (argv.format) {
792
+ queue.unshift([
793
+ "format",
794
+ (sharp) =>
795
+ sharp.toFormat(argv.format, { compression: argv.hcompression }),
796
+ ]);
797
+ }
798
+
799
+ // @see https://sharp.pixelplumbing.com/api-output#keepgainmap
800
+ if (argv.keepGainMap) {
801
+ queue.unshift(["keepGainMap", (sharp) => sharp.keepGainMap()]);
802
+ }
803
+
804
+ // @see https://sharp.pixelplumbing.com/api-output#withmetadata
805
+ if (argv.metadata) {
806
+ queue.unshift([
807
+ "withMetadata",
808
+ (sharp) => sharp.withMetadata(argv.metadata),
809
+ ]);
810
+ }
811
+
812
+ // @see https://sharp.pixelplumbing.com/api-output#withdensity
813
+ if (argv.withDensity !== undefined) {
814
+ queue.unshift([
815
+ "withDensity",
816
+ (sharp) => sharp.withDensity(argv.withDensity),
817
+ ]);
818
+ }
612
819
 
613
- // Exports.
614
- module.exports = cli
615
- module.exports.inputOptions = Object.keys(inputOptions)
616
- module.exports.parse = function recursiveParse (args, context = {}) {
617
- return promisifiedParse(args, context).then(argv => {
618
- // Handle arguments.
619
- // NOTE Use queue.unshift to apply global options first.
620
-
621
- // Global options.
622
-
623
- // Require at least one input file.
624
- // NOTE: check here b/c https://github.com/yargs/yargs/issues/403
625
- if (argv.input && argv.input.length === 0) {
626
- throw new Error('Not enough arguments following: i, input')
627
- }
628
-
629
- // @see https://sharp.pixelplumbing.com/api-output#timeout
630
- if (argv.timeout) {
631
- queue.unshift(['timeout', (sharp) => sharp.timeout({ seconds: argv.timeout })])
632
- }
633
-
634
- // Output options.
635
-
636
- // @see https://sharp.pixelplumbing.com/api-output#toformat
637
- if (argv.format) {
638
- queue.unshift(['format', (sharp) => sharp.toFormat(argv.format, { compression: argv.hcompression })])
639
- }
640
-
641
- // @see https://sharp.pixelplumbing.com/api-output#withmetadata
642
- if (argv.metadata) {
643
- queue.unshift(['withMetadata', (sharp) => sharp.withMetadata(argv.metadata)])
644
- }
645
-
646
- // @see https://sharp.pixelplumbing.com/api-output#heif
647
- const { heif } = sharp.format
648
- if (argv.hcompression !== optimizationOptions.hcompression.default || // HEIF-specific.
649
- // Ensure libheif is installed before applying generic options.
650
- (heif.input && heif.input.file &&
651
- (argv.effort || argv.hbitdepth || argv.lossless || argv.quality))) {
652
- queue.unshift(['heif', (sharp) => {
820
+ // @see https://sharp.pixelplumbing.com/api-output#withgainmap
821
+ if (argv.withGainMap) {
822
+ queue.unshift(["withGainMap", (sharp) => sharp.withGainMap()]);
823
+ }
824
+
825
+ // @see https://sharp.pixelplumbing.com/api-output#heif
826
+ const { heif } = sharp.format;
827
+ if (
828
+ argv.hcompression !== optimizationOptions.hcompression.default || // HEIF-specific.
829
+ // Ensure libheif is installed before applying generic options.
830
+ (heif.input &&
831
+ heif.input.file &&
832
+ (argv.effort !== undefined ||
833
+ argv.hbitdepth ||
834
+ argv.lossless ||
835
+ argv.quality ||
836
+ argv.tune))
837
+ ) {
838
+ queue.unshift([
839
+ "heif",
840
+ (sharp, { format } = {}) => {
841
+ if (format && format !== "heif") return sharp;
653
842
  return sharp.heif({
654
843
  bitdepth: argv.hbitdepth,
655
844
  compression: argv.hcompression,
656
845
  effort: argv.effort,
657
846
  force: false,
658
847
  lossless: argv.lossless,
659
- quality: argv.quality
660
- })
661
- }])
662
- }
663
-
664
- // @see https://sharp.pixelplumbing.com/api-output#avif
665
- if (argv.chromaSubsampling || argv.effort || argv.lossless || argv.quality) {
666
- queue.unshift(['avif', (sharp) => {
848
+ quality: argv.quality,
849
+ tune: argv.tune,
850
+ });
851
+ },
852
+ ]);
853
+ }
854
+
855
+ // @see https://sharp.pixelplumbing.com/api-output#avif
856
+ if (
857
+ argv.chromaSubsampling ||
858
+ argv.effort !== undefined ||
859
+ argv.lossless ||
860
+ argv.quality ||
861
+ argv.tune
862
+ ) {
863
+ queue.unshift([
864
+ "avif",
865
+ (sharp, { format } = {}) => {
866
+ if (format && format !== "avif") return sharp;
667
867
  return sharp.avif({
668
868
  chromaSubsampling: argv.chromaSubsampling,
669
869
  effort: argv.effort,
670
870
  force: false,
671
871
  lossless: argv.lossless,
672
- quality: argv.quality
673
- })
674
- }])
675
- }
676
-
677
- // @see https://sharp.pixelplumbing.com/api-output#gif
678
- if (argv.colors || argv.effort || argv.dither || argv.interFrameMaxError ||
679
- argv.interPaletteMaxError || argv.loop || argv.delay || argv.progressive || argv.reuse) {
680
- queue.unshift(['gif', (sharp) => {
872
+ quality: argv.quality,
873
+ tune: argv.tune,
874
+ });
875
+ },
876
+ ]);
877
+ }
878
+
879
+ // @see https://sharp.pixelplumbing.com/api-output#gif
880
+ if (
881
+ argv.colors ||
882
+ argv.effort !== undefined ||
883
+ argv.dither !== undefined ||
884
+ argv.interFrameMaxError ||
885
+ argv.interPaletteMaxError ||
886
+ argv.keepDuplicateFrames ||
887
+ argv.loop ||
888
+ argv.delay !== undefined ||
889
+ argv.progressive ||
890
+ argv.reuse
891
+ ) {
892
+ queue.unshift([
893
+ "gif",
894
+ (sharp, { format } = {}) => {
895
+ if (format && format !== "gif") return sharp;
681
896
  return sharp.gif({
682
897
  colors: argv.colors,
683
898
  force: false,
@@ -685,28 +900,33 @@ module.exports.parse = function recursiveParse (args, context = {}) {
685
900
  dither: argv.dither,
686
901
  interFrameMaxError: argv.interFrameMaxError,
687
902
  interPaletteMaxError: argv.interPaletteMaxError,
903
+ keepDuplicateFrames: argv.keepDuplicateFrames,
688
904
  loop: argv.loop,
689
905
  delay: argv.delay,
690
906
  progressive: argv.progressive,
691
- reuse: argv.reuse
692
- })
693
- }])
694
- }
695
-
696
- // @see https://sharp.pixelplumbing.com/api-output#jpeg
697
- if (
698
- argv.chromaSubsampling ||
699
- argv.mozjpeg ||
700
- argv.optimise ||
701
- argv.optimiseCoding !== true ||
702
- argv.optimiseScans ||
703
- argv.overshootDeringing ||
704
- argv.progressive ||
705
- argv.quantisationTable ||
706
- argv.quality ||
707
- argv.trellisQuantisation
708
- ) {
709
- queue.unshift(['jpeg', (sharp) => {
907
+ reuse: argv.reuse,
908
+ });
909
+ },
910
+ ]);
911
+ }
912
+
913
+ // @see https://sharp.pixelplumbing.com/api-output#jpeg
914
+ if (
915
+ argv.chromaSubsampling ||
916
+ argv.mozjpeg ||
917
+ argv.optimise ||
918
+ argv.optimiseCoding !== true ||
919
+ argv.optimiseScans ||
920
+ argv.overshootDeringing ||
921
+ argv.progressive ||
922
+ argv.quantisationTable ||
923
+ argv.quality ||
924
+ argv.trellisQuantisation
925
+ ) {
926
+ queue.unshift([
927
+ "jpeg",
928
+ (sharp, { format } = {}) => {
929
+ if (format && format !== "jpeg") return sharp;
710
930
  return sharp.jpeg({
711
931
  chromaSubsampling: argv.chromaSubsampling,
712
932
  force: false,
@@ -717,15 +937,26 @@ module.exports.parse = function recursiveParse (args, context = {}) {
717
937
  progressive: argv.progressive,
718
938
  quality: argv.quality,
719
939
  quantisationTable: argv.quantisationTable,
720
- trellisQuantisation: argv.optimise || argv.trellisQuantisation
721
- })
722
- }])
723
- }
724
-
725
- // @see https://sharp.pixelplumbing.com/api-output#png
726
- if (argv.adaptiveFiltering || argv.colors || argv.compressionLevel ||
727
- argv.dither || argv.effort || argv.palette || argv.progressive) {
728
- queue.unshift(['png', (sharp) => {
940
+ trellisQuantisation: argv.optimise || argv.trellisQuantisation,
941
+ });
942
+ },
943
+ ]);
944
+ }
945
+
946
+ // @see https://sharp.pixelplumbing.com/api-output#png
947
+ if (
948
+ argv.adaptiveFiltering ||
949
+ argv.colors ||
950
+ argv.compressionLevel !== undefined ||
951
+ argv.dither !== undefined ||
952
+ argv.effort ||
953
+ argv.palette ||
954
+ argv.progressive
955
+ ) {
956
+ queue.unshift([
957
+ "png",
958
+ (sharp, { format } = {}) => {
959
+ if (format && format !== "png") return sharp;
729
960
  return sharp.png({
730
961
  adaptiveFiltering: argv.adaptiveFiltering,
731
962
  colors: argv.colors,
@@ -734,20 +965,35 @@ module.exports.parse = function recursiveParse (args, context = {}) {
734
965
  effort: argv.effort,
735
966
  force: false,
736
967
  palette: argv.palette,
737
- progressive: argv.progressive
738
- })
739
- }])
740
- }
741
-
742
- // @see https://sharp.pixelplumbing.com/api-output#tiff
743
- if (argv.bitdepth ||
744
- argv.compression !== optimizationOptions.compression.default ||
745
- argv.predictor !== optimizationOptions.predictor.default ||
746
- argv.miniswhite || argv.pyramid || argv.quality || argv.resolutionUnit ||
747
- argv.tileBackground || argv.tileHeight || argv.tileWidth || argv.xres || argv.yres) {
748
- queue.unshift(['tiff', (sharp) => {
968
+ progressive: argv.progressive,
969
+ });
970
+ },
971
+ ]);
972
+ }
973
+
974
+ // @see https://sharp.pixelplumbing.com/api-output#tiff
975
+ if (
976
+ argv.bigtiff ||
977
+ argv.bitdepth ||
978
+ argv.compression !== optimizationOptions.compression.default ||
979
+ argv.predictor !== optimizationOptions.predictor.default ||
980
+ argv.miniswhite ||
981
+ argv.pyramid ||
982
+ argv.quality ||
983
+ argv.resolutionUnit ||
984
+ argv.tileBackground ||
985
+ argv.tileHeight ||
986
+ argv.tileWidth ||
987
+ argv.xres ||
988
+ argv.yres
989
+ ) {
990
+ queue.unshift([
991
+ "tiff",
992
+ (sharp, { format } = {}) => {
993
+ if (format && format !== "tiff") return sharp;
749
994
  return sharp.tiff({
750
995
  background: argv.tileBackground,
996
+ bigtiff: argv.bigtiff,
751
997
  bitdepth: argv.bitdepth,
752
998
  compression: argv.compression,
753
999
  force: false,
@@ -760,20 +1006,34 @@ module.exports.parse = function recursiveParse (args, context = {}) {
760
1006
  tileHeight: argv.tileHeight || argv.tileWidth,
761
1007
  tileWidth: argv.tileWidth || argv.tileHeight,
762
1008
  xres: argv.xres,
763
- yres: argv.yres
764
- })
765
- }])
766
- }
767
-
768
- // @see https://sharp.pixelplumbing.com/api-output#webp
769
- if (argv.alphaQuality || argv.quality || argv.lossless || argv.minSize ||
770
- argv.mixed || argv.nearLossless || argv.effort ||
771
- argv.preset !== optimizationOptions.preset.default || argv.smartDeblock ||
772
- argv.smartSubsample) {
773
- queue.unshift(['webp', (sharp) => {
1009
+ yres: argv.yres,
1010
+ });
1011
+ },
1012
+ ]);
1013
+ }
1014
+
1015
+ // @see https://sharp.pixelplumbing.com/api-output#webp
1016
+ if (
1017
+ argv.alphaQuality ||
1018
+ argv.quality ||
1019
+ argv.lossless ||
1020
+ argv.minSize ||
1021
+ argv.mixed ||
1022
+ argv.nearLossless ||
1023
+ argv.effort !== undefined ||
1024
+ argv.exact ||
1025
+ argv.preset !== optimizationOptions.preset.default ||
1026
+ argv.smartDeblock ||
1027
+ argv.smartSubsample
1028
+ ) {
1029
+ queue.unshift([
1030
+ "webp",
1031
+ (sharp, { format } = {}) => {
1032
+ if (format && format !== "webp") return sharp;
774
1033
  return sharp.webp({
775
1034
  alphaQuality: argv.alphaQuality,
776
1035
  effort: argv.effort,
1036
+ exact: argv.exact,
777
1037
  force: false,
778
1038
  lossless: argv.lossless,
779
1039
  minSize: argv.minSize,
@@ -782,19 +1042,13 @@ module.exports.parse = function recursiveParse (args, context = {}) {
782
1042
  preset: argv.preset,
783
1043
  quality: argv.quality,
784
1044
  smartDeblock: argv.smartDeblock,
785
- smartSubsample: argv.smartSubsample
786
- })
787
- }])
788
- }
789
-
790
- // Invoke with remaining arguments (if any).
791
- const { '--': remainingargv = [] } = argv
792
- if (remainingargv.length > 0) {
793
- return recursiveParse(remainingargv, {
794
- ...context,
795
- ...pick(argv, Object.keys(options)) // Retain options.
796
- })
797
- }
798
- return argv
799
- })
800
- }
1045
+ smartSubsample: argv.smartSubsample,
1046
+ });
1047
+ },
1048
+ ]);
1049
+ }
1050
+
1051
+ return argv;
1052
+ };
1053
+
1054
+ export default cli;