@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
@@ -23,87 +23,91 @@
23
23
 
24
24
  // @see https://sharp.pixelplumbing.com/api-operation#sharpen
25
25
 
26
- // Strict mode.
27
- 'use strict'
28
-
29
- // Package modules.
30
- const pick = require('lodash.pick')
31
-
32
26
  // Local modules.
33
- const queue = require('../../lib/queue')
27
+ import { pick } from "../../lib/utils.js";
34
28
 
35
29
  // Configure.
36
30
  const positionals = {
37
31
  sigma: {
38
- desc: 'The sigma of the Gaussian mask',
39
- defaultDescription: '1 + radius / 2',
40
- type: 'number'
41
- }
42
- }
32
+ desc: "The sigma of the Gaussian mask",
33
+ defaultDescription: "1 + radius / 2",
34
+ type: "number",
35
+ },
36
+ };
43
37
 
44
38
  const options = {
45
39
  m1: {
46
- alias: 'flat',
40
+ alias: "flat",
47
41
  desc: 'The level of sharpening to apply to "flat" areas',
48
42
  defaultDescription: 1.0,
49
- type: 'number'
43
+ nargs: 1,
44
+ type: "number",
50
45
  },
51
46
  m2: {
52
- alias: 'jagged',
47
+ alias: "jagged",
53
48
  desc: 'The level of sharpening to apply to "jagged" areas',
54
49
  defaultDescription: 2.0,
55
- type: 'number'
50
+ nargs: 1,
51
+ type: "number",
56
52
  },
57
53
  x1: {
58
54
  desc: 'The threshold between "flat" and "jagged" areas',
59
55
  defaultDescription: 2.0,
60
- type: 'number'
56
+ nargs: 1,
57
+ type: "number",
61
58
  },
62
59
  y2: {
63
- desc: 'The maximum amount of brightening',
60
+ desc: "The maximum amount of brightening",
64
61
  defaultDescription: 10.0,
65
- type: 'number'
62
+ nargs: 1,
63
+ type: "number",
66
64
  },
67
65
  y3: {
68
- desc: 'The maximum amount of darkening',
66
+ desc: "The maximum amount of darkening",
69
67
  defaultDescription: 20.0,
70
- type: 'number'
71
- }
72
- }
73
- const optionNames = Object.keys(options)
68
+ nargs: 1,
69
+ type: "number",
70
+ },
71
+ };
72
+ const optionNames = Object.keys(options);
74
73
 
75
74
  // Command builder.
76
75
  const builder = (yargs) => {
77
76
  return yargs
78
77
  .strict()
79
- .example('$0 sharpen')
80
- .example('$0 sharpen 2')
81
- .example('$0 sharpen 2 --m1 0 --m2 3 --x1 3 --y2 15 --y3 15')
82
- .epilog('For more information on available options, please visit https://sharp.pixelplumbing.com/api-operation#sharpen')
83
- .positional('sigma', positionals.sigma)
78
+ .example("$0 sharpen")
79
+ .example("$0 sharpen 2")
80
+ .example("$0 sharpen 2 --m1 0 --m2 3 --x1 3 --y2 15 --y3 15")
81
+ .epilog(
82
+ "For more information on available options, please visit https://sharp.pixelplumbing.com/api-operation#sharpen",
83
+ )
84
+ .positional("sigma", positionals.sigma)
84
85
  .options(options)
85
- .group(optionNames, 'Command Options')
86
- }
86
+ .group(optionNames, "Command Options");
87
+ };
87
88
 
88
89
  // Command handler.
89
90
  const handler = (args) => {
90
91
  const options = {
91
92
  ...pick(args, Object.keys(positionals)),
92
- ...pick(args, optionNames)
93
- }
93
+ ...pick(args, optionNames),
94
+ };
94
95
 
95
- return queue.push(['sharpen', (sharp) => {
96
- if (Object.keys(options).length === 0) {
97
- return sharp.sharpen()
98
- }
99
- return sharp.sharpen(options)
100
- }])
101
- }
96
+ return args["#queue"].push([
97
+ "sharpen",
98
+ (sharp) => {
99
+ if (Object.keys(options).length === 0) {
100
+ return sharp.sharpen();
101
+ }
102
+ return sharp.sharpen(options);
103
+ },
104
+ ]);
105
+ };
102
106
 
103
107
  // Exports.
104
- module.exports = {
105
- command: 'sharpen [sigma]',
106
- describe: 'Sharpen the image',
108
+ export default {
109
+ command: "sharpen [sigma]",
110
+ describe: "Sharpen the image",
107
111
  builder,
108
- handler
109
- }
112
+ handler,
113
+ };
@@ -23,51 +23,51 @@
23
23
 
24
24
  // @see https://sharp.pixelplumbing.com/api-operation#threshold
25
25
 
26
- // Strict mode.
27
- 'use strict'
28
-
29
- // Local modules.
30
- const queue = require('../../lib/queue')
31
-
32
26
  // Configure.
33
27
  const positionals = {
34
28
  value: {
35
- desc: 'A value in the range 0-255 representing the level at which the threshold will be applied',
29
+ desc: "A value in the range 0-255 representing the level at which the threshold will be applied",
36
30
  defaultDescription: 128,
37
- type: 'number'
38
- }
39
- }
31
+ type: "number",
32
+ },
33
+ };
40
34
 
41
35
  const options = {
42
36
  greyscale: {
43
- alias: 'grayscale',
44
- desc: 'Convert to single channel greyscale',
45
- type: 'boolean'
46
- }
47
- }
37
+ alias: "grayscale",
38
+ desc: "Convert to single channel greyscale",
39
+ type: "boolean",
40
+ },
41
+ };
48
42
 
49
43
  // Command builder.
50
44
  const builder = (yargs) => {
51
- const optionNames = Object.keys(options)
45
+ const optionNames = Object.keys(options);
52
46
  return yargs
53
47
  .strict()
54
- .epilog('For more information on available options, please visit https://sharp.pixelplumbing.com/api-operation#threshold')
55
- .positional('value', positionals.value)
48
+ .epilog(
49
+ "For more information on available options, please visit https://sharp.pixelplumbing.com/api-operation#threshold",
50
+ )
51
+ .positional("value", positionals.value)
56
52
  .options(options)
57
- .group(optionNames, 'Command Options')
58
- }
53
+ .group(optionNames, "Command Options");
54
+ };
59
55
 
60
56
  // Command handler.
61
57
  const handler = (args) => {
62
- return queue.push(['threshold', (sharp) => {
63
- return sharp.threshold(args.value, { greyscale: args.greyscale })
64
- }])
65
- }
58
+ return args["#queue"].push([
59
+ "threshold",
60
+ (sharp) => {
61
+ return sharp.threshold(args.value, { greyscale: args.greyscale });
62
+ },
63
+ ]);
64
+ };
66
65
 
67
66
  // Exports.
68
- module.exports = {
69
- command: 'threshold [value]',
70
- describe: 'Any pixel value greather than or equal to the threshold value will be set to 255, otherwise it will be set to 0',
67
+ export default {
68
+ command: "threshold [value]",
69
+ describe:
70
+ "Any pixel value greater than or equal to the threshold value will be set to 255, otherwise it will be set to 0",
71
71
  builder,
72
- handler
73
- }
72
+ handler,
73
+ };
@@ -21,29 +21,27 @@
21
21
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
23
 
24
- // @see https://sharp.dimens.io/api-operation#unflatten
25
-
26
- // Strict mode.
27
- 'use strict'
28
-
29
- // Local modules.
30
- const queue = require('../../lib/queue')
24
+ // @see https://sharp.pixelplumbing.com/api-operation#unflatten
31
25
 
32
26
  // Command builder.
33
27
  const builder = (yargs) => {
34
28
  return yargs
35
29
  .strict()
36
- .example('$0 unflatten')
37
- .epilog('For more information on available options, please visit https://sharp.dimens.io/api-operation#unflatten')
38
- }
30
+ .example("$0 unflatten")
31
+ .epilog(
32
+ "For more information on available options, please visit https://sharp.pixelplumbing.com/api-operation#unflatten",
33
+ );
34
+ };
39
35
 
40
36
  // Command handler.
41
- const handler = (args) => queue.push(['unflatten', (sharp) => sharp.unflatten()])
37
+ const handler = (args) =>
38
+ args["#queue"].push(["unflatten", (sharp) => sharp.unflatten()]);
42
39
 
43
40
  // Exports.
44
- module.exports = {
45
- command: 'unflatten',
46
- describe: 'Ensure the image has an alpha channel with all white pixel values made fully transparent',
41
+ export default {
42
+ command: "unflatten",
43
+ describe:
44
+ "Ensure the image has an alpha channel with all white pixel values made fully transparent",
47
45
  builder,
48
- handler
49
- }
46
+ handler,
47
+ };
package/cmd/output.js CHANGED
@@ -23,103 +23,108 @@
23
23
 
24
24
  // @see https://sharp.pixelplumbing.com/api-output#tile
25
25
 
26
- // Strict mode.
27
- 'use strict'
28
-
29
- // Package modules.
30
- const pick = require('lodash.pick')
31
-
32
26
  // Local modules.
33
- const constants = require('../lib/constants')
34
- const queue = require('../lib/queue')
27
+ import constants from "../lib/constants.js";
28
+ import { pick } from "../lib/utils.js";
35
29
 
36
30
  // Configure.
37
31
  const positionals = {
38
32
  size: {
39
- desc: 'Tile size in pixels',
33
+ desc: "Tile size in pixels",
40
34
  defaultDescription: 256,
41
- type: 'number'
42
- }
43
- }
35
+ type: "number",
36
+ },
37
+ };
44
38
 
45
39
  const options = {
46
40
  angle: {
47
41
  choices: [0, 90, 180, 270],
48
- defaultDescription: '0',
49
- desc: 'Tile angle of rotation'
42
+ defaultDescription: "0",
43
+ desc: "Tile angle of rotation",
44
+ nargs: 1,
50
45
  },
51
46
  background: {
52
- defaultDescription: 'rgb(255, 255, 255, 1)',
53
- desc: 'Background colour, parsed by the color module',
54
- type: 'string'
47
+ defaultDescription: "rgb(255, 255, 255, 1)",
48
+ desc: "Background colour, parsed by the color module",
49
+ type: "string",
55
50
  },
56
51
  basename: {
57
- desc: 'The name of the directory within the zip file',
58
- type: 'string'
52
+ desc: "The name of the directory within the zip file",
53
+ type: "string",
59
54
  },
60
55
  center: {
61
- alias: 'centre',
62
- desc: 'Center images in tile',
63
- type: 'boolean'
56
+ alias: "centre",
57
+ desc: "Center images in tile",
58
+ type: "boolean",
64
59
  },
65
60
  container: {
66
61
  choices: constants.CONTAINER,
67
- defaultDescription: 'fs',
68
- desc: 'Tile container'
62
+ defaultDescription: "fs",
63
+ desc: "Tile container",
69
64
  },
70
65
  depth: {
71
66
  choices: constants.DEPTH,
72
- defaultDescription: 'auto',
73
- desc: 'Pyramid depth'
67
+ defaultDescription: "auto",
68
+ desc: "Pyramid depth",
74
69
  },
75
70
  id: {
76
- defaultDescription: 'https://example.com/iiif',
77
- desc: 'Set the @id/id attribute of info.json',
78
- type: 'string'
71
+ defaultDescription: "https://example.com/iiif",
72
+ desc: "Set the @id/id attribute of info.json",
73
+ type: "string",
79
74
  },
80
75
  layout: {
81
76
  choices: constants.LAYOUT,
82
- defaultDescription: 'dz',
83
- desc: 'Filesystem layout'
77
+ defaultDescription: "dz",
78
+ desc: "Filesystem layout",
84
79
  },
85
80
  overlap: {
86
- desc: 'Tile overlap in pixels',
87
- defaultDescription: '0',
88
- type: 'number'
81
+ desc: "Tile overlap in pixels",
82
+ defaultDescription: "0",
83
+ nargs: 1,
84
+ type: "number",
89
85
  },
90
86
  skipBlanks: {
91
87
  defaultDescription: -1,
92
- desc: 'Threshold to skip tile generation',
93
- type: 'number'
94
- }
95
- }
96
- const optionNames = Object.keys(options)
88
+ desc: "Threshold to skip tile generation",
89
+ nargs: 1,
90
+ type: "number",
91
+ },
92
+ };
93
+ const optionNames = Object.keys(options);
97
94
 
98
95
  // Command builder.
99
96
  const builder = (yargs) => {
100
97
  return yargs
101
98
  .strict()
102
- .example('$0 tile 512', 'output.dz is the Deep Zoom XML definition, output_files contains 512×512 tiles grouped by zoom level')
103
- .epilog('For more information on available options, please visit https://sharp.pixelplumbing.com/api-output#tile')
104
- .positional('size', positionals.size)
99
+ .example(
100
+ "$0 tile 512",
101
+ "output.dz is the Deep Zoom XML definition, output_files contains 512×512 tiles grouped by zoom level",
102
+ )
103
+ .epilog(
104
+ "For more information on available options, please visit https://sharp.pixelplumbing.com/api-output#tile",
105
+ )
106
+ .positional("size", positionals.size)
105
107
  .options(options)
106
- .group(optionNames, 'Command Options')
107
- }
108
+ .group(optionNames, "Command Options");
109
+ };
108
110
 
109
111
  // Command handler.
110
112
  const handler = (args) => {
111
- return queue.push(['tile', (sharp) => {
112
- return sharp.tile({
113
- size: args.size,
114
- ...pick(args, optionNames)
115
- })
116
- }])
117
- }
113
+ return args["#queue"].push([
114
+ "tile",
115
+ (sharp) => {
116
+ return sharp.tile({
117
+ size: args.size,
118
+ ...pick(args, optionNames),
119
+ });
120
+ },
121
+ ]);
122
+ };
118
123
 
119
124
  // Exports.
120
- module.exports = {
121
- command: 'tile [size]',
122
- describe: 'Use tile-based deep zoom (image pyramid) output',
125
+ export default {
126
+ command: "tile [size]",
127
+ describe: "Use tile-based deep zoom (image pyramid) output",
123
128
  builder,
124
- handler
125
- }
129
+ handler,
130
+ };
@@ -21,82 +21,88 @@
21
21
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
23
 
24
- // @see https://sharp.dimens.io/api-resize#extend
25
-
26
- // Strict mode.
27
- 'use strict'
28
-
29
- // Package modules.
30
- const pick = require('lodash.pick')
24
+ // @see https://sharp.pixelplumbing.com/api-resize#extend
31
25
 
32
26
  // Local modules.
33
- const constants = require('../../lib/constants')
34
- const queue = require('../../lib/queue')
27
+ import constants from "../../lib/constants.js";
28
+ import { pick } from "../../lib/utils.js";
35
29
 
36
30
  // Configure.
37
31
  const positionals = {
38
32
  bottom: {
39
- desc: 'Pixel count to add to the bottom edge',
40
- type: 'number'
33
+ desc: "Pixel count to add to the bottom edge",
34
+ type: "number",
41
35
  },
42
36
  left: {
43
- desc: 'Pixel count to add to the left edge',
44
- type: 'number'
37
+ desc: "Pixel count to add to the left edge",
38
+ type: "number",
45
39
  },
46
40
  right: {
47
- desc: 'Pixel count to add to the right edge',
48
- type: 'number'
41
+ desc: "Pixel count to add to the right edge",
42
+ type: "number",
49
43
  },
50
44
  top: {
51
- desc: 'Pixel count to add to the top edge',
52
- type: 'number'
53
- }
54
- }
45
+ desc: "Pixel count to add to the top edge",
46
+ type: "number",
47
+ },
48
+ };
55
49
 
56
50
  const options = {
57
51
  background: {
58
- defaultDescription: 'rgba(0, 0, 0, 1)',
59
- desc: 'Background colour, parsed by the color module',
60
- type: 'string'
52
+ defaultDescription: "rgba(0, 0, 0, 1)",
53
+ desc: "Background colour, parsed by the color module",
54
+ type: "string",
61
55
  },
62
56
  extendWith: {
63
57
  choices: constants.EXTEND_WITH,
64
- default: 'background',
65
- desc: 'Populate new pixels using this method'
66
- }
67
- }
58
+ default: "background",
59
+ desc: "Populate new pixels using this method",
60
+ },
61
+ };
68
62
 
69
63
  // Command builder.
70
64
  const builder = (yargs) => {
71
- const optionNames = Object.keys(options)
65
+ const optionNames = Object.keys(options);
72
66
  return yargs
73
67
  .strict()
74
- .example('$0 extend 10 20 10 10 --background rgba(0,0,0,0)', 'Add 10 transparent pixels to the top, left, and right edges, and 20 to the bottom edge')
75
- .example('$0 extend 0 10 0 0 --background red', 'Add 10 red pixels to the bottom edge.')
76
- .epilog('For more information on available options, please visit https://sharp.dimens.io/api-resize#extend')
77
- .positional('top', positionals.top)
78
- .positional('bottom', positionals.bottom)
79
- .positional('left', positionals.left)
80
- .positional('right', positionals.right)
68
+ .example(
69
+ "$0 extend 10 20 10 10 --background rgba(0,0,0,0)",
70
+ "Add 10 transparent pixels to the top, left, and right edges, and 20 to the bottom edge",
71
+ )
72
+ .example(
73
+ "$0 extend 0 10 0 0 --background red",
74
+ "Add 10 red pixels to the bottom edge.",
75
+ )
76
+ .epilog(
77
+ "For more information on available options, please visit https://sharp.pixelplumbing.com/api-resize#extend",
78
+ )
79
+ .positional("top", positionals.top)
80
+ .positional("bottom", positionals.bottom)
81
+ .positional("left", positionals.left)
82
+ .positional("right", positionals.right)
81
83
  .options(options)
82
- .group(optionNames, 'Command Options')
83
- }
84
+ .group(optionNames, "Command Options");
85
+ };
84
86
 
85
87
  // Command handler.
86
88
  const handler = (args) => {
87
- return queue.push(['extend', (sharp) => {
88
- return sharp.extend({
89
- background: args.background,
90
- extendWith: args.extendWith,
91
- ...pick(args, Object.keys(positionals))
92
- })
93
- }])
94
- }
89
+ return args["#queue"].push([
90
+ "extend",
91
+ (sharp) => {
92
+ return sharp.extend({
93
+ background: args.background,
94
+ extendWith: args.extendWith,
95
+ ...pick(args, Object.keys(positionals)),
96
+ });
97
+ },
98
+ ]);
99
+ };
95
100
 
96
101
  // Exports.
97
- module.exports = {
98
- command: 'extend <top> <bottom> <left> <right>',
99
- describe: 'Extends/pads the edges of the image with the provided background colour',
102
+ export default {
103
+ command: "extend <top> <bottom> <left> <right>",
104
+ describe:
105
+ "Extends/pads the edges of the image with the provided background colour",
100
106
  builder,
101
- handler
102
- }
107
+ handler,
108
+ };
@@ -21,59 +21,58 @@
21
21
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
23
 
24
- // @see https://sharp.dimens.io/api-resize#extract
25
-
26
- // Strict mode.
27
- 'use strict'
28
-
29
- // Package modules.
30
- const pick = require('lodash.pick')
24
+ // @see https://sharp.pixelplumbing.com/api-resize#extract
31
25
 
32
26
  // Local modules.
33
- const queue = require('../../lib/queue')
27
+ import { pick } from "../../lib/utils.js";
34
28
 
35
29
  // Configure.
36
30
  const positionals = {
37
31
  height: {
38
- desc: 'Height of region to extract',
39
- type: 'number'
32
+ desc: "Height of region to extract",
33
+ type: "number",
40
34
  },
41
35
  left: {
42
- desc: 'Zero-indexed offset from left edge',
43
- type: 'number'
36
+ desc: "Zero-indexed offset from left edge",
37
+ type: "number",
44
38
  },
45
39
  top: {
46
- desc: 'Zero-indexed offset from top edge',
47
- type: 'number'
40
+ desc: "Zero-indexed offset from top edge",
41
+ type: "number",
48
42
  },
49
43
  width: {
50
- desc: 'Width of region to extract',
51
- type: 'number'
52
- }
53
- }
44
+ desc: "Width of region to extract",
45
+ type: "number",
46
+ },
47
+ };
54
48
 
55
49
  // Command builder.
56
50
  const builder = (yargs) => {
57
51
  return yargs
58
52
  .strict()
59
- .epilog('For more information on available options, please visit https://sharp.dimens.io/api-resize#extract')
60
- .positional('top', positionals.top)
61
- .positional('left', positionals.left)
62
- .positional('width', positionals.width)
63
- .positional('height', positionals.height)
64
- }
53
+ .epilog(
54
+ "For more information on available options, please visit https://sharp.pixelplumbing.com/api-resize#extract",
55
+ )
56
+ .positional("top", positionals.top)
57
+ .positional("left", positionals.left)
58
+ .positional("width", positionals.width)
59
+ .positional("height", positionals.height);
60
+ };
65
61
 
66
62
  // Command handler.
67
63
  const handler = (args) => {
68
- return queue.push(['extract', (sharp) => {
69
- return sharp.extract(pick(args, Object.keys(positionals)))
70
- }])
71
- }
64
+ return args["#queue"].push([
65
+ "extract",
66
+ (sharp) => {
67
+ return sharp.extract(pick(args, Object.keys(positionals)));
68
+ },
69
+ ]);
70
+ };
72
71
 
73
72
  // Exports.
74
- module.exports = {
75
- command: 'extract <top> <left> <width> <height>',
76
- describe: 'Extract a region of the image',
73
+ export default {
74
+ command: "extract <top> <left> <width> <height>",
75
+ describe: "Extract a region of the image",
77
76
  builder,
78
- handler
79
- }
77
+ handler,
78
+ };